1 25 package com.mysql.jdbc; 26 27 import com.mysql.jdbc.profiler.ProfileEventSink; 28 import com.mysql.jdbc.profiler.ProfilerEvent; 29 30 import java.io.IOException ; 31 import java.io.InputStream ; 32 import java.io.Reader ; 33 import java.io.UnsupportedEncodingException ; 34 35 import java.math.BigDecimal ; 36 37 import java.net.URL ; 38 39 import java.sql.Array ; 40 import java.sql.Blob ; 41 import java.sql.Clob ; 42 import java.sql.Date ; 43 import java.sql.ParameterMetaData ; 44 import java.sql.Ref ; 45 import java.sql.SQLException ; 46 import java.sql.Time ; 47 import java.sql.Types ; 48 49 import java.util.ArrayList ; 50 import java.util.BitSet ; 51 import java.util.Calendar ; 52 import java.util.Locale ; 53 import java.util.TimeZone ; 54 55 62 public class ServerPreparedStatement extends PreparedStatement { 63 static class BatchedBindValues { 64 BindValue[] batchedParameterValues; 65 66 BatchedBindValues(BindValue[] paramVals) { 67 int numParams = paramVals.length; 68 69 this.batchedParameterValues = new BindValue[numParams]; 70 71 for (int i = 0; i < numParams; i++) { 72 this.batchedParameterValues[i] = new BindValue(paramVals[i]); 73 } 74 } 75 } 76 77 static class BindValue { 78 79 long bindLength; 80 81 int bufferType; 82 83 byte byteBinding; 84 85 double doubleBinding; 86 87 float floatBinding; 88 89 int intBinding; 90 91 boolean isLongData; 92 93 boolean isNull; 94 95 boolean isSet = false; 96 97 long longBinding; 98 99 short shortBinding; 100 101 Object value; 102 103 BindValue() { 104 } 105 106 BindValue(BindValue copyMe) { 107 this.value = copyMe.value; 108 this.isSet = copyMe.isSet; 109 this.isLongData = copyMe.isLongData; 110 this.isNull = copyMe.isNull; 111 this.bufferType = copyMe.bufferType; 112 this.bindLength = copyMe.bindLength; 113 this.byteBinding = copyMe.byteBinding; 114 this.shortBinding = copyMe.shortBinding; 115 this.intBinding = copyMe.intBinding; 116 this.longBinding = copyMe.longBinding; 117 this.floatBinding = copyMe.floatBinding; 118 this.doubleBinding = copyMe.doubleBinding; 119 } 120 121 void reset() { 122 this.isSet = false; 123 this.value = null; 124 this.isLongData = false; 125 126 this.byteBinding = 0; 127 this.shortBinding = 0; 128 this.intBinding = 0; 129 this.longBinding = 0L; 130 this.floatBinding = 0; 131 this.doubleBinding = 0D; 132 } 133 134 public String toString() { 135 return toString(false); 136 } 137 138 public String toString(boolean quoteIfNeeded) { 139 if (this.isLongData) { 140 return "' STREAM DATA '"; 141 } 142 143 switch (this.bufferType) { 144 case MysqlDefs.FIELD_TYPE_TINY: 145 return String.valueOf(byteBinding); 146 case MysqlDefs.FIELD_TYPE_SHORT: 147 return String.valueOf(shortBinding); 148 case MysqlDefs.FIELD_TYPE_LONG: 149 return String.valueOf(intBinding); 150 case MysqlDefs.FIELD_TYPE_LONGLONG: 151 return String.valueOf(longBinding); 152 case MysqlDefs.FIELD_TYPE_FLOAT: 153 return String.valueOf(floatBinding); 154 case MysqlDefs.FIELD_TYPE_DOUBLE: 155 return String.valueOf(doubleBinding); 156 case MysqlDefs.FIELD_TYPE_TIME: 157 case MysqlDefs.FIELD_TYPE_DATE: 158 case MysqlDefs.FIELD_TYPE_DATETIME: 159 case MysqlDefs.FIELD_TYPE_TIMESTAMP: 160 case MysqlDefs.FIELD_TYPE_VAR_STRING: 161 case MysqlDefs.FIELD_TYPE_STRING: 162 case MysqlDefs.FIELD_TYPE_VARCHAR: 163 if (quoteIfNeeded) { 164 return "'" + String.valueOf(value) + "'"; 165 } else { 166 return String.valueOf(value); 167 } 168 default: 169 if (value instanceof byte[]) { 170 return "byte data"; 171 172 } else { 173 if (quoteIfNeeded) { 174 return "'" + String.valueOf(value) + "'"; 175 } else { 176 return String.valueOf(value); 177 } 178 } 179 } 180 } 181 } 182 183 184 private static final byte MAX_DATE_REP_LENGTH = (byte) 5; 185 186 190 private static final byte MAX_DATETIME_REP_LENGTH = 12; 191 192 196 private static final byte MAX_TIME_REP_LENGTH = 13; 197 198 private static void storeTime(Buffer intoBuf, Time tm) throws SQLException { 199 intoBuf.ensureCapacity(9); 200 intoBuf.writeByte((byte) 8); intoBuf.writeByte((byte) 0); intoBuf.writeLong(0); 204 Calendar cal = Calendar.getInstance(); 205 cal.setTime(tm); 206 intoBuf.writeByte((byte) cal.get(Calendar.HOUR_OF_DAY)); 207 intoBuf.writeByte((byte) cal.get(Calendar.MINUTE)); 208 intoBuf.writeByte((byte) cal.get(Calendar.SECOND)); 209 210 } 212 213 214 private Calendar dateTimeBindingCal = null; 215 216 221 private boolean detectedLongParameterSwitch = false; 222 223 227 private int fieldCount; 228 229 230 private boolean invalid = false; 231 232 233 private SQLException invalidationException; 234 235 236 private boolean isSelectQuery; 237 238 private Buffer outByteBuffer; 239 240 241 private BindValue[] parameterBindings; 242 243 244 private Field[] parameterFields; 245 246 247 private Field[] resultFields; 248 249 250 private boolean sendTypesToServer = false; 251 252 253 private long serverStatementId; 254 255 256 private int stringTypeCode = MysqlDefs.FIELD_TYPE_STRING; 257 258 private boolean serverNeedsResetBeforeEachExecution; 259 260 273 public ServerPreparedStatement(Connection conn, String sql, String catalog) 274 throws SQLException { 275 super(conn, catalog); 276 277 checkNullOrEmptyQuery(sql); 278 279 this.isSelectQuery = StringUtils.startsWithIgnoreCaseAndWs(sql, 280 "SELECT"); 282 if (this.connection.versionMeetsMinimum(5, 0, 0)) { 283 this.serverNeedsResetBeforeEachExecution = 284 !this.connection.versionMeetsMinimum(5, 0, 3); 285 } else { 286 this.serverNeedsResetBeforeEachExecution = 287 !this.connection.versionMeetsMinimum(4, 1, 10); 288 } 289 290 this.useTrueBoolean = this.connection.versionMeetsMinimum(3, 21, 23); 291 this.hasLimitClause = (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1); this.firstCharOfStmt = StringUtils.firstNonWsCharUc(sql); 293 this.originalSql = sql; 294 295 if (this.connection.versionMeetsMinimum(4, 1, 2)) { 296 this.stringTypeCode = MysqlDefs.FIELD_TYPE_VAR_STRING; 297 } else { 298 this.stringTypeCode = MysqlDefs.FIELD_TYPE_STRING; 299 } 300 301 try { 302 serverPrepare(sql); 303 } catch (SQLException sqlEx) { 304 realClose(false); 305 throw sqlEx; 307 } catch (Exception ex) { 308 realClose(false); 309 310 throw new SQLException (ex.toString(), 311 SQLError.SQL_STATE_GENERAL_ERROR); 312 } 313 } 314 315 323 public synchronized void addBatch() throws SQLException { 324 checkClosed(); 325 326 if (this.batchedArgs == null) { 327 this.batchedArgs = new ArrayList (); 328 } 329 330 this.batchedArgs.add(new BatchedBindValues(this.parameterBindings)); 331 } 332 333 protected String asSql(boolean quoteStreamsAndUnknowns) throws SQLException { 334 335 PreparedStatement pStmtForSub = null; 336 337 try { 338 pStmtForSub = new PreparedStatement(this.connection, 339 this.originalSql, this.currentCatalog); 340 341 int numParameters = pStmtForSub.parameterCount; 342 int ourNumParameters = this.parameterCount; 343 344 for (int i = 0; (i < numParameters) && (i < ourNumParameters); i++) { 345 if (this.parameterBindings[i] != null) { 346 if (this.parameterBindings[i].isNull) { 347 pStmtForSub.setNull(i + 1, Types.NULL); 348 } else { 349 BindValue bindValue = this.parameterBindings[i]; 350 351 switch (bindValue.bufferType) { 355 356 case MysqlDefs.FIELD_TYPE_TINY: 357 pStmtForSub.setByte(i + 1, bindValue.byteBinding); 358 break; 359 case MysqlDefs.FIELD_TYPE_SHORT: 360 pStmtForSub.setShort(i + 1, bindValue.shortBinding); 361 break; 362 case MysqlDefs.FIELD_TYPE_LONG: 363 pStmtForSub.setInt(i + 1, bindValue.intBinding); 364 break; 365 case MysqlDefs.FIELD_TYPE_LONGLONG: 366 pStmtForSub.setLong(i + 1, bindValue.longBinding); 367 break; 368 case MysqlDefs.FIELD_TYPE_FLOAT: 369 pStmtForSub.setFloat(i + 1, bindValue.floatBinding); 370 break; 371 case MysqlDefs.FIELD_TYPE_DOUBLE: 372 pStmtForSub.setDouble(i + 1, 373 bindValue.doubleBinding); 374 break; 375 default: 376 pStmtForSub.setObject(i + 1, 377 this.parameterBindings[i].value); 378 break; 379 } 380 } 381 } 382 } 383 384 return pStmtForSub.asSql(quoteStreamsAndUnknowns); 385 } finally { 386 if (pStmtForSub != null) { 387 try { 388 pStmtForSub.close(); 389 } catch (SQLException sqlEx) { 390 ; } 392 } 393 } 394 } 395 396 401 protected void checkClosed() throws SQLException { 402 if (this.invalid) { 403 throw this.invalidationException; 404 } 405 406 } 408 409 412 public void clearParameters() throws SQLException { 413 clearParametersInternal(true); 414 } 415 416 private void clearParametersInternal(boolean clearServerParameters) 417 throws SQLException { 418 boolean hadLongData = false; 419 420 if (this.parameterBindings != null) { 421 for (int i = 0; i < this.parameterCount; i++) { 422 if ((this.parameterBindings[i] != null) 423 && this.parameterBindings[i].isLongData) { 424 hadLongData = true; 425 } 426 427 this.parameterBindings[i].reset(); 428 } 429 } 430 431 if (clearServerParameters && hadLongData) { 432 serverResetStatement(); 433 434 this.detectedLongParameterSwitch = false; 435 } 436 } 437 438 protected boolean isCached = false; 439 440 protected void setClosed(boolean flag) { 441 this.isClosed = flag; 442 } 443 446 public void close() throws SQLException { 447 if (this.isCached) { 448 this.isClosed = true; 449 this.connection.recachePreparedStatement(this); 450 return; 451 } 452 453 realClose(true); 454 } 455 456 private void dumpCloseForTestcase() { 457 StringBuffer buf = new StringBuffer (); 458 this.connection.generateConnectionCommentBlock(buf); 459 buf.append("DEALLOCATE PREPARE debug_stmt_"); 460 buf.append(this.statementId); 461 buf.append(";\n"); 462 463 this.connection.dumpTestcaseQuery(buf.toString()); 464 } 465 466 private void dumpExecuteForTestcase() throws SQLException { 467 StringBuffer buf = new StringBuffer (); 468 469 for (int i = 0; i < this.parameterCount; i++) { 470 this.connection.generateConnectionCommentBlock(buf); 471 472 buf.append("SET @debug_stmt_param"); 473 buf.append(this.statementId); 474 buf.append("_"); 475 buf.append(i); 476 buf.append("="); 477 478 if (this.parameterBindings[i].isNull) { 479 buf.append("NULL"); 480 } else { 481 buf.append(this.parameterBindings[i].toString(true)); 482 } 483 484 buf.append(";\n"); 485 } 486 487 this.connection.generateConnectionCommentBlock(buf); 488 489 buf.append("EXECUTE debug_stmt_"); 490 buf.append(this.statementId); 491 492 if (this.parameterCount > 0) { 493 buf.append(" USING "); 494 for (int i = 0; i < this.parameterCount; i++) { 495 if (i > 0) { 496 buf.append(", "); 497 } 498 499 buf.append("@debug_stmt_param"); 500 buf.append(this.serverStatementId); 501 buf.append("_"); 502 buf.append(i); 503 504 } 505 } 506 507 buf.append(";\n"); 508 509 this.connection.dumpTestcaseQuery(buf.toString()); 510 } 511 512 private void dumpPrepareForTestcase() throws SQLException { 513 514 StringBuffer buf = new StringBuffer (this.originalSql.length() + 64); 515 516 this.connection.generateConnectionCommentBlock(buf); 517 518 buf.append("PREPARE debug_stmt_"); 519 buf.append(this.statementId); 520 buf.append(" FROM \""); 521 buf.append(this.originalSql); 522 buf.append("\";\n"); 523 524 this.connection.dumpTestcaseQuery(buf.toString()); 525 } 526 527 530 public synchronized int[] executeBatch() throws SQLException { 531 if (this.connection.isReadOnly()) { 532 throw new SQLException (Messages 533 .getString("ServerPreparedStatement.2") + Messages.getString("ServerPreparedStatement.3"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 536 } 537 538 checkClosed(); 539 540 synchronized (this.connection.getMutex()) { 541 clearWarnings(); 542 543 BindValue[] oldBindValues = this.parameterBindings; 546 547 try { 548 int[] updateCounts = null; 549 550 if (this.batchedArgs != null) { 551 int nbrCommands = this.batchedArgs.size(); 552 updateCounts = new int[nbrCommands]; 553 554 if (this.retrieveGeneratedKeys) { 555 this.batchedGeneratedKeys = new ArrayList (nbrCommands); 556 } 557 558 for (int i = 0; i < nbrCommands; i++) { 559 updateCounts[i] = -3; 560 } 561 562 SQLException sqlEx = null; 563 564 int commandIndex = 0; 565 566 BindValue[] previousBindValuesForBatch = null; 567 568 for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { 569 Object arg = this.batchedArgs.get(commandIndex); 570 571 if (arg instanceof String ) { 572 updateCounts[commandIndex] = executeUpdate((String ) arg); 573 } else { 574 this.parameterBindings = ((BatchedBindValues) arg).batchedParameterValues; 575 576 try { 577 581 if (previousBindValuesForBatch != null) { 582 for (int j = 0; j < this.parameterBindings.length; j++) { 583 if (this.parameterBindings[j].bufferType != previousBindValuesForBatch[j].bufferType) { 584 this.sendTypesToServer = true; 585 586 break; 587 } 588 } 589 } 590 591 try { 592 updateCounts[commandIndex] = executeUpdate(false); 593 } finally { 594 previousBindValuesForBatch = this.parameterBindings; 595 } 596 597 if (this.retrieveGeneratedKeys) { 598 java.sql.ResultSet rs = null; 599 600 try { 601 rs = getGeneratedKeysInternal(); 611 612 while (rs.next()) { 613 this.batchedGeneratedKeys 614 .add(new byte[][] { rs 615 .getBytes(1) }); 616 } 617 } finally { 618 if (rs != null) { 619 rs.close(); 620 } 621 } 622 } 623 } catch (SQLException ex) { 624 updateCounts[commandIndex] = EXECUTE_FAILED; 625 626 if (this.connection.getContinueBatchOnError()) { 627 sqlEx = ex; 628 } else { 629 int[] newUpdateCounts = new int[commandIndex]; 630 System.arraycopy(updateCounts, 0, 631 newUpdateCounts, 0, commandIndex); 632 633 throw new java.sql.BatchUpdateException (ex 634 .getMessage(), ex.getSQLState(), ex 635 .getErrorCode(), newUpdateCounts); 636 } 637 } 638 } 639 } 640 641 if (sqlEx != null) { 642 throw new java.sql.BatchUpdateException (sqlEx 643 .getMessage(), sqlEx.getSQLState(), sqlEx 644 .getErrorCode(), updateCounts); 645 } 646 } 647 648 return (updateCounts != null) ? updateCounts : new int[0]; 649 } finally { 650 this.parameterBindings = oldBindValues; 651 this.sendTypesToServer = true; 652 653 clearBatch(); 654 } 655 } 656 } 657 658 662 protected com.mysql.jdbc.ResultSet executeInternal(int maxRowsToRetrieve, 663 Buffer sendPacket, boolean createStreamingResultSet, 664 boolean queryIsSelectOnly, boolean unpackFields) 665 throws SQLException { 666 this.numberOfExecutions++; 667 668 try { 670 return serverExecute(maxRowsToRetrieve, createStreamingResultSet); 671 } catch (SQLException sqlEx) { 672 if (this.connection.getEnablePacketDebug()) { 674 this.connection.getIO().dumpPacketRingBuffer(); 675 } 676 677 if (this.connection.getDumpQueriesOnException()) { 678 String extractedSql = toString(); 679 StringBuffer messageBuf = new StringBuffer (extractedSql 680 .length() + 32); 681 messageBuf 682 .append("\n\nQuery being executed when exception was thrown:\n\n"); 683 messageBuf.append(extractedSql); 684 685 sqlEx = Connection.appendMessageToException(sqlEx, messageBuf 686 .toString()); 687 } 688 689 throw sqlEx; 690 } catch (Exception ex) { 691 if (this.connection.getEnablePacketDebug()) { 692 this.connection.getIO().dumpPacketRingBuffer(); 693 } 694 695 SQLException sqlEx = new SQLException (ex.toString(), 696 SQLError.SQL_STATE_GENERAL_ERROR); 697 698 if (this.connection.getDumpQueriesOnException()) { 699 String extractedSql = toString(); 700 StringBuffer messageBuf = new StringBuffer (extractedSql 701 .length() + 32); 702 messageBuf 703 .append("\n\nQuery being executed when exception was thrown:\n\n"); 704 messageBuf.append(extractedSql); 705 706 sqlEx = Connection.appendMessageToException(sqlEx, messageBuf 707 .toString()); 708 } 709 710 throw sqlEx; 711 } 712 } 713 714 717 protected Buffer fillSendPacket() throws SQLException { 718 return null; } 720 721 725 protected Buffer fillSendPacket(byte[][] batchedParameterStrings, 726 InputStream [] batchedParameterStreams, boolean[] batchedIsStream, 727 int[] batchedStreamLengths) throws SQLException { 728 return null; } 730 731 private BindValue getBinding(int parameterIndex, boolean forLongData) 732 throws SQLException { 733 if (this.parameterBindings.length == 0) { 734 throw new SQLException (Messages 735 .getString("ServerPreparedStatement.8"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 737 } 738 739 parameterIndex--; 740 741 if ((parameterIndex < 0) 742 || (parameterIndex >= this.parameterBindings.length)) { 743 throw new SQLException (Messages 744 .getString("ServerPreparedStatement.9") + (parameterIndex + 1) 746 + Messages.getString("ServerPreparedStatement.10") + this.parameterBindings.length, 748 SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 749 } 750 751 if (this.parameterBindings[parameterIndex] == null) { 752 this.parameterBindings[parameterIndex] = new BindValue(); 753 } else { 754 if (this.parameterBindings[parameterIndex].isLongData 755 && !forLongData) { 756 this.detectedLongParameterSwitch = true; 757 } 758 } 759 760 this.parameterBindings[parameterIndex].isSet = true; 761 762 return this.parameterBindings[parameterIndex]; 763 } 764 765 768 synchronized byte[] getBytes(int parameterIndex) throws SQLException { 769 BindValue bindValue = getBinding(parameterIndex, false); 770 771 if (bindValue.isNull) { 772 return null; 773 } else if (bindValue.isLongData) { 774 throw new NotImplemented(); 775 } else { 776 if (this.outByteBuffer == null) { 777 this.outByteBuffer = Buffer.allocateNew(this.connection 778 .getNetBufferLength(), false); 779 } 780 781 this.outByteBuffer.clear(); 782 783 int originalPosition = this.outByteBuffer.getPosition(); 784 785 storeBinding(this.outByteBuffer, bindValue, this.connection.getIO()); 786 787 int newPosition = this.outByteBuffer.getPosition(); 788 789 int length = newPosition - originalPosition; 790 791 byte[] valueAsBytes = new byte[length]; 792 793 System.arraycopy(this.outByteBuffer.getByteBuffer(), 794 originalPosition, valueAsBytes, 0, length); 795 796 return valueAsBytes; 797 } 798 } 799 800 803 public java.sql.ResultSetMetaData getMetaData() throws SQLException { 804 checkClosed(); 805 806 if (this.resultFields == null) { 807 return null; 808 } 809 810 return new ResultSetMetaData(this.resultFields); 811 } 812 813 816 public synchronized ParameterMetaData getParameterMetaData() throws SQLException { 817 checkClosed(); 818 819 if (this.parameterMetaData == null) { 820 this.parameterMetaData = new MysqlParameterMetadata( 821 this.parameterFields, this.parameterCount); 822 } 823 824 return this.parameterMetaData; 825 } 826 827 830 boolean isNull(int paramIndex) { 831 throw new IllegalArgumentException (Messages 832 .getString("ServerPreparedStatement.7")); } 834 835 844 protected void realClose(boolean calledExplicitly) throws SQLException { 845 if (this.isClosed) { 846 return; 847 } 848 849 if (this.connection != null && 850 this.connection.getAutoGenerateTestcaseScript()) { 851 dumpCloseForTestcase(); 852 } 853 854 865 SQLException exceptionDuringClose = null; 866 867 if (calledExplicitly) { 868 try { 869 synchronized (this.connection.getMutex()) { 870 MysqlIO mysql = this.connection.getIO(); 871 872 Buffer packet = mysql.getSharedSendPacket(); 873 874 packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT); 875 packet.writeLong(this.serverStatementId); 876 877 mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null, 878 packet, true, null); 879 } 880 } catch (SQLException sqlEx) { 881 exceptionDuringClose = sqlEx; 882 } 883 } 884 885 clearParametersInternal(false); 886 this.parameterBindings = null; 887 888 this.parameterFields = null; 889 this.resultFields = null; 890 891 super.realClose(calledExplicitly); 892 893 if (exceptionDuringClose != null) { 894 throw exceptionDuringClose; 895 } 896 } 897 898 905 protected void rePrepare() throws SQLException { 906 this.invalidationException = null; 907 908 try { 909 serverPrepare(this.originalSql); 910 } catch (SQLException sqlEx) { 911 this.invalidationException = sqlEx; 913 } catch (Exception ex) { 914 this.invalidationException = new SQLException (ex.toString(), 915 SQLError.SQL_STATE_GENERAL_ERROR); 916 } 917 918 if (this.invalidationException != null) { 919 this.invalid = true; 920 921 this.parameterBindings = null; 922 923 this.parameterFields = null; 924 this.resultFields = null; 925 926 if (this.results != null) { 927 try { 928 this.results.close(); 929 } catch (Exception ex) { 930 ; 931 } 932 } 933 934 if (this.connection != null) { 935 if (this.maxRowsChanged) { 936 this.connection.unsetMaxRows(this); 937 } 938 939 if (!this.connection.getDontTrackOpenResources()) { 940 this.connection.unregisterStatement(this); 941 } 942 } 943 } 944 } 945 946 979 private com.mysql.jdbc.ResultSet serverExecute(int maxRowsToRetrieve, 980 boolean createStreamingResultSet) throws SQLException { 981 synchronized (this.connection.getMutex()) { 982 if (this.detectedLongParameterSwitch) { 983 throw new SQLException (Messages 984 .getString("ServerPreparedStatement.11") + Messages.getString("ServerPreparedStatement.12"), SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); 987 } 988 989 for (int i = 0; i < this.parameterCount; i++) { 991 if (!this.parameterBindings[i].isSet) { 992 throw new SQLException (Messages 993 .getString("ServerPreparedStatement.13") + (i + 1) + Messages.getString("ServerPreparedStatement.14"), 995 SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } 997 } 998 999 for (int i = 0; i < this.parameterCount; i++) { 1003 if (this.parameterBindings[i].isLongData) { 1004 serverLongData(i, this.parameterBindings[i]); 1005 } 1006 } 1007 1008 if (this.connection.getAutoGenerateTestcaseScript()) { 1009 dumpExecuteForTestcase(); 1010 } 1011 1012 MysqlIO mysql = this.connection.getIO(); 1016 1017 Buffer packet = mysql.getSharedSendPacket(); 1018 1019 packet.clear(); 1020 packet.writeByte((byte) MysqlDefs.COM_EXECUTE); 1021 packet.writeLong(this.serverStatementId); 1022 1023 if (this.connection.versionMeetsMinimum(4, 1, 2)) { 1024 packet.writeByte((byte) 0); packet.writeLong(1); } 1027 1028 1029 int nullCount = (this.parameterCount + 7) / 8; 1030 1031 int nullBitsPosition = packet.getPosition(); 1035 1036 for (int i = 0; i < nullCount; i++) { 1037 packet.writeByte((byte) 0); 1038 } 1039 1040 byte[] nullBitsBuffer = new byte[nullCount]; 1041 1042 1043 packet.writeByte(this.sendTypesToServer ? (byte) 1 : (byte) 0); 1044 1045 if (this.sendTypesToServer) { 1046 1050 for (int i = 0; i < this.parameterCount; i++) { 1051 packet.writeInt(this.parameterBindings[i].bufferType); 1052 } 1053 } 1054 1055 for (int i = 0; i < this.parameterCount; i++) { 1059 if (!this.parameterBindings[i].isLongData) { 1060 if (!this.parameterBindings[i].isNull) { 1061 storeBinding(packet, this.parameterBindings[i], mysql); 1062 } else { 1063 nullBitsBuffer[i / 8] |= (1 << (i & 7)); 1064 } 1065 } 1066 } 1067 1068 int endPosition = packet.getPosition(); 1073 packet.setPosition(nullBitsPosition); 1074 packet.writeBytesNoNull(nullBitsBuffer); 1075 packet.setPosition(endPosition); 1076 1077 long begin = 0; 1078 1079 if (this.connection.getProfileSql() 1080 || this.connection.getLogSlowQueries() 1081 || this.connection.getGatherPerformanceMetrics()) { 1082 begin = System.currentTimeMillis(); 1083 } 1084 1085 Buffer resultPacket = mysql.sendCommand(MysqlDefs.COM_EXECUTE, 1086 null, packet, false, null); 1087 1088 if (this.connection.getLogSlowQueries() 1089 || this.connection.getGatherPerformanceMetrics()) { 1090 long elapsedTime = System.currentTimeMillis() - begin; 1091 1092 if (this.connection.getLogSlowQueries() 1093 && (elapsedTime > this.connection 1094 .getSlowQueryThresholdMillis())) { 1095 StringBuffer mesgBuf = new StringBuffer ( 1096 48 + this.originalSql.length()); 1097 mesgBuf.append(Messages 1098 .getString("ServerPreparedStatement.15")); mesgBuf.append(this.connection 1100 .getSlowQueryThresholdMillis()); 1101 mesgBuf.append(Messages 1102 .getString("ServerPreparedStatement.16")); mesgBuf.append(this.originalSql); 1104 1105 this.connection.getLog().logWarn(mesgBuf.toString()); 1106 1107 if (this.connection.getExplainSlowQueries()) { 1108 String queryAsString = asSql(true); 1109 1110 mysql.explainSlowQuery(queryAsString.getBytes(), 1111 queryAsString); 1112 } 1113 } 1114 1115 if (this.connection.getGatherPerformanceMetrics()) { 1116 this.connection.registerQueryExecutionTime(elapsedTime); 1117 } 1118 } 1119 1120 this.connection.incrementNumberOfPreparedExecutes(); 1121 1122 if (this.connection.getProfileSql()) { 1123 this.eventSink = ProfileEventSink.getInstance(this.connection); 1124 1125 this.eventSink.consumeEvent(new ProfilerEvent( 1126 ProfilerEvent.TYPE_EXECUTE, "", this.currentCatalog, this.connection.getId(), this.statementId, -1, System 1128 .currentTimeMillis(), (int) (System 1129 .currentTimeMillis() - begin), null, 1130 new Throwable (), null)); 1131 } 1132 1133 com.mysql.jdbc.ResultSet rs = mysql.readAllResults(this, 1134 maxRowsToRetrieve, this.resultSetType, 1135 this.resultSetConcurrency, createStreamingResultSet, 1136 this.currentCatalog, resultPacket, true, this.fieldCount, 1137 true); 1138 1139 1140 if (!createStreamingResultSet && 1141 this.serverNeedsResetBeforeEachExecution) { 1142 serverResetStatement(); } 1144 1145 this.sendTypesToServer = false; 1146 this.results = rs; 1147 1148 return rs; 1149 } 1150 } 1151 1152 1179 private void serverLongData(int parameterIndex, BindValue longData) 1180 throws SQLException { 1181 synchronized (this.connection.getMutex()) { 1182 MysqlIO mysql = this.connection.getIO(); 1183 1184 Buffer packet = mysql.getSharedSendPacket(); 1185 1186 Object value = longData.value; 1187 1188 if (value instanceof byte[]) { 1189 packet.clear(); 1190 packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); 1191 packet.writeLong(this.serverStatementId); 1192 packet.writeInt((parameterIndex)); 1193 1194 packet.writeBytesNoNull((byte[]) longData.value); 1195 1196 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, 1197 null); 1198 } else if (value instanceof InputStream ) { 1199 storeStream(mysql, parameterIndex, packet, (InputStream ) value); 1200 } else if (value instanceof java.sql.Blob ) { 1201 storeStream(mysql, parameterIndex, packet, 1202 ((java.sql.Blob ) value).getBinaryStream()); 1203 } else if (value instanceof Reader ) { 1204 storeReader(mysql, parameterIndex, packet, (Reader ) value); 1205 } else { 1206 throw new SQLException (Messages 1207 .getString("ServerPreparedStatement.18") + value.getClass().getName() + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 1210 } 1211 } 1212 } 1213 1214 private void serverPrepare(String sql) throws SQLException { 1215 synchronized (this.connection.getMutex()) { 1216 MysqlIO mysql = this.connection.getIO(); 1217 1218 if (this.connection.getAutoGenerateTestcaseScript()) { 1219 dumpPrepareForTestcase(); 1220 } 1221 1222 try { 1223 long begin = 0; 1224 1225 if (StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) { this.isLoadDataQuery = true; 1227 } else { 1228 this.isLoadDataQuery = false; 1229 } 1230 1231 if (this.connection.getProfileSql()) { 1232 begin = System.currentTimeMillis(); 1233 } 1234 1235 String characterEncoding = null; 1236 String connectionEncoding = this.connection.getEncoding(); 1237 1238 if (!this.isLoadDataQuery && this.connection.getUseUnicode() 1239 && (connectionEncoding != null)) { 1240 characterEncoding = connectionEncoding; 1241 } 1242 1243 Buffer prepareResultPacket = mysql.sendCommand( 1244 MysqlDefs.COM_PREPARE, sql, null, false, 1245 characterEncoding); 1246 1247 if (this.connection.versionMeetsMinimum(4, 1, 1)) { 1248 prepareResultPacket.setPosition(1); 1253 } else { 1254 prepareResultPacket.setPosition(0); 1257 } 1258 1259 this.serverStatementId = prepareResultPacket.readLong(); 1260 this.fieldCount = prepareResultPacket.readInt(); 1261 this.parameterCount = prepareResultPacket.readInt(); 1262 this.parameterBindings = new BindValue[this.parameterCount]; 1263 1264 for (int i = 0; i < this.parameterCount; i++) { 1265 this.parameterBindings[i] = new BindValue(); 1266 } 1267 1268 this.connection.incrementNumberOfPrepares(); 1269 1270 if (this.connection.getProfileSql()) { 1271 this.eventSink = ProfileEventSink 1272 .getInstance(this.connection); 1273 1274 this.eventSink.consumeEvent(new ProfilerEvent( 1275 ProfilerEvent.TYPE_PREPARE, 1276 "", this.currentCatalog, this.connection.getId(), this.statementId, -1, 1278 System.currentTimeMillis(), (int) (System 1279 .currentTimeMillis() - begin), null, 1280 new Throwable (), sql)); 1281 } 1282 1283 if (this.parameterCount > 0) { 1284 if (this.connection.versionMeetsMinimum(4, 1, 2) 1285 && !mysql.isVersion(5, 0, 0)) { 1286 this.parameterFields = new Field[this.parameterCount]; 1287 1288 Buffer metaDataPacket = mysql.readPacket(); 1289 1290 int i = 0; 1291 1292 while (!metaDataPacket.isLastDataPacket() 1293 && (i < this.parameterCount)) { 1294 this.parameterFields[i++] = mysql.unpackField( 1295 metaDataPacket, false); 1296 metaDataPacket = mysql.readPacket(); 1297 } 1298 } 1299 } 1300 1301 if (this.fieldCount > 0) { 1302 this.resultFields = new Field[this.fieldCount]; 1303 1304 Buffer fieldPacket = mysql.readPacket(); 1305 1306 int i = 0; 1307 1308 while (!fieldPacket.isLastDataPacket() 1310 && (i < this.fieldCount)) { 1311 this.resultFields[i++] = mysql.unpackField(fieldPacket, 1312 false); 1313 fieldPacket = mysql.readPacket(); 1314 } 1315 } 1316 } catch (SQLException sqlEx) { 1317 if (this.connection.getDumpQueriesOnException()) { 1318 StringBuffer messageBuf = new StringBuffer (this.originalSql 1319 .length() + 32); 1320 messageBuf 1321 .append("\n\nQuery being prepared when exception was thrown:\n\n"); 1322 messageBuf.append(this.originalSql); 1323 1324 sqlEx = Connection.appendMessageToException(sqlEx, 1325 messageBuf.toString()); 1326 } 1327 1328 throw sqlEx; 1329 } finally { 1330 this.connection.getIO().clearInputStream(); 1334 } 1335 } 1336 } 1337 1338 private void serverResetStatement() throws SQLException { 1339 synchronized (this.connection.getMutex()) { 1340 1341 MysqlIO mysql = this.connection.getIO(); 1342 1343 Buffer packet = mysql.getSharedSendPacket(); 1344 1345 packet.clear(); 1346 packet.writeByte((byte) MysqlDefs.COM_RESET_STMT); 1347 packet.writeLong(this.serverStatementId); 1348 1349 try { 1350 mysql.sendCommand(MysqlDefs.COM_RESET_STMT, null, packet, 1351 !this.connection.versionMeetsMinimum(4, 1, 2), null); 1352 } catch (SQLException sqlEx) { 1353 throw sqlEx; 1354 } catch (Exception ex) { 1355 throw new SQLException (ex.toString(), 1356 SQLError.SQL_STATE_GENERAL_ERROR); 1357 } finally { 1358 mysql.clearInputStream(); 1359 } 1360 } 1361 } 1362 1363 1366 public void setArray(int i, Array x) throws SQLException { 1367 throw new NotImplemented(); 1368 } 1369 1370 1374 public void setAsciiStream(int parameterIndex, InputStream x, int length) 1375 throws SQLException { 1376 checkClosed(); 1377 1378 if (x == null) { 1379 setNull(parameterIndex, java.sql.Types.BINARY); 1380 } else { 1381 BindValue binding = getBinding(parameterIndex, true); 1382 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1383 1384 binding.value = x; 1385 binding.isNull = false; 1386 binding.isLongData = true; 1387 1388 if (this.connection.getUseStreamLengthsInPrepStmts()) { 1389 binding.bindLength = length; 1390 } else { 1391 binding.bindLength = -1; 1392 } 1393 } 1394 } 1395 1396 1399 public void setBigDecimal(int parameterIndex, BigDecimal x) 1400 throws SQLException { 1401 checkClosed(); 1402 1403 if (x == null) { 1404 setNull(parameterIndex, java.sql.Types.DECIMAL); 1405 } else { 1406 setString(parameterIndex, StringUtils.fixDecimalExponent(x 1407 .toString())); 1408 } 1409 } 1410 1411 1415 public void setBinaryStream(int parameterIndex, InputStream x, int length) 1416 throws SQLException { 1417 checkClosed(); 1418 1419 if (x == null) { 1420 setNull(parameterIndex, java.sql.Types.BINARY); 1421 } else { 1422 BindValue binding = getBinding(parameterIndex, true); 1423 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1424 1425 binding.value = x; 1426 binding.isNull = false; 1427 binding.isLongData = true; 1428 1429 if (this.connection.getUseStreamLengthsInPrepStmts()) { 1430 binding.bindLength = length; 1431 } else { 1432 binding.bindLength = -1; 1433 } 1434 } 1435 } 1436 1437 1440 public void setBlob(int parameterIndex, Blob x) throws SQLException { 1441 checkClosed(); 1442 1443 if (x == null) { 1444 setNull(parameterIndex, java.sql.Types.BINARY); 1445 } else { 1446 BindValue binding = getBinding(parameterIndex, true); 1447 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1448 1449 binding.value = x; 1450 binding.isNull = false; 1451 binding.isLongData = true; 1452 1453 if (this.connection.getUseStreamLengthsInPrepStmts()) { 1454 binding.bindLength = x.length(); 1455 } else { 1456 binding.bindLength = -1; 1457 } 1458 } 1459 } 1460 1461 1464 public void setBoolean(int parameterIndex, boolean x) throws SQLException { 1465 setByte(parameterIndex, (x ? (byte) 1 : (byte) 0)); 1466 } 1467 1468 1471 public void setByte(int parameterIndex, byte x) throws SQLException { 1472 checkClosed(); 1473 1474 BindValue binding = getBinding(parameterIndex, false); 1475 setType(binding, MysqlDefs.FIELD_TYPE_TINY); 1476 1477 binding.value = null; 1478 binding.byteBinding = x; 1479 binding.isNull = false; 1480 binding.isLongData = false; 1481 } 1482 1483 1486 public void setBytes(int parameterIndex, byte[] x) throws SQLException { 1487 checkClosed(); 1488 1489 if (x == null) { 1490 setNull(parameterIndex, java.sql.Types.BINARY); 1491 } else { 1492 BindValue binding = getBinding(parameterIndex, false); 1493 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1494 1495 binding.value = x; 1496 binding.isNull = false; 1497 binding.isLongData = false; 1498 } 1499 } 1500 1501 1505 public void setCharacterStream(int parameterIndex, Reader reader, int length) 1506 throws SQLException { 1507 checkClosed(); 1508 1509 if (reader == null) { 1510 setNull(parameterIndex, java.sql.Types.BINARY); 1511 } else { 1512 BindValue binding = getBinding(parameterIndex, true); 1513 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1514 1515 binding.value = reader; 1516 binding.isNull = false; 1517 binding.isLongData = true; 1518 1519 if (this.connection.getUseStreamLengthsInPrepStmts()) { 1520 binding.bindLength = length; 1521 } else { 1522 binding.bindLength = -1; 1523 } 1524 } 1525 } 1526 1527 1530 public void setClob(int parameterIndex, Clob x) throws SQLException { 1531 checkClosed(); 1532 1533 if (x == null) { 1534 setNull(parameterIndex, java.sql.Types.BINARY); 1535 } else { 1536 BindValue binding = getBinding(parameterIndex, true); 1537 setType(binding, MysqlDefs.FIELD_TYPE_BLOB); 1538 1539 binding.value = x.getCharacterStream(); 1540 binding.isNull = false; 1541 binding.isLongData = true; 1542 1543 if (this.connection.getUseStreamLengthsInPrepStmts()) { 1544 binding.bindLength = x.length(); 1545 } else { 1546 binding.bindLength = -1; 1547 } 1548 } 1549 } 1550 1551 1563 public void setDate(int parameterIndex, Date x) throws SQLException { 1564 setDate(parameterIndex, x, null); 1565 } 1566 1567 1581 public void setDate(int parameterIndex, Date x, Calendar cal) 1582 throws SQLException { 1583 if (x == null) { 1584 setNull(parameterIndex, java.sql.Types.DATE); 1585 } else { 1586 BindValue binding = getBinding(parameterIndex, false); 1587 setType(binding, MysqlDefs.FIELD_TYPE_DATE); 1588 1589 binding.value = x; 1590 binding.isNull = false; 1591 binding.isLongData = false; 1592 } 1593 } 1594 1595 1598 public void setDouble(int parameterIndex, double x) throws SQLException { 1599 checkClosed(); 1600 1601 if (!this.connection.getAllowNanAndInf() 1602 && (x == Double.POSITIVE_INFINITY 1603 || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) { 1604 throw new SQLException ("'" + x 1605 + "' is not a valid numeric or approximate numeric value", 1606 SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 1607 1608 } 1609 1610 BindValue binding = getBinding(parameterIndex, false); 1611 setType(binding, MysqlDefs.FIELD_TYPE_DOUBLE); 1612 1613 binding.value = null; 1614 binding.doubleBinding = x; 1615 binding.isNull = false; 1616 binding.isLongData = false; 1617 } 1618 1619 1622 public void setFloat(int parameterIndex, float x) throws SQLException { 1623 checkClosed(); 1624 1625 BindValue binding = getBinding(parameterIndex, false); 1626 setType(binding, MysqlDefs.FIELD_TYPE_FLOAT); 1627 1628 binding.value = null; 1629 binding.floatBinding = x; 1630 binding.isNull = false; 1631 binding.isLongData = false; 1632 } 1633 1634 1637 public void setInt(int parameterIndex, int x) throws SQLException { 1638 checkClosed(); 1639 1640 BindValue binding = getBinding(parameterIndex, false); 1641 setType(binding, MysqlDefs.FIELD_TYPE_LONG); 1642 1643 binding.value = null; 1644 binding.intBinding = x; 1645 binding.isNull = false; 1646 binding.isLongData = false; 1647 } 1648 1649 1652 public void setLong(int parameterIndex, long x) throws SQLException { 1653 checkClosed(); 1654 1655 BindValue binding = getBinding(parameterIndex, false); 1656 setType(binding, MysqlDefs.FIELD_TYPE_LONGLONG); 1657 1658 binding.value = null; 1659 binding.longBinding = x; 1660 binding.isNull = false; 1661 binding.isLongData = false; 1662 } 1663 1664 1667 public void setNull(int parameterIndex, int sqlType) throws SQLException { 1668 checkClosed(); 1669 1670 BindValue binding = getBinding(parameterIndex, false); 1671 1672 if (binding.bufferType == 0) { 1677 setType(binding, MysqlDefs.FIELD_TYPE_NULL); 1678 } 1679 1680 binding.value = null; 1681 binding.isNull = true; 1682 binding.isLongData = false; 1683 } 1684 1685 1688 public void setNull(int parameterIndex, int sqlType, String typeName) 1689 throws SQLException { 1690 checkClosed(); 1691 1692 BindValue binding = getBinding(parameterIndex, false); 1693 1694 if (binding.bufferType == 0) { 1699 setType(binding, MysqlDefs.FIELD_TYPE_NULL); 1700 } 1701 1702 binding.value = null; 1703 binding.isNull = true; 1704 binding.isLongData = false; 1705 } 1706 1707 1710 public void setRef(int i, Ref x) throws SQLException { 1711 throw new NotImplemented(); 1712 } 1713 1714 1717 public void setShort(int parameterIndex, short x) throws SQLException { 1718 checkClosed(); 1719 1720 BindValue binding = getBinding(parameterIndex, false); 1721 setType(binding, MysqlDefs.FIELD_TYPE_SHORT); 1722 1723 binding.value = null; 1724 binding.shortBinding = x; 1725 binding.isNull = false; 1726 binding.isLongData = false; 1727 } 1728 1729 1732 public void setString(int parameterIndex, String x) throws SQLException { 1733 checkClosed(); 1734 1735 if (x == null) { 1736 setNull(parameterIndex, java.sql.Types.CHAR); 1737 } else { 1738 BindValue binding = getBinding(parameterIndex, false); 1739 1740 setType(binding, this.stringTypeCode); 1741 1742 binding.value = x; 1743 binding.isNull = false; 1744 binding.isLongData = false; 1745 } 1746 } 1747 1748 1759 public void setTime(int parameterIndex, java.sql.Time x) 1760 throws SQLException { 1761 setTimeInternal(parameterIndex, x, TimeZone.getDefault(), false); 1762 } 1763 1764 1779 public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) 1780 throws SQLException { 1781 setTimeInternal(parameterIndex, x, cal.getTimeZone(), true); 1782 } 1783 1784 1799 public void setTimeInternal(int parameterIndex, java.sql.Time x, 1800 TimeZone tz, boolean rollForward) throws SQLException { 1801 if (x == null) { 1802 setNull(parameterIndex, java.sql.Types.TIME); 1803 } else { 1804 BindValue binding = getBinding(parameterIndex, false); 1805 setType(binding, MysqlDefs.FIELD_TYPE_TIME); 1806 1807 binding.value = TimeUtil.changeTimezone(this.connection, x, tz, 1808 this.connection.getServerTimezoneTZ(), rollForward); 1809 binding.isNull = false; 1810 binding.isLongData = false; 1811 } 1812 } 1813 1814 1826 public void setTimestamp(int parameterIndex, java.sql.Timestamp x) 1827 throws SQLException { 1828 setTimestampInternal(parameterIndex, x, TimeZone.getDefault(), false); 1829 } 1830 1831 1845 public void setTimestamp(int parameterIndex, java.sql.Timestamp x, 1846 Calendar cal) throws SQLException { 1847 setTimestampInternal(parameterIndex, x, cal.getTimeZone(), true); 1848 } 1849 1850 protected void setTimestampInternal(int parameterIndex, 1851 java.sql.Timestamp x, TimeZone tz, boolean rollForward) 1852 throws SQLException { 1853 if (x == null) { 1854 setNull(parameterIndex, java.sql.Types.TIMESTAMP); 1855 } else { 1856 BindValue binding = getBinding(parameterIndex, false); 1857 setType(binding, MysqlDefs.FIELD_TYPE_DATETIME); 1858 1859 binding.value = TimeUtil.changeTimezone(this.connection, x, tz, 1860 this.connection.getServerTimezoneTZ(), rollForward); 1861 binding.isNull = false; 1862 binding.isLongData = false; 1863 } 1864 } 1865 1866 private void setType(BindValue oldValue, int bufferType) { 1867 if (oldValue.bufferType != bufferType) { 1868 this.sendTypesToServer = true; 1869 } 1870 1871 oldValue.bufferType = bufferType; 1872 } 1873 1874 1893 public void setUnicodeStream(int parameterIndex, InputStream x, int length) 1894 throws SQLException { 1895 checkClosed(); 1896 1897 throw new NotImplemented(); 1898 } 1899 1900 1903 public void setURL(int parameterIndex, URL x) throws SQLException { 1904 checkClosed(); 1905 1906 setString(parameterIndex, x.toString()); 1907 } 1908 1909 1920 private void storeBinding(Buffer packet, BindValue bindValue, MysqlIO mysql) 1921 throws SQLException { 1922 try { 1923 Object value = bindValue.value; 1924 1925 switch (bindValue.bufferType) { 1929 1930 case MysqlDefs.FIELD_TYPE_TINY: 1931 packet.writeByte(bindValue.byteBinding); 1932 return; 1933 case MysqlDefs.FIELD_TYPE_SHORT: 1934 packet.ensureCapacity(2); 1935 packet.writeInt(bindValue.shortBinding); 1936 return; 1937 case MysqlDefs.FIELD_TYPE_LONG: 1938 packet.ensureCapacity(4); 1939 packet.writeLong(bindValue.intBinding); 1940 return; 1941 case MysqlDefs.FIELD_TYPE_LONGLONG: 1942 packet.ensureCapacity(8); 1943 packet.writeLongLong(bindValue.longBinding); 1944 return; 1945 case MysqlDefs.FIELD_TYPE_FLOAT: 1946 packet.ensureCapacity(4); 1947 packet.writeFloat(bindValue.floatBinding); 1948 return; 1949 case MysqlDefs.FIELD_TYPE_DOUBLE: 1950 packet.ensureCapacity(8); 1951 packet.writeDouble(bindValue.doubleBinding); 1952 return; 1953 case MysqlDefs.FIELD_TYPE_TIME: 1954 storeTime(packet, (Time ) value); 1955 return; 1956 case MysqlDefs.FIELD_TYPE_DATE: 1957 case MysqlDefs.FIELD_TYPE_DATETIME: 1958 case MysqlDefs.FIELD_TYPE_TIMESTAMP: 1959 storeDateTime(packet, (java.util.Date ) value, mysql); 1960 return; 1961 case MysqlDefs.FIELD_TYPE_VAR_STRING: 1962 case MysqlDefs.FIELD_TYPE_STRING: 1963 case MysqlDefs.FIELD_TYPE_VARCHAR: 1964 if (!this.isLoadDataQuery) { 1965 packet.writeLenString((String ) value, this.charEncoding, 1966 this.connection.getServerCharacterEncoding(), 1967 this.charConverter, this.connection 1968 .parserKnowsUnicode()); 1969 } else { 1970 packet.writeLenBytes(((String ) value).getBytes()); 1971 } 1972 1973 return; 1974 } 1975 1976 if (value instanceof byte[]) { 1977 packet.writeLenBytes((byte[]) value); 1978 } 1979 } catch (UnsupportedEncodingException uEE) { 1980 throw new SQLException (Messages 1981 .getString("ServerPreparedStatement.22") + this.connection.getEncoding() + "'", SQLError.SQL_STATE_GENERAL_ERROR); 1984 } 1985 } 1986 1987 private void storeDataTime412AndOlder(Buffer intoBuf, java.util.Date dt) 1988 throws SQLException { 1989 if (this.dateTimeBindingCal == null) { 1992 this.dateTimeBindingCal = Calendar.getInstance(); 1993 } 1994 1995 this.dateTimeBindingCal.setTime(dt); 1996 1997 intoBuf.ensureCapacity(8); 1998 intoBuf.writeByte((byte) 7); 2000 int year = this.dateTimeBindingCal.get(Calendar.YEAR); 2001 int month = this.dateTimeBindingCal.get(Calendar.MONTH) + 1; 2002 int date = this.dateTimeBindingCal.get(Calendar.DATE); 2003 2004 intoBuf.writeInt(year); 2005 intoBuf.writeByte((byte) month); 2006 intoBuf.writeByte((byte) date); 2007 2008 if (dt instanceof java.sql.Date ) { 2009 intoBuf.writeByte((byte) 0); 2010 intoBuf.writeByte((byte) 0); 2011 intoBuf.writeByte((byte) 0); 2012 } else { 2013 intoBuf.writeByte((byte) this.dateTimeBindingCal 2014 .get(Calendar.HOUR_OF_DAY)); 2015 intoBuf.writeByte((byte) this.dateTimeBindingCal 2016 .get(Calendar.MINUTE)); 2017 intoBuf.writeByte((byte) this.dateTimeBindingCal 2018 .get(Calendar.SECOND)); 2019 } 2020 } 2021 2022 private void storeDateTime(Buffer intoBuf, java.util.Date dt, MysqlIO mysql) 2023 throws SQLException { 2024 if (this.connection.versionMeetsMinimum(4, 1, 3)) { 2025 storeDateTime413AndNewer(intoBuf, dt); 2026 } else { 2027 storeDataTime412AndOlder(intoBuf, dt); 2028 } 2029 } 2030 2031 private void storeDateTime413AndNewer(Buffer intoBuf, java.util.Date dt) 2032 throws SQLException { 2033 if (this.dateTimeBindingCal == null) { 2036 this.dateTimeBindingCal = Calendar.getInstance(); 2037 } 2038 2039 this.dateTimeBindingCal.setTime(dt); 2040 2041 byte length = (byte) 7; 2042 2043 intoBuf.ensureCapacity(length); 2044 2045 if (dt instanceof java.sql.Timestamp ) { 2046 length = (byte) 11; 2047 } 2048 2049 intoBuf.writeByte(length); 2051 int year = this.dateTimeBindingCal.get(Calendar.YEAR); 2052 int month = this.dateTimeBindingCal.get(Calendar.MONTH) + 1; 2053 int date = this.dateTimeBindingCal.get(Calendar.DATE); 2054 2055 intoBuf.writeInt(year); 2056 intoBuf.writeByte((byte) month); 2057 intoBuf.writeByte((byte) date); 2058 2059 if (dt instanceof java.sql.Date ) { 2060 intoBuf.writeByte((byte) 0); 2061 intoBuf.writeByte((byte) 0); 2062 intoBuf.writeByte((byte) 0); 2063 } else { 2064 intoBuf.writeByte((byte) this.dateTimeBindingCal 2065 .get(Calendar.HOUR_OF_DAY)); 2066 intoBuf.writeByte((byte) this.dateTimeBindingCal 2067 .get(Calendar.MINUTE)); 2068 intoBuf.writeByte((byte) this.dateTimeBindingCal 2069 .get(Calendar.SECOND)); 2070 } 2071 2072 if (length == 11) { 2073 intoBuf.writeLong(((java.sql.Timestamp ) dt).getNanos()); 2074 } 2075 } 2076 2077 private void storeReader(MysqlIO mysql, int parameterIndex, Buffer packet, 2081 Reader inStream) throws SQLException { 2082 char[] buf = new char[8192]; 2083 2084 int numRead = 0; 2085 2086 int bytesInPacket = 0; 2087 int totalBytesRead = 0; 2088 int bytesReadAtLastSend = 0; 2089 int packetIsFullAt = this.connection.getBlobSendChunkSize(); 2090 2091 try { 2092 packet.clear(); 2093 packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); 2094 packet.writeLong(this.serverStatementId); 2095 packet.writeInt((parameterIndex)); 2096 2097 boolean readAny = false; 2098 2099 while ((numRead = inStream.read(buf)) != -1) { 2100 readAny = true; 2101 2102 byte[] valueAsBytes = StringUtils.getBytes(buf, null, 2103 this.connection.getEncoding(), this.connection 2104 .getServerCharacterEncoding(), 0, numRead, 2105 this.connection.parserKnowsUnicode()); 2106 2107 packet.writeBytesNoNull(valueAsBytes, 0, valueAsBytes.length); 2108 2109 bytesInPacket += valueAsBytes.length; 2110 totalBytesRead += valueAsBytes.length; 2111 2112 if (bytesInPacket >= packetIsFullAt) { 2113 bytesReadAtLastSend = totalBytesRead; 2114 2115 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, 2116 true, null); 2117 2118 bytesInPacket = 0; 2119 packet.clear(); 2120 packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); 2121 packet.writeLong(this.serverStatementId); 2122 packet.writeInt((parameterIndex)); 2123 } 2124 } 2125 2126 if (totalBytesRead != bytesReadAtLastSend) { 2127 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, 2128 null); 2129 } 2130 2131 if (!readAny) { 2132 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, 2133 null); 2134 } 2135 } catch (IOException ioEx) { 2136 throw new SQLException (Messages 2137 .getString("ServerPreparedStatement.24") + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR); 2139 } finally { 2140 if (inStream != null) { 2141 try { 2142 inStream.close(); 2143 } catch (IOException ioEx) { 2144 ; } 2146 } 2147 } 2148 } 2149 2150 private void storeStream(MysqlIO mysql, int parameterIndex, Buffer packet, 2151 InputStream inStream) throws SQLException { 2152 byte[] buf = new byte[16384]; 2153 2154 int numRead = 0; 2155 2156 try { 2157 int bytesInPacket = 0; 2158 int totalBytesRead = 0; 2159 int bytesReadAtLastSend = 0; 2160 int packetIsFullAt = this.connection.getBlobSendChunkSize(); 2161 2162 packet.clear(); 2163 packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); 2164 packet.writeLong(this.serverStatementId); 2165 packet.writeInt((parameterIndex)); 2166 2167 boolean readAny = false; 2168 2169 while ((numRead = inStream.read(buf)) != -1) { 2170 2171 readAny = true; 2172 2173 packet.writeBytesNoNull(buf, 0, numRead); 2174 bytesInPacket += numRead; 2175 totalBytesRead += numRead; 2176 2177 if (bytesInPacket >= packetIsFullAt) { 2178 bytesReadAtLastSend = totalBytesRead; 2179 2180 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, 2181 true, null); 2182 2183 bytesInPacket = 0; 2184 packet.clear(); 2185 packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); 2186 packet.writeLong(this.serverStatementId); 2187 packet.writeInt((parameterIndex)); 2188 } 2189 } 2190 2191 if (totalBytesRead != bytesReadAtLastSend) { 2192 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, 2193 null); 2194 } 2195 2196 if (!readAny) { 2197 mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, 2198 null); 2199 } 2200 } catch (IOException ioEx) { 2201 throw new SQLException (Messages 2202 .getString("ServerPreparedStatement.25") + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR); 2204 } finally { 2205 if (inStream != null) { 2206 try { 2207 inStream.close(); 2208 } catch (IOException ioEx) { 2209 ; } 2211 } 2212 } 2213 } 2214 2215 2218 public String toString() { 2219 StringBuffer toStringBuf = new StringBuffer (); 2220 2221 toStringBuf.append("com.mysql.jdbc.ServerPreparedStatement["); toStringBuf.append(this.serverStatementId); 2223 toStringBuf.append("] - "); 2225 try { 2226 toStringBuf.append(asSql()); 2227 } catch (SQLException sqlEx) { 2228 toStringBuf.append(Messages.getString("ServerPreparedStatement.6")); toStringBuf.append(sqlEx); 2230 } 2231 2232 return toStringBuf.toString(); 2233 } 2234} 2235 | Popular Tags |