| 1 24 25 package org.objectweb.cjdbc.driver; 26 27 import java.io.ByteArrayInputStream ; 28 import java.io.ByteArrayOutputStream ; 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.io.ObjectInputStream ; 32 import java.io.ObjectOutputStream ; 33 import java.io.Serializable ; 34 import java.math.BigDecimal ; 35 import java.net.MalformedURLException ; 36 import java.net.URL ; 37 import java.sql.Array ; 38 import java.sql.BatchUpdateException ; 39 import java.sql.Date ; 40 import java.sql.ParameterMetaData ; 41 import java.sql.Ref ; 42 import java.sql.SQLException ; 43 import java.sql.Time ; 44 import java.sql.Timestamp ; 45 import java.sql.Types ; 46 import java.text.ParseException ; 47 import java.text.SimpleDateFormat ; 48 import java.util.ArrayList ; 49 import java.util.Vector ; 50 51 import org.objectweb.cjdbc.common.exceptions.NotImplementedException; 52 import org.objectweb.cjdbc.common.sql.filters.HexaBlobFilter; 53 import org.objectweb.cjdbc.common.util.Strings; 54 55 82 public class PreparedStatement extends Statement 83 implements 84 java.sql.PreparedStatement  85 { 86 87 88 92 93 public static final String BYTE_TAG = "b|"; 94 95 public static final String BYTES_TAG = "B|"; 96 97 public static final String BLOB_TAG = "c|"; 98 99 public static final String CLOB_TAG = "C|"; 100 101 public static final String BOOLEAN_TAG = "0|"; 102 103 public static final String BIG_DECIMAL_TAG = "1|"; 104 105 public static final String DATE_TAG = "d|"; 106 107 public static final String DOUBLE_TAG = "D|"; 108 109 public static final String FLOAT_TAG = "F|"; 110 111 public static final String INTEGER_TAG = "I|"; 112 113 public static final String LONG_TAG = "L|"; 114 115 public static final String NULL_TAG = "N|"; 116 117 public static final String NULL_STRING_TAG = "n|"; 118 119 public static final String OBJECT_TAG = "O|"; 120 121 public static final String REF_TAG = "R|"; 122 123 public static final String SHORT_TAG = "s|"; 124 125 public static final String STRING_TAG = "S|"; 126 127 public static final String TIME_TAG = "t|"; 128 129 public static final String TIMESTAMP_TAG = "T|"; 130 131 public static final String URL_TAG = "U|"; 132 133 134 public static final String TAG_MARKER = "!%"; 135 136 public static final String TAG_MARKER_ESCAPE = TAG_MARKER + ";"; 137 138 public static final String START_PARAM_TAG = "<" + TAG_MARKER; 139 140 public static final String END_PARAM_TAG = "|" + TAG_MARKER + ">"; 141 142 143 protected String sql; 144 145 private String [] inStrings; 146 147 private String [] templateStrings; 148 149 private StringBuffer sbuf = new StringBuffer (); 151 152 162 public PreparedStatement(Connection connection, String sqlStatement) 163 throws SQLException  164 { 165 super(connection); 166 167 168 ArrayList segs = new ArrayList (); 169 int lastParmEnd = 0; 170 171 177 boolean inString = false; 178 boolean inMetaString = false; 179 180 this.sql = sqlStatement.trim(); 181 this.connection = connection; 182 for (int i = 0; i < sql.length(); ++i) 183 { 184 if (sql.charAt(i) == '\'') 185 inString = !inString; 186 if (sql.charAt(i) == '"') 187 inMetaString = !inMetaString; 188 if ((sql.charAt(i) == '?') && (!(inString || inMetaString))) 189 { 190 segs.add(sql.substring(lastParmEnd, i)); 191 lastParmEnd = i + 1; 192 } 193 } 194 segs.add(sql.substring(lastParmEnd, sql.length())); 195 196 int size = segs.size(); 197 templateStrings = new String [size]; 198 inStrings = new String [size - 1]; 199 clearParameters(); 200 201 for (int i = 0; i < size; ++i) 202 templateStrings[i] = (String ) segs.get(i); 203 } 204 205 210 public void close() throws SQLException  211 { 212 sql = null; 213 templateStrings = null; 214 inStrings = null; 215 216 super.close(); 217 } 218 219 227 public java.sql.ResultSet executeQuery() throws SQLException  228 { 229 return super.executeQuery(sql, compileQuery()); } 231 232 241 public int executeUpdate() throws SQLException  242 { 243 return super.executeUpdateWithSkeleton(sql, compileQuery()); 244 } 246 247 255 protected synchronized String compileQuery() throws SQLException  256 { 257 sbuf.setLength(0); 258 int i; 259 260 for (i = 0; i < inStrings.length; ++i) 261 { 262 if (inStrings[i] == null) 263 throw new SQLException ("Parameter " + (i + 1) + " is incorrect"); 264 sbuf.append(templateStrings[i]).append(inStrings[i]); 265 } 266 sbuf.append(templateStrings[inStrings.length]); 267 return sbuf.toString(); 268 } 269 270 280 protected String doEscapeProcessing(String x) 281 { 282 synchronized (sbuf) 285 { 286 sbuf.setLength(0); 287 int i; 288 sbuf.append(connection.getEscapeChar()); 289 for (i = 0; i < x.length(); ++i) 290 { 291 char c = x.charAt(i); 292 if ((c == '\'' && connection.isEscapeSingleQuote()) 293 || (c == '\\' && connection.isEscapeBackslash())) 294 sbuf.append(c); 295 sbuf.append(c); 296 } 297 sbuf.append(connection.getEscapeChar()); 298 } 299 return sbuf.toString(); 300 } 301 302 311 public void setNull(int parameterIndex, int sqlType) throws SQLException  312 { 313 if (connection.isDriverProcessed()) 314 set(parameterIndex, "null"); 315 else 316 setWithTag(parameterIndex, NULL_TAG, String.valueOf(sqlType)); 317 } 318 319 327 public void setBoolean(int parameterIndex, boolean x) throws SQLException  328 { 329 if (connection.isDriverProcessed()) 330 { 331 set(parameterIndex, x 332 ? connection.getPreparedStatementBooleanTrue() 333 : connection.getPreparedStatementBooleanFalse()); 334 } 335 else 336 { 337 setWithTag(parameterIndex, BOOLEAN_TAG, String.valueOf(x)); 338 } 339 } 340 341 348 public void setByte(int parameterIndex, byte x) throws SQLException  349 { 350 if (connection.isDriverProcessed()) 351 { 352 set(parameterIndex, Integer.toString(x)); 353 } 354 else 355 { 356 setWithTag(parameterIndex, BYTE_TAG, Integer.toString(x)); 357 } 358 } 359 360 368 public void setShort(int parameterIndex, short x) throws SQLException  369 { 370 if (connection.isDriverProcessed()) 371 { 372 set(parameterIndex, Integer.toString(x)); 373 } 374 else 375 { 376 setWithTag(parameterIndex, SHORT_TAG, Integer.toString(x)); 377 } 378 } 379 380 388 public void setInt(int parameterIndex, int x) throws SQLException  389 { 390 if (connection.isDriverProcessed()) 391 { 392 set(parameterIndex, Integer.toString(x)); 393 } 394 else 395 { 396 setWithTag(parameterIndex, INTEGER_TAG, Integer.toString(x)); 397 } 398 } 399 400 408 public void setLong(int parameterIndex, long x) throws SQLException  409 { 410 if (connection.isDriverProcessed()) 411 { 412 set(parameterIndex, Long.toString(x)); 413 } 414 else 415 { 416 setWithTag(parameterIndex, LONG_TAG, Long.toString(x)); 417 } 418 } 419 420 428 public void setFloat(int parameterIndex, float x) throws SQLException  429 { 430 if (connection.isDriverProcessed()) 431 { 432 set(parameterIndex, Float.toString(x)); 433 } 434 else 435 { 436 setWithTag(parameterIndex, FLOAT_TAG, Float.toString(x)); 437 } 438 } 439 440 448 public void setDouble(int parameterIndex, double x) throws SQLException  449 { 450 if (connection.isDriverProcessed()) 451 { 452 set(parameterIndex, Double.toString(x)); 453 } 454 else 455 { 456 setWithTag(parameterIndex, DOUBLE_TAG, Double.toString(x)); 457 } 458 } 459 460 468 public void setBigDecimal(int parameterIndex, BigDecimal x) 469 throws SQLException  470 { 471 if (connection.isDriverProcessed()) 472 { 473 if (x == null) 474 setNull(parameterIndex, Types.DECIMAL); 475 else 476 set(parameterIndex, x.toString()); 477 } 478 else 479 { 480 if (x == null) 481 setWithTag(parameterIndex, BIG_DECIMAL_TAG, NULL_TAG); 482 else 483 setWithTag(parameterIndex, BIG_DECIMAL_TAG, x.toString()); 484 } 485 } 486 487 496 public void setString(int parameterIndex, String x) throws SQLException  497 { 498 if (connection.isDriverProcessed()) 499 { 500 if (x == null) 501 setNull(parameterIndex, Types.VARCHAR); 503 else 504 { 505 if (escapeProcessing 506 && (connection.isEscapeBackslash() || connection 507 .isEscapeSingleQuote())) 508 set(parameterIndex, doEscapeProcessing(x)); 509 else 510 set(parameterIndex, x); 512 } 513 } 514 else 515 { 516 if (x == null) 517 setWithTag(parameterIndex, STRING_TAG, NULL_TAG); 518 else 519 { 520 if (NULL_TAG.equals(x)) 521 { setWithTag(parameterIndex, NULL_STRING_TAG, x); 524 } 525 else 526 { setWithTag(parameterIndex, STRING_TAG, x); 529 } 530 } 531 } 532 } 533 534 542 public void setBytes(int parameterIndex, byte[] x) throws SQLException  543 { 544 String blob; 545 try 546 { 547 synchronized (sbuf) 548 { 549 if (connection.isDriverProcessed()) 550 { 551 552 blob = connection.getBlobFilter().encode(x); 553 sbuf.setLength(0); 554 sbuf.append(connection.escapeChar); 555 sbuf.append(blob); 556 sbuf.append(connection.escapeChar); 557 set(parameterIndex, sbuf.toString()); 558 } 559 else 560 { 561 566 blob = new HexaBlobFilter().encode(x); 567 setWithTag(parameterIndex, BYTES_TAG, blob); 568 } 569 } 570 } 571 catch (OutOfMemoryError oome) 572 { 573 blob = null; 574 sbuf = null; 575 System.gc(); 576 throw new SQLException ("Out of memory"); 577 } 578 } 579 580 588 public void setDate(int parameterIndex, java.sql.Date x) throws SQLException  589 { 590 if (connection.isDriverProcessed()) 591 { 592 if (x == null) 593 setNull(parameterIndex, Types.DATE); 594 else 595 set(parameterIndex, "'" + new java.sql.Date (x.getTime()).toString() 596 + "'"); 597 } 598 else 599 { 600 if (x == null) 601 setWithTag(parameterIndex, DATE_TAG, NULL_TAG); 602 else 603 setWithTag(parameterIndex, DATE_TAG, new java.sql.Date (x.getTime()) 604 .toString()); 605 } 606 } 607 608 616 public void setTime(int parameterIndex, Time x) throws SQLException  617 { 618 if (connection.isDriverProcessed()) 619 { 620 if (x == null) 621 setNull(parameterIndex, Types.TIME); 622 else 623 set(parameterIndex, "{t '" + x.toString() + "'}"); 624 } 625 else 626 { 627 if (x == null) 628 setWithTag(parameterIndex, TIME_TAG, NULL_TAG); 629 else 630 setWithTag(parameterIndex, TIME_TAG, x.toString()); 631 } 632 } 633 634 642 public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException  643 { 644 if (connection.isDriverProcessed()) 645 { 646 if (x == null) 647 setNull(parameterIndex, Types.TIMESTAMP); 648 else 649 { 650 if (x.getClass().equals(Timestamp .class)) 653 set(parameterIndex, "'" + x.toString() + "'"); 654 else 655 set(parameterIndex, "'" + new Timestamp (x.getTime()).toString() + "'"); 656 } 657 } 658 else 659 { 660 if (x == null) 661 setWithTag(parameterIndex, TIMESTAMP_TAG, NULL_TAG); 662 else 663 { 664 if (x.getClass().equals(Timestamp .class)) 665 setWithTag(parameterIndex, TIMESTAMP_TAG, x.toString()); 666 else 667 setWithTag(parameterIndex, TIMESTAMP_TAG, new Timestamp (x.getTime()) 668 .toString()); 669 } 670 } 671 } 672 673 688 public void setAsciiStream(int parameterIndex, InputStream x, int length) 689 throws SQLException  690 { 691 setBinaryStream(parameterIndex, x, length); 692 } 693 694 711 public void setUnicodeStream(int parameterIndex, InputStream x, int length) 712 throws SQLException  713 { 714 setBinaryStream(parameterIndex, x, length); 715 } 716 717 734 public void setBinaryStream(int parameterIndex, InputStream inStreamArg, 735 int length) throws SQLException  736 { 737 byte[] data = new byte[length]; 738 try 739 { 740 inStreamArg.read(data, 0, length); 741 } 742 catch (Exception ioe) 743 { 744 throw new SQLException ("Problem with streaming of data"); 745 } 746 setBytes(parameterIndex, data); 747 } 748 749 758 public void clearParameters() throws SQLException  759 { 760 int i; 761 762 for (i = 0; i < inStrings.length; i++) 763 inStrings[i] = null; 764 } 765 766 788 public void setObject(int parameterIndex, Object x, int targetSqlType, 789 int scale) throws SQLException  790 { 791 if (x == null) 792 { 793 setNull(parameterIndex, targetSqlType); 794 return; 795 } 796 797 try 798 { 799 boolean failed = false; 800 switch (targetSqlType) 801 { 802 808 case Types.TINYINT : 810 case Types.SMALLINT : 811 case Types.INTEGER : 812 if (x instanceof Number ) 813 setInt(parameterIndex, ((Number ) x).intValue()); 814 else if (x instanceof Boolean ) 815 setInt(parameterIndex, ((Boolean ) x).booleanValue() ? 1 : 0); 816 else if (x instanceof String ) 817 setInt(parameterIndex, Integer.parseInt((String ) x)); 818 else 819 failed = true; 820 break; 821 case Types.BIGINT : 822 if (x instanceof Number ) 823 setLong(parameterIndex, ((Number ) x).longValue()); 824 else if (x instanceof String ) 825 setLong(parameterIndex, Long.parseLong((String ) x)); 826 else if (x instanceof Boolean ) 827 setLong(parameterIndex, ((Boolean ) x).booleanValue() ? 1 : 0); 828 else 829 failed = true; 830 break; 831 case Types.REAL : 832 case Types.FLOAT : 833 case Types.DOUBLE : 834 case Types.DECIMAL : 835 case Types.NUMERIC : 836 if (connection.isDriverProcessed()) 839 set(parameterIndex, x.toString()); 840 else 841 setWithTag(parameterIndex, STRING_TAG, x.toString()); 842 break; 843 case Types.BIT : 844 case Types.BOOLEAN : 845 if (x instanceof Number ) 846 setBoolean(parameterIndex, 0 != ((Number ) x).longValue()); 847 else if (x instanceof Boolean ) 848 setBoolean(parameterIndex, ((Boolean ) x).booleanValue()); 849 else if (x instanceof String ) 850 setBoolean(parameterIndex, Boolean.valueOf((String ) x) 851 .booleanValue()); 852 else 853 failed = true; 854 break; 855 case Types.CHAR : 856 case Types.VARCHAR : 857 case Types.LONGVARCHAR : 858 setString(parameterIndex, x.toString()); 859 break; 860 case Types.BINARY : 861 case Types.VARBINARY : 862 case Types.LONGVARBINARY : 863 if (x instanceof byte[]) 864 setBytes(parameterIndex, (byte[]) x); 865 else if (x instanceof Blob) 866 setBlob(parameterIndex, (Blob) x); 867 else if (x instanceof Serializable ) 868 setObject(parameterIndex, x); 870 else 871 failed = true; 872 break; 873 case Types.DATE : 874 if (x instanceof String ) 875 setDate(parameterIndex, java.sql.Date.valueOf((String ) x)); 876 else if (x instanceof java.sql.Date ) 877 setDate(parameterIndex, (java.sql.Date ) x); 878 else if (x instanceof Timestamp ) 879 setDate(parameterIndex, 880 new java.sql.Date (((Timestamp ) x).getTime())); 881 else 882 failed = true; 883 break; 884 case Types.TIME : 885 if (x instanceof String ) 886 setTime(parameterIndex, Time.valueOf((String ) x)); 887 else if (x instanceof Time ) 888 setTime(parameterIndex, (Time ) x); 889 else if (x instanceof Timestamp ) 890 setTime(parameterIndex, new Time (((Timestamp ) x).getTime())); 891 else 892 failed = true; 893 break; 894 case |