| 1 19 package com.mysql.jdbc; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.ByteArrayOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.ObjectOutputStream ; 26 import java.io.Reader ; 27 import java.io.StringReader ; 28 import java.io.UnsupportedEncodingException ; 29 30 import java.math.BigDecimal ; 31 32 import java.net.URL ; 33 34 import java.sql.Array ; 35 import java.sql.Clob ; 36 import java.sql.ParameterMetaData ; 37 import java.sql.Ref ; 38 import java.sql.SQLException ; 39 import java.sql.Time ; 40 import java.sql.Timestamp ; 41 import java.sql.Types ; 42 43 import java.text.ParsePosition ; 44 import java.text.SimpleDateFormat ; 45 46 import java.util.ArrayList ; 47 import java.util.Calendar ; 48 import java.util.TimeZone ; 49 50 51 74 public class PreparedStatement extends com.mysql.jdbc.Statement 75 implements java.sql.PreparedStatement { 76 private java.sql.DatabaseMetaData dbmd = null; 77 private ParseInfo parseInfo; 78 private java.sql.ResultSetMetaData pstmtResultMetaData; 79 private SimpleDateFormat tsdf = null; 80 private String originalSql = null; 81 private boolean[] isNull = null; 82 private boolean[] isStream = null; 83 private InputStream [] parameterStreams = null; 84 private byte[][] parameterValues = null; 85 private byte[][] staticSqlStrings = null; 86 private byte[] streamConvertBuf = new byte[4096]; 87 private int[] streamLengths = null; 88 private boolean hasLimitClause = false; 89 private boolean isLoadDataQuery = false; 90 private boolean retrieveGeneratedKeys = false; 91 private boolean useTrueBoolean = false; 92 private char firstCharOfStmt = 0; 93 94 104 public PreparedStatement(Connection conn, String sql, String catalog) 105 throws SQLException { 106 super(conn, catalog); 107 108 if (sql == null) { 109 throw new SQLException ("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 110 } 111 112 originalSql = sql; 113 114 this.dbmd = this.connection.getMetaData(); 115 116 useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23); 117 118 this.parseInfo = new ParseInfo(sql, this.connection, this.dbmd, 119 this.charEncoding, this.charConverter); 120 121 initializeFromParseInfo(); 122 } 123 124 135 public PreparedStatement(Connection conn, String sql, String catalog, 136 ParseInfo cachedParseInfo) throws SQLException { 137 super(conn, catalog); 138 139 if (sql == null) { 140 throw new SQLException ("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 141 } 142 143 originalSql = sql; 144 145 this.dbmd = this.connection.getMetaData(); 146 147 useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23); 148 149 this.parseInfo = cachedParseInfo; 150 151 initializeFromParseInfo(); 152 } 153 154 163 public void setArray(int i, Array x) throws SQLException { 164 throw new NotImplemented(); 165 } 166 167 185 public synchronized void setAsciiStream(int parameterIndex, InputStream x, 186 int length) throws SQLException { 187 if (x == null) { 188 setNull(parameterIndex, java.sql.Types.VARCHAR); 189 } else { 190 setBinaryStream(parameterIndex, x, length); 191 } 192 } 193 194 203 public void setBigDecimal(int parameterIndex, BigDecimal x) 204 throws SQLException { 205 if (x == null) { 206 setNull(parameterIndex, java.sql.Types.DECIMAL); 207 } else { 208 setInternal(parameterIndex, fixDecimalExponent(x.toString())); 209 } 210 } 211 212 229 public void setBinaryStream(int parameterIndex, InputStream x, int length) 230 throws SQLException { 231 if (x == null) { 232 setNull(parameterIndex, java.sql.Types.BINARY); 233 } else { 234 if ((parameterIndex < 1) 235 || (parameterIndex > staticSqlStrings.length)) { 236 throw new java.sql.SQLException ( 237 "Parameter index out of range (" + parameterIndex + " > " 238 + staticSqlStrings.length + ")", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 239 } 240 241 parameterStreams[parameterIndex - 1] = x; 242 isStream[parameterIndex - 1] = true; 243 streamLengths[parameterIndex - 1] = length; 244 isNull[parameterIndex - 1] = false; 245 } 246 } 247 248 256 public void setBlob(int i, java.sql.Blob x) throws SQLException { 257 setBinaryStream(i, x.getBinaryStream(), (int) x.length()); 258 } 259 260 269 public void setBoolean(int parameterIndex, boolean x) 270 throws SQLException { 271 if (useTrueBoolean) { 272 setInternal(parameterIndex, x ? "'1'" : "'0'"); 273 } else { 274 setInternal(parameterIndex, x ? "'t'" : "'f'"); 275 } 276 } 277 278 287 public void setByte(int parameterIndex, byte x) throws SQLException { 288 setInternal(parameterIndex, String.valueOf(x)); 289 } 290 291 302 public void setBytes(int parameterIndex, byte[] x) 303 throws SQLException { 304 if (x == null) { 305 setNull(parameterIndex, java.sql.Types.BINARY); 306 } else { 307 int numBytes = x.length; 309 310 ByteArrayOutputStream bOut = new ByteArrayOutputStream (numBytes); 311 312 bOut.write('\''); 313 314 for (int i = 0; i < numBytes; ++i) { 315 byte b = x[i]; 316 317 switch (b) { 318 case 0: 319 bOut.write('\\'); 320 bOut.write('0'); 321 322 break; 323 324 case '\n': 325 bOut.write('\\'); 326 bOut.write('n'); 327 328 break; 329 330 case '\r': 331 bOut.write('\\'); 332 bOut.write('r'); 333 334 break; 335 336 case '\\': 337 bOut.write('\\'); 338 bOut.write('\\'); 339 340 break; 341 342 case '\'': 343 bOut.write('\\'); 344 bOut.write('\''); 345 346 break; 347 348 case '"': 349 bOut.write('\\'); 350 bOut.write('"'); 351 352 break; 353 354 case '\032': 355 bOut.write('\\'); 356 bOut.write('Z'); 357 358 break; 359 360 default: 361 bOut.write(b); 362 } 363 } 364 365 bOut.write('\''); 366 367 setInternal(parameterIndex, bOut.toByteArray()); 368 } 369 } 370 371 389 public void setCharacterStream(int parameterIndex, java.io.Reader reader, 390 int length) throws SQLException { 391 try { 392 if (reader == null) { 393 setNull(parameterIndex, Types.LONGVARCHAR); 394 } else { 395 char[] c = null; 396 int len = 0; 397 398 boolean useLength = this.connection.useStreamLengthsInPrepStmts(); 399 400 if (useLength && (length != -1)) { 401 c = new char[length]; 402 403 int numCharsRead = readFully(reader, c, length); 405 setString(parameterIndex, new String (c, 0, numCharsRead)); 406 } else { 407 c = new char[4096]; 408 409 StringBuffer buf = new StringBuffer (); 410 411 while ((len = reader.read(c)) != -1) { 412 buf.append(c, 0, len); 413 } 414 415 setString(parameterIndex, buf.toString()); 416 } 417 } 418 } catch (java.io.IOException ioEx) { 419 throw new SQLException (ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR); 420 } 421 } 422 423 431 public void setClob(int i, Clob x) throws SQLException { 432 setString(i, x.getSubString(1L, (int) x.length())); 433 } 434 435 444 public void setDate(int parameterIndex, java.sql.Date x) 445 throws SQLException { 446 if (x == null) { 447 setNull(parameterIndex, java.sql.Types.DATE); 448 } else { 449 SimpleDateFormat dateFormatter = new SimpleDateFormat ( 452 "''yyyy-MM-dd''"); 453 setInternal(parameterIndex, dateFormatter.format(x)); 454 } 455 } 456 457 467 public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) 468 throws SQLException { 469 setDate(parameterIndex, x); 470 } 471 472 481 public void setDouble(int parameterIndex, double x) 482 throws SQLException { 483 setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x))); 484 } 485 486 495 public void setFloat(int parameterIndex, float x) throws SQLException { 496 setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x))); 497 } 498 499 508 public void setInt(int parameterIndex, int x) throws SQLException { 509 setInternal(parameterIndex, String.valueOf(x)); 510 } 511 512 521 public void setLong(int parameterIndex, long x) throws SQLException { 522 setInternal(parameterIndex, String.valueOf(x)); 523 } 524 525 533 public synchronized java.sql.ResultSetMetaData getMetaData() throws SQLException { 534 PreparedStatement mdStmt = null; 535 java.sql.ResultSet mdRs = null; 536 537 if (this.pstmtResultMetaData == null) { 538 try { 539 mdStmt = new PreparedStatement(this.connection, 540 this.originalSql, this.currentCatalog, this.parseInfo); 541 542 mdStmt.setMaxRows(0); 543 544 int paramCount = this.parameterValues.length; 545 546 for (int i = 1; i <= paramCount; i++) { 547 mdStmt.setString(i, ""); 548 } 549 550 boolean hadResults = mdStmt.execute(); 551 552 if (hadResults) { 553 mdRs = mdStmt.getResultSet(); 554 555 this.pstmtResultMetaData = mdRs.getMetaData(); 556 } else { 557 this.pstmtResultMetaData = new ResultSetMetaData(new Field[0]); 558 } 559 } finally { 560 SQLException sqlExRethrow = null; 561 562 if (mdRs != null) { 563 try { 564 mdRs.close(); 565 } catch (SQLException sqlEx) { 566 sqlExRethrow = sqlEx; 567 } 568 569 mdRs = null; 570 } 571 572 if (mdStmt != null) { 573 try { 574 mdStmt.close(); 575 } catch (SQLException sqlEx) { 576 sqlExRethrow = sqlEx; 577 } 578 579 mdStmt = null; 580 } 581 582 if (sqlExRethrow != null) { 583 throw sqlExRethrow; 584 } 585 } 586 } 587 588 return this.pstmtResultMetaData; 589 } 590 591 604 public void setNull(int parameterIndex, int sqlType) 605 throws SQLException { 606 setInternal(parameterIndex, "null"); 607 isNull[parameterIndex - 1] = true; 608 } 609 610 612 625 public void setNull(int parameterIndex, int sqlType, String arg) 626 throws SQLException { 627 setNull(parameterIndex, sqlType); 628 } 629 630 655 public void setObject(int parameterIndex, Object parameterObj, 656 int targetSqlType, int scale) throws SQLException { 657 if (parameterObj == null) { 658 setNull(parameterIndex, java.sql.Types.OTHER); 659 } else { 660 try { 661 switch (targetSqlType) { 662 case Types.BIT: 663 case Types.TINYINT: 664 case Types.SMALLINT: 665 case Types.INTEGER: 666 case Types.BIGINT: 667 case Types.REAL: 668 case Types.FLOAT: 669 case Types.DOUBLE: 670 case Types.DECIMAL: 671 case Types.NUMERIC: 672 673 Number parameterAsNum; 674 675 if (parameterObj instanceof Boolean ) { 676 parameterAsNum = ((Boolean ) parameterObj).booleanValue() 677 ? new Integer (1) : new Integer (0); 678 } else if (parameterObj instanceof String ) { 679 switch (targetSqlType) { 680 case Types.BIT: 681 parameterAsNum = (Boolean.getBoolean((String ) parameterObj) 682 ? new Integer ("1") : new Integer ("0")); 683 684 break; 685 686 case Types.TINYINT: 687 case Types.SMALLINT: 688 case Types.INTEGER: 689 parameterAsNum = Integer.valueOf((String ) parameterObj); 690 691 break; 692 693 case Types.BIGINT: 694 parameterAsNum = Long.valueOf((String ) parameterObj); 695 696 break; 697 698 case Types.REAL: 699 parameterAsNum = Float.valueOf((String ) parameterObj); 700 701 break; 702 703 case Types.FLOAT: 704 case Types.DOUBLE: 705 parameterAsNum = Double.valueOf((String ) parameterObj); 706 707 break; 708 709 case Types.DECIMAL: 710 case Types.NUMERIC:default: 711 parameterAsNum = new java.math.BigDecimal ((String ) parameterObj); 712 } 713 } else { 714 parameterAsNum = (Number ) parameterObj; 715 } 716 717 switch (targetSqlType) { 718 case Types.BIT: 719 case Types.TINYINT: 720 case Types.SMALLINT: 721 case Types.INTEGER: 722 setInt(parameterIndex, parameterAsNum.intValue()); 723 724 break; 725 726 case Types.BIGINT: 727 setLong(parameterIndex, parameterAsNum.longValue()); 728 729 break; 730 731 case Types.REAL: 732 setFloat(parameterIndex, parameterAsNum.floatValue()); 733 734 break; 735 736 case Types.FLOAT: 737 case Types.DOUBLE: 738 setDouble(parameterIndex, parameterAsNum.doubleValue()); 739 740 break; 741 742 case Types.DECIMAL: 743 case Types.NUMERIC:default: 744 745 if (parameterAsNum instanceof java.math.BigDecimal ) { 746 setBigDecimal(parameterIndex, 747 (java.math.BigDecimal ) parameterAsNum); 748 } else if (parameterAsNum instanceof java.math.BigInteger ) { 749 setBigDecimal(parameterIndex, 750 new java.math.BigDecimal ( 751 (java.math.BigInteger ) parameterAsNum, scale)); 752 } else { 753 setBigDecimal(parameterIndex, 754 new java.math.BigDecimal ( 755 parameterAsNum.doubleValue())); 756 } 757 758 break; 759 } 760 761 break; 762 763 case Types.CHAR: 764 case Types.VARCHAR: 765 case Types.LONGVARCHAR: 766 setString(parameterIndex, parameterObj.toString()); 767 768 break; 769 770 case Types.CLOB: 771 772 if (parameterObj instanceof java.sql.Clob ) { 773 setClob(parameterIndex, (java.sql.Clob ) parameterObj); 774 } else { 775 setString(parameterIndex, parameterObj.toString()); 776 } 777 778 break; 779 780 case Types.BINARY: 781 case Types.VARBINARY: 782 case Types.LONGVARBINARY: 783 case Types.BLOB: 784 785 if (parameterObj instanceof byte[]) { 786 setBytes(parameterIndex, (byte[]) parameterObj); 787 } else if (parameterObj instanceof java.sql.Blob ) { 788 setBlob(parameterIndex, (java.sql.Blob ) parameterObj); 789 } else { 790 setBytes(parameterIndex, 791 StringUtils.getBytes(parameterObj.toString(), 792 this.charConverter, this.charEncoding)); 793 } 794 795 break; 796 797 case Types.DATE: 798 case Types.TIMESTAMP: 799 800 java.util.Date parameterAsDate; 801 802 if (parameterObj instanceof String  |