~ubuntu-branches/ubuntu/trusty/mysql-connector-java/trusty

« back to all changes in this revision

Viewing changes to src/com/mysql/jdbc/ServerPreparedStatement.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Miguel Landaeta
  • Date: 2013-07-02 17:07:51 UTC
  • mfrom: (1.1.8) (3.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20130702170751-f4rszjabxg0391fr
Tags: 5.1.25-1
* New upstream release
* Refreshed the patches
* Added a patch to build with one JDK and removed the build
  dependency on java-gcj-compat-dev
* Updated Standards-Version to 3.9.4 (no changes)
* Use canonical URLs for the Vcs-* fields
* debian/rules: Improved the clean target to allow rebuilds
* Updated the watch file
* Renamed debian/README.Debian-source to README.source

[ Miguel Landaeta ] 
* Fix FTBFS with OpenJDK 7 (Closes: #706668)
* Remove Michael Koch from Uploaders list.
  Thanks for your work on this package. (Closes: #654122).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
 
2
 Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3
3
 
4
4
 
5
5
  The MySQL Connector/J is licensed under the terms of the GPLv2
51
51
 
52
52
import com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
53
53
import com.mysql.jdbc.exceptions.MySQLTimeoutException;
 
54
import com.mysql.jdbc.log.LogUtils;
54
55
import com.mysql.jdbc.profiler.ProfilerEvent;
55
56
 
56
57
/**
61
62
 *          mmatthews Exp $
62
63
 */
63
64
public class ServerPreparedStatement extends PreparedStatement {
64
 
        private static final Constructor JDBC_4_SPS_CTOR;
 
65
        private static final Constructor<?> JDBC_4_SPS_CTOR;
65
66
        
66
67
        static {
67
68
                if (Util.isJdbc4()) {
84
85
        
85
86
        protected static final int BLOB_STREAM_READ_BUF_SIZE = 8192;
86
87
 
87
 
        static class BatchedBindValues {
88
 
                BindValue[] batchedParameterValues;
 
88
        public static class BatchedBindValues {
 
89
                public BindValue[] batchedParameterValues;
89
90
 
90
91
                BatchedBindValues(BindValue[] paramVals) {
91
92
                        int numParams = paramVals.length;
100
101
 
101
102
        public static class BindValue {
102
103
 
103
 
                long boundBeforeExecutionNum = 0;
 
104
                public long boundBeforeExecutionNum = 0;
104
105
                
105
106
                public long bindLength; /* Default length of data */
106
107
 
107
 
                int bufferType; /* buffer type */
108
 
 
109
 
                byte byteBinding;
110
 
 
111
 
                double doubleBinding;
112
 
 
113
 
                float floatBinding;
114
 
 
115
 
                int intBinding;
 
108
                public int bufferType; /* buffer type */
 
109
 
 
110
                public double doubleBinding;
 
111
 
 
112
                public float floatBinding;
116
113
 
117
114
                public boolean isLongData; /* long data indicator */
118
115
 
119
116
                public boolean isNull; /* NULL indicator */
120
117
 
121
 
                boolean isSet = false; /* has this parameter been set? */
122
 
 
123
 
                long longBinding;
124
 
 
125
 
                short shortBinding;
 
118
                public boolean isSet = false; /* has this parameter been set? */
 
119
 
 
120
                public long longBinding; /* all integral values are stored here */
126
121
 
127
122
                public Object value; /* The value to store */
128
123
 
136
131
                        this.isNull = copyMe.isNull;
137
132
                        this.bufferType = copyMe.bufferType;
138
133
                        this.bindLength = copyMe.bindLength;
139
 
                        this.byteBinding = copyMe.byteBinding;
140
 
                        this.shortBinding = copyMe.shortBinding;
141
 
                        this.intBinding = copyMe.intBinding;
142
134
                        this.longBinding = copyMe.longBinding;
143
135
                        this.floatBinding = copyMe.floatBinding;
144
136
                        this.doubleBinding = copyMe.doubleBinding;
149
141
                        this.value = null;
150
142
                        this.isLongData = false;
151
143
 
152
 
                        this.byteBinding = 0;
153
 
                        this.shortBinding = 0;
154
 
                        this.intBinding = 0;
155
144
                        this.longBinding = 0L;
156
145
                        this.floatBinding = 0;
157
146
                        this.doubleBinding = 0D;
168
157
 
169
158
                        switch (this.bufferType) {
170
159
                        case MysqlDefs.FIELD_TYPE_TINY:
171
 
                                return String.valueOf(byteBinding);
172
160
                        case MysqlDefs.FIELD_TYPE_SHORT:
173
 
                                return String.valueOf(shortBinding);
174
161
                        case MysqlDefs.FIELD_TYPE_LONG:
175
 
                                return String.valueOf(intBinding);
176
162
                        case MysqlDefs.FIELD_TYPE_LONGLONG:
177
163
                                return String.valueOf(longBinding);
178
164
                        case MysqlDefs.FIELD_TYPE_FLOAT:
188
174
                        case MysqlDefs.FIELD_TYPE_VARCHAR:
189
175
                                if (quoteIfNeeded) {
190
176
                                        return "'" + String.valueOf(value) + "'";
191
 
                                } else {
192
 
                                        return String.valueOf(value);
193
177
                                }
 
178
                                return String.valueOf(value);
 
179
 
194
180
                        default:
195
181
                                if (value instanceof byte[]) {
196
182
                                        return "byte data";
197
 
 
198
 
                                } else {
199
 
                                        if (quoteIfNeeded) {
200
 
                                                return "'" + String.valueOf(value) + "'";
201
 
                                        } else {
202
 
                                                return String.valueOf(value);
203
 
                                        }
204
 
                                }
 
183
                                }
 
184
                                if (quoteIfNeeded) {
 
185
                                        return "'" + String.valueOf(value) + "'";
 
186
                                }
 
187
                                return String.valueOf(value);
205
188
                        }
206
189
                }
207
190
                
242
225
                        case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
243
226
                                if (value instanceof byte[]) {
244
227
                                        return ((byte[]) value).length;
245
 
                                } else {
246
 
                                        return ((String) value).length();
247
228
                                }
 
229
                                return ((String) value).length();
 
230
 
248
231
                        default: 
249
232
                                return 0;
250
233
                        }
252
235
        }
253
236
 
254
237
        /* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
255
 
        private static final byte MAX_DATE_REP_LENGTH = (byte) 5;
 
238
        //private static final byte MAX_DATE_REP_LENGTH = (byte) 5;
256
239
 
257
240
        /*
258
241
         * 1 (length) + 2 (year) + 1 (month) + 1 (day) + 1 (hour) + 1 (minute) + 1
259
242
         * (second) + 4 (microseconds)
260
243
         */
261
 
        private static final byte MAX_DATETIME_REP_LENGTH = 12;
 
244
        //private static final byte MAX_DATETIME_REP_LENGTH = 12;
262
245
 
263
246
        /*
264
247
         * 1 (length) + 1 (is negative) + 4 (day count) + 1 (hour) + 1 (minute) + 1
265
248
         * (seconds) + 4 (microseconds)
266
249
         */
267
 
        private static final byte MAX_TIME_REP_LENGTH = 13;
 
250
        //private static final byte MAX_TIME_REP_LENGTH = 13;
268
251
        
269
252
        private boolean hasOnDuplicateKeyUpdate = false;
270
253
 
405
388
                
406
389
                this.useAutoSlowLog = this.connection.getAutoSlowLog();
407
390
                this.useTrueBoolean = this.connection.versionMeetsMinimum(3, 21, 23);
408
 
                this.hasLimitClause = (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1); //$NON-NLS-1$
 
391
                int lim_id = StringUtils.indexOfIgnoreCase(sql, "LIMIT");
 
392
                if (lim_id != -1) {
 
393
                        boolean hasPreviosIdChar = false;
 
394
                        boolean hasFollowingIdChar = false;
 
395
                        if (lim_id > 0 && (
 
396
                                        sql.charAt(lim_id - 1) == '`' ||
 
397
                                        StringUtils.isValidIdChar(sql.charAt(lim_id - 1))
 
398
                                        )) {
 
399
                                hasPreviosIdChar = true;
 
400
                        }
 
401
                        if (lim_id + 5 < sql.length() && (
 
402
                                        sql.charAt(lim_id + 5) == '`' ||
 
403
                                        StringUtils.isValidIdChar(sql.charAt(lim_id + 5))
 
404
                                        )) {
 
405
                                hasFollowingIdChar = true;
 
406
                        }
 
407
                        if (!hasPreviosIdChar && !hasFollowingIdChar) {
 
408
                                this.hasLimitClause = true;
 
409
                        }
 
410
                } else {
 
411
                        this.hasLimitClause = false;
 
412
                }
 
413
                
409
414
                
410
415
                String statementComment = this.connection.getStatementComment();
411
416
 
448
453
         * 
449
454
         * @see StatementImpl#addBatch
450
455
         */
451
 
        public synchronized void addBatch() throws SQLException {
452
 
                checkClosed();
 
456
        public void addBatch() throws SQLException {
 
457
                synchronized (checkClosed().getConnectionMutex()) {
453
458
 
454
 
                if (this.batchedArgs == null) {
455
 
                        this.batchedArgs = new ArrayList();
 
459
                        if (this.batchedArgs == null) {
 
460
                                this.batchedArgs = new ArrayList<Object>();
 
461
                        }
 
462
        
 
463
                        this.batchedArgs.add(new BatchedBindValues(this.parameterBindings));
456
464
                }
457
 
 
458
 
                this.batchedArgs.add(new BatchedBindValues(this.parameterBindings));
459
465
        }
460
466
 
461
 
        protected synchronized String asSql(boolean quoteStreamsAndUnknowns) throws SQLException {
462
 
 
463
 
                if (this.isClosed) {
464
 
                        return "statement has been closed, no further internal information available";
465
 
                }
466
 
                
467
 
                PreparedStatement pStmtForSub = null;
468
 
 
469
 
                try {
470
 
                        pStmtForSub = PreparedStatement.getInstance(this.connection,
471
 
                                        this.originalSql, this.currentCatalog);
472
 
 
473
 
                        int numParameters = pStmtForSub.parameterCount;
474
 
                        int ourNumParameters = this.parameterCount;
475
 
 
476
 
                        for (int i = 0; (i < numParameters) && (i < ourNumParameters); i++) {
477
 
                                if (this.parameterBindings[i] != null) {
478
 
                                        if (this.parameterBindings[i].isNull) {
479
 
                                                pStmtForSub.setNull(i + 1, Types.NULL);
480
 
                                        } else {
481
 
                                                BindValue bindValue = this.parameterBindings[i];
482
 
 
483
 
                                                //
484
 
                                                // Handle primitives first
485
 
                                                //
486
 
                                                switch (bindValue.bufferType) {
487
 
 
488
 
                                                case MysqlDefs.FIELD_TYPE_TINY:
489
 
                                                        pStmtForSub.setByte(i + 1, bindValue.byteBinding);
490
 
                                                        break;
491
 
                                                case MysqlDefs.FIELD_TYPE_SHORT:
492
 
                                                        pStmtForSub.setShort(i + 1, bindValue.shortBinding);
493
 
                                                        break;
494
 
                                                case MysqlDefs.FIELD_TYPE_LONG:
495
 
                                                        pStmtForSub.setInt(i + 1, bindValue.intBinding);
496
 
                                                        break;
497
 
                                                case MysqlDefs.FIELD_TYPE_LONGLONG:
498
 
                                                        pStmtForSub.setLong(i + 1, bindValue.longBinding);
499
 
                                                        break;
500
 
                                                case MysqlDefs.FIELD_TYPE_FLOAT:
501
 
                                                        pStmtForSub.setFloat(i + 1, bindValue.floatBinding);
502
 
                                                        break;
503
 
                                                case MysqlDefs.FIELD_TYPE_DOUBLE:
504
 
                                                        pStmtForSub.setDouble(i + 1,
505
 
                                                                        bindValue.doubleBinding);
506
 
                                                        break;
507
 
                                                default:
508
 
                                                        pStmtForSub.setObject(i + 1,
509
 
                                                                        this.parameterBindings[i].value);
510
 
                                                        break;
 
467
        protected String asSql(boolean quoteStreamsAndUnknowns) throws SQLException {
 
468
 
 
469
                synchronized (checkClosed().getConnectionMutex()) {
 
470
                        
 
471
                        PreparedStatement pStmtForSub = null;
 
472
        
 
473
                        try {
 
474
                                pStmtForSub = PreparedStatement.getInstance(this.connection,
 
475
                                                this.originalSql, this.currentCatalog);
 
476
        
 
477
                                int numParameters = pStmtForSub.parameterCount;
 
478
                                int ourNumParameters = this.parameterCount;
 
479
        
 
480
                                for (int i = 0; (i < numParameters) && (i < ourNumParameters); i++) {
 
481
                                        if (this.parameterBindings[i] != null) {
 
482
                                                if (this.parameterBindings[i].isNull) {
 
483
                                                        pStmtForSub.setNull(i + 1, Types.NULL);
 
484
                                                } else {
 
485
                                                        BindValue bindValue = this.parameterBindings[i];
 
486
        
 
487
                                                        //
 
488
                                                        // Handle primitives first
 
489
                                                        //
 
490
                                                        switch (bindValue.bufferType) {
 
491
        
 
492
                                                        case MysqlDefs.FIELD_TYPE_TINY:
 
493
                                                                pStmtForSub.setByte(i + 1, (byte)bindValue.longBinding);
 
494
                                                                break;
 
495
                                                        case MysqlDefs.FIELD_TYPE_SHORT:
 
496
                                                                pStmtForSub.setShort(i + 1, (short)bindValue.longBinding);
 
497
                                                                break;
 
498
                                                        case MysqlDefs.FIELD_TYPE_LONG:
 
499
                                                                pStmtForSub.setInt(i + 1, (int)bindValue.longBinding);
 
500
                                                                break;
 
501
                                                        case MysqlDefs.FIELD_TYPE_LONGLONG:
 
502
                                                                pStmtForSub.setLong(i + 1, bindValue.longBinding);
 
503
                                                                break;
 
504
                                                        case MysqlDefs.FIELD_TYPE_FLOAT:
 
505
                                                                pStmtForSub.setFloat(i + 1, bindValue.floatBinding);
 
506
                                                                break;
 
507
                                                        case MysqlDefs.FIELD_TYPE_DOUBLE:
 
508
                                                                pStmtForSub.setDouble(i + 1,
 
509
                                                                                bindValue.doubleBinding);
 
510
                                                                break;
 
511
                                                        default:
 
512
                                                                pStmtForSub.setObject(i + 1,
 
513
                                                                                this.parameterBindings[i].value);
 
514
                                                                break;
 
515
                                                        }
511
516
                                                }
512
517
                                        }
513
518
                                }
514
 
                        }
515
 
 
516
 
                        return pStmtForSub.asSql(quoteStreamsAndUnknowns);
517
 
                } finally {
518
 
                        if (pStmtForSub != null) {
519
 
                                try {
520
 
                                        pStmtForSub.close();
521
 
                                } catch (SQLException sqlEx) {
522
 
                                        ; // ignore
 
519
        
 
520
                                return pStmtForSub.asSql(quoteStreamsAndUnknowns);
 
521
                        } finally {
 
522
                                if (pStmtForSub != null) {
 
523
                                        try {
 
524
                                                pStmtForSub.close();
 
525
                                        } catch (SQLException sqlEx) {
 
526
                                                ; // ignore
 
527
                                        }
523
528
                                }
524
529
                        }
525
530
                }
530
535
         * 
531
536
         * @see com.mysql.jdbc.Statement#checkClosed()
532
537
         */
533
 
        protected synchronized void checkClosed() throws SQLException {
 
538
        protected MySQLConnection checkClosed() throws SQLException {
534
539
                if (this.invalid) {
535
540
                        throw this.invalidationException;
536
541
                }
537
542
 
538
 
                super.checkClosed();
 
543
                return super.checkClosed();
539
544
        }
540
545
 
541
546
        /**
542
547
         * @see java.sql.PreparedStatement#clearParameters()
543
548
         */
544
549
        public void clearParameters() throws SQLException {
545
 
                checkClosed();
546
 
                clearParametersInternal(true);
 
550
                synchronized (checkClosed().getConnectionMutex()) {
 
551
                        clearParametersInternal(true);
 
552
                }
547
553
        }
548
554
 
549
 
        private synchronized void clearParametersInternal(boolean clearServerParameters)
 
555
        private void clearParametersInternal(boolean clearServerParameters)
550
556
                        throws SQLException {
551
557
                boolean hadLongData = false;
552
558
 
576
582
 
577
583
        private Calendar defaultTzCalendar;
578
584
 
579
 
        protected synchronized void setClosed(boolean flag) {
 
585
        protected void setClosed(boolean flag) {
580
586
                this.isClosed = flag;
581
587
        }
582
588
        
583
589
        /**
584
590
         * @see java.sql.Statement#close()
585
591
         */
586
 
        public synchronized void close() throws SQLException {
587
 
                if (this.isCached && !this.isClosed) {
588
 
                        clearParameters();
589
 
                        
590
 
                        this.isClosed = true;
591
 
                        
592
 
                        this.connection.recachePreparedStatement(this);
593
 
                        return;
 
592
        public void close() throws SQLException {
 
593
                try {
 
594
                        synchronized (checkClosed().getConnectionMutex()) {
 
595
                                if (this.isCached && !this.isClosed) {
 
596
                                        clearParameters();
 
597
                                        
 
598
                                        this.isClosed = true;
 
599
                                        
 
600
                                        this.connection.recachePreparedStatement(this);
 
601
                                        return;
 
602
                                }
 
603
                                
 
604
                                realClose(true, true);
 
605
                        }
 
606
                } catch (SQLException sqlEx) {
 
607
                        if (SQLError.SQL_STATE_CONNECTION_NOT_OPEN.equals(sqlEx.getSQLState())) {
 
608
                                return;
 
609
                        }
 
610
                        
 
611
                        throw sqlEx;
594
612
                }
595
 
                
596
 
                realClose(true, true);
597
 
        }
598
 
 
599
 
        private synchronized void dumpCloseForTestcase() {
600
 
                StringBuffer buf = new StringBuffer();
601
 
                this.connection.generateConnectionCommentBlock(buf);
602
 
                buf.append("DEALLOCATE PREPARE debug_stmt_");
603
 
                buf.append(this.statementId);
604
 
                buf.append(";\n");
605
 
 
606
 
                this.connection.dumpTestcaseQuery(buf.toString());
607
 
        }
608
 
 
609
 
        private synchronized void dumpExecuteForTestcase() throws SQLException {
610
 
                StringBuffer buf = new StringBuffer();
611
 
 
612
 
                for (int i = 0; i < this.parameterCount; i++) {
 
613
        }
 
614
 
 
615
        private void dumpCloseForTestcase() throws SQLException {
 
616
                synchronized (checkClosed().getConnectionMutex()) {
 
617
                        StringBuffer buf = new StringBuffer();
613
618
                        this.connection.generateConnectionCommentBlock(buf);
614
 
 
615
 
                        buf.append("SET @debug_stmt_param");
 
619
                        buf.append("DEALLOCATE PREPARE debug_stmt_");
616
620
                        buf.append(this.statementId);
617
 
                        buf.append("_");
618
 
                        buf.append(i);
619
 
                        buf.append("=");
620
 
 
621
 
                        if (this.parameterBindings[i].isNull) {
622
 
                                buf.append("NULL");
623
 
                        } else {
624
 
                                buf.append(this.parameterBindings[i].toString(true));
625
 
                        }
626
 
 
627
621
                        buf.append(";\n");
 
622
        
 
623
                        this.connection.dumpTestcaseQuery(buf.toString());
628
624
                }
629
 
 
630
 
                this.connection.generateConnectionCommentBlock(buf);
631
 
 
632
 
                buf.append("EXECUTE debug_stmt_");
633
 
                buf.append(this.statementId);
634
 
 
635
 
                if (this.parameterCount > 0) {
636
 
                        buf.append(" USING ");
 
625
        }
 
626
 
 
627
        private void dumpExecuteForTestcase() throws SQLException {
 
628
                synchronized (checkClosed().getConnectionMutex()) {
 
629
                        StringBuffer buf = new StringBuffer();
 
630
        
637
631
                        for (int i = 0; i < this.parameterCount; i++) {
638
 
                                if (i > 0) {
639
 
                                        buf.append(", ");
640
 
                                }
641
 
 
642
 
                                buf.append("@debug_stmt_param");
 
632
                                this.connection.generateConnectionCommentBlock(buf);
 
633
        
 
634
                                buf.append("SET @debug_stmt_param");
643
635
                                buf.append(this.statementId);
644
636
                                buf.append("_");
645
637
                                buf.append(i);
646
 
 
647
 
                        }
648
 
                }
649
 
 
650
 
                buf.append(";\n");
651
 
 
652
 
                this.connection.dumpTestcaseQuery(buf.toString());
653
 
        }
654
 
 
655
 
        private synchronized void dumpPrepareForTestcase() throws SQLException {
656
 
 
657
 
                StringBuffer buf = new StringBuffer(this.originalSql.length() + 64);
658
 
 
659
 
                this.connection.generateConnectionCommentBlock(buf);
660
 
 
661
 
                buf.append("PREPARE debug_stmt_");
662
 
                buf.append(this.statementId);
663
 
                buf.append(" FROM \"");
664
 
                buf.append(this.originalSql);
665
 
                buf.append("\";\n");
666
 
 
667
 
                this.connection.dumpTestcaseQuery(buf.toString());
668
 
        }
669
 
 
670
 
        protected synchronized int[] executeBatchSerially(int batchTimeout) throws SQLException {
671
 
                MySQLConnection locallyScopedConn = this.connection;
672
 
                
673
 
                if (locallyScopedConn == null) {
674
 
                        checkClosed();
675
 
                }
676
 
                
677
 
                if (locallyScopedConn.isReadOnly()) {
678
 
                        throw SQLError.createSQLException(Messages
679
 
                                        .getString("ServerPreparedStatement.2") //$NON-NLS-1$
680
 
                                        + Messages.getString("ServerPreparedStatement.3"), //$NON-NLS-1$
681
 
                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
682
 
                }
683
 
 
684
 
                checkClosed();
685
 
 
686
 
                synchronized (locallyScopedConn) {
 
638
                                buf.append("=");
 
639
        
 
640
                                if (this.parameterBindings[i].isNull) {
 
641
                                        buf.append("NULL");
 
642
                                } else {
 
643
                                        buf.append(this.parameterBindings[i].toString(true));
 
644
                                }
 
645
        
 
646
                                buf.append(";\n");
 
647
                        }
 
648
        
 
649
                        this.connection.generateConnectionCommentBlock(buf);
 
650
        
 
651
                        buf.append("EXECUTE debug_stmt_");
 
652
                        buf.append(this.statementId);
 
653
        
 
654
                        if (this.parameterCount > 0) {
 
655
                                buf.append(" USING ");
 
656
                                for (int i = 0; i < this.parameterCount; i++) {
 
657
                                        if (i > 0) {
 
658
                                                buf.append(", ");
 
659
                                        }
 
660
        
 
661
                                        buf.append("@debug_stmt_param");
 
662
                                        buf.append(this.statementId);
 
663
                                        buf.append("_");
 
664
                                        buf.append(i);
 
665
        
 
666
                                }
 
667
                        }
 
668
        
 
669
                        buf.append(";\n");
 
670
        
 
671
                        this.connection.dumpTestcaseQuery(buf.toString());
 
672
                }
 
673
        }
 
674
 
 
675
        private void dumpPrepareForTestcase() throws SQLException {
 
676
                synchronized (checkClosed().getConnectionMutex()) {
 
677
                        StringBuffer buf = new StringBuffer(this.originalSql.length() + 64);
 
678
        
 
679
                        this.connection.generateConnectionCommentBlock(buf);
 
680
        
 
681
                        buf.append("PREPARE debug_stmt_");
 
682
                        buf.append(this.statementId);
 
683
                        buf.append(" FROM \"");
 
684
                        buf.append(this.originalSql);
 
685
                        buf.append("\";\n");
 
686
        
 
687
                        this.connection.dumpTestcaseQuery(buf.toString());
 
688
                }
 
689
        }
 
690
 
 
691
        protected int[] executeBatchSerially(int batchTimeout) throws SQLException {
 
692
                synchronized (checkClosed().getConnectionMutex()) {
 
693
                        MySQLConnection locallyScopedConn = this.connection;
 
694
                        
 
695
                        
 
696
                        if (locallyScopedConn.isReadOnly()) {
 
697
                                throw SQLError.createSQLException(Messages
 
698
                                                .getString("ServerPreparedStatement.2") //$NON-NLS-1$
 
699
                                                + Messages.getString("ServerPreparedStatement.3"), //$NON-NLS-1$
 
700
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
701
                        }
 
702
                        
687
703
                        clearWarnings();
688
704
 
689
705
                        // Store this for later, we're going to 'swap' them out
698
714
                                        updateCounts = new int[nbrCommands];
699
715
 
700
716
                                        if (this.retrieveGeneratedKeys) {
701
 
                                                this.batchedGeneratedKeys = new ArrayList(nbrCommands);
 
717
                                                this.batchedGeneratedKeys = new ArrayList<ResultSetRow>(nbrCommands);
702
718
                                        }
703
719
 
704
720
                                        for (int i = 0; i < nbrCommands; i++) {
828
844
         * @see com.mysql.jdbc.PreparedStatement#executeInternal(int,
829
845
         *      com.mysql.jdbc.Buffer, boolean, boolean)
830
846
         */
831
 
        protected synchronized com.mysql.jdbc.ResultSetInternalMethods executeInternal(int maxRowsToRetrieve,
 
847
        protected com.mysql.jdbc.ResultSetInternalMethods executeInternal(int maxRowsToRetrieve,
832
848
                        Buffer sendPacket, boolean createStreamingResultSet,
833
849
                        boolean queryIsSelectOnly, Field[] metadataFromCache,
834
850
                        boolean isBatch)
835
851
                        throws SQLException {
836
 
                this.numberOfExecutions++;
837
 
 
838
 
                // We defer to server-side execution
839
 
                try {
840
 
                        return serverExecute(maxRowsToRetrieve, createStreamingResultSet, 
841
 
                                        metadataFromCache);
842
 
                } catch (SQLException sqlEx) {
843
 
                        // don't wrap SQLExceptions
844
 
                        if (this.connection.getEnablePacketDebug()) {
845
 
                                this.connection.getIO().dumpPacketRingBuffer();
846
 
                        }
847
 
 
848
 
                        if (this.connection.getDumpQueriesOnException()) {
849
 
                                String extractedSql = toString();
850
 
                                StringBuffer messageBuf = new StringBuffer(extractedSql
851
 
                                                .length() + 32);
852
 
                                messageBuf
853
 
                                                .append("\n\nQuery being executed when exception was thrown:\n");
854
 
                                messageBuf.append(extractedSql);
855
 
            messageBuf.append("\n\n");
856
 
 
857
 
                                sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf
858
 
                                                .toString(), getExceptionInterceptor());
859
 
                        }
860
 
 
861
 
                        throw sqlEx;
862
 
                } catch (Exception ex) {
863
 
                        if (this.connection.getEnablePacketDebug()) {
864
 
                                this.connection.getIO().dumpPacketRingBuffer();
865
 
                        }
866
 
 
867
 
                        SQLException sqlEx = SQLError.createSQLException(ex.toString(),
868
 
                                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
869
 
 
870
 
                        if (this.connection.getDumpQueriesOnException()) {
871
 
                                String extractedSql = toString();
872
 
                                StringBuffer messageBuf = new StringBuffer(extractedSql
873
 
                                                .length() + 32);
874
 
                                messageBuf
875
 
                                                .append("\n\nQuery being executed when exception was thrown:\n");
876
 
                                messageBuf.append(extractedSql);
877
 
            messageBuf.append("\n\n");
878
 
 
879
 
                                sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf
880
 
                                                .toString(), getExceptionInterceptor());
881
 
                        }
882
 
 
883
 
                        sqlEx.initCause(ex);
884
 
                        
885
 
                        throw sqlEx;
 
852
                synchronized (checkClosed().getConnectionMutex()) {
 
853
                        this.numberOfExecutions++;
 
854
        
 
855
                        // We defer to server-side execution
 
856
                        try {
 
857
                                return serverExecute(maxRowsToRetrieve, createStreamingResultSet, 
 
858
                                                metadataFromCache);
 
859
                        } catch (SQLException sqlEx) {
 
860
                                // don't wrap SQLExceptions
 
861
                                if (this.connection.getEnablePacketDebug()) {
 
862
                                        this.connection.getIO().dumpPacketRingBuffer();
 
863
                                }
 
864
        
 
865
                                if (this.connection.getDumpQueriesOnException()) {
 
866
                                        String extractedSql = toString();
 
867
                                        StringBuffer messageBuf = new StringBuffer(extractedSql
 
868
                                                        .length() + 32);
 
869
                                        messageBuf
 
870
                                                        .append("\n\nQuery being executed when exception was thrown:\n");
 
871
                                        messageBuf.append(extractedSql);
 
872
                    messageBuf.append("\n\n");
 
873
        
 
874
                                        sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf
 
875
                                                        .toString(), getExceptionInterceptor());
 
876
                                }
 
877
        
 
878
                                throw sqlEx;
 
879
                        } catch (Exception ex) {
 
880
                                if (this.connection.getEnablePacketDebug()) {
 
881
                                        this.connection.getIO().dumpPacketRingBuffer();
 
882
                                }
 
883
        
 
884
                                SQLException sqlEx = SQLError.createSQLException(ex.toString(),
 
885
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
886
        
 
887
                                if (this.connection.getDumpQueriesOnException()) {
 
888
                                        String extractedSql = toString();
 
889
                                        StringBuffer messageBuf = new StringBuffer(extractedSql
 
890
                                                        .length() + 32);
 
891
                                        messageBuf
 
892
                                                        .append("\n\nQuery being executed when exception was thrown:\n");
 
893
                                        messageBuf.append(extractedSql);
 
894
                    messageBuf.append("\n\n");
 
895
        
 
896
                                        sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf
 
897
                                                        .toString(), getExceptionInterceptor());
 
898
                                }
 
899
        
 
900
                                sqlEx.initCause(ex);
 
901
                                
 
902
                                throw sqlEx;
 
903
                        }
886
904
                }
887
905
        }
888
906
 
912
930
         * @return
913
931
         * @throws SQLException
914
932
         */
915
 
        protected synchronized BindValue getBinding(int parameterIndex, boolean forLongData)
 
933
        protected  BindValue getBinding(int parameterIndex, boolean forLongData)
916
934
                        throws SQLException {
917
 
                checkClosed();
 
935
                synchronized (checkClosed().getConnectionMutex()) {
918
936
                
919
 
                if (this.parameterBindings.length == 0) {
920
 
                        throw SQLError.createSQLException(Messages
921
 
                                        .getString("ServerPreparedStatement.8"), //$NON-NLS-1$
922
 
                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
923
 
                }
924
 
 
925
 
                parameterIndex--;
926
 
 
927
 
                if ((parameterIndex < 0)
928
 
                                || (parameterIndex >= this.parameterBindings.length)) {
929
 
                        throw SQLError.createSQLException(Messages
930
 
                                        .getString("ServerPreparedStatement.9") //$NON-NLS-1$
931
 
                                        + (parameterIndex + 1)
932
 
                                        + Messages.getString("ServerPreparedStatement.10") //$NON-NLS-1$
933
 
                                        + this.parameterBindings.length,
934
 
                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
935
 
                }
936
 
 
937
 
                if (this.parameterBindings[parameterIndex] == null) {
938
 
                        this.parameterBindings[parameterIndex] = new BindValue();
939
 
                } else {
940
 
                        if (this.parameterBindings[parameterIndex].isLongData
941
 
                                        && !forLongData) {
942
 
                                this.detectedLongParameterSwitch = true;
943
 
                        }
944
 
                }
945
 
 
946
 
                this.parameterBindings[parameterIndex].isSet = true;
947
 
                this.parameterBindings[parameterIndex].boundBeforeExecutionNum = this.numberOfExecutions;
948
 
 
949
 
                return this.parameterBindings[parameterIndex];
 
937
                        if (this.parameterBindings.length == 0) {
 
938
                                throw SQLError.createSQLException(Messages
 
939
                                                .getString("ServerPreparedStatement.8"), //$NON-NLS-1$
 
940
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
941
                        }
 
942
        
 
943
                        parameterIndex--;
 
944
        
 
945
                        if ((parameterIndex < 0)
 
946
                                        || (parameterIndex >= this.parameterBindings.length)) {
 
947
                                throw SQLError.createSQLException(Messages
 
948
                                                .getString("ServerPreparedStatement.9") //$NON-NLS-1$
 
949
                                                + (parameterIndex + 1)
 
950
                                                + Messages.getString("ServerPreparedStatement.10") //$NON-NLS-1$
 
951
                                                + this.parameterBindings.length,
 
952
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
953
                        }
 
954
        
 
955
                        if (this.parameterBindings[parameterIndex] == null) {
 
956
                                this.parameterBindings[parameterIndex] = new BindValue();
 
957
                        } else {
 
958
                                if (this.parameterBindings[parameterIndex].isLongData
 
959
                                                && !forLongData) {
 
960
                                        this.detectedLongParameterSwitch = true;
 
961
                                }
 
962
                        }
 
963
        
 
964
                        this.parameterBindings[parameterIndex].isSet = true;
 
965
                        this.parameterBindings[parameterIndex].boundBeforeExecutionNum = this.numberOfExecutions;
 
966
        
 
967
                        return this.parameterBindings[parameterIndex];
 
968
                }
 
969
        }
 
970
 
 
971
        /**
 
972
         * Return current bind values for use by Statement Interceptors.
 
973
         * @return the bind values as set by setXXX and stored by addBatch
 
974
         * @see #executeBatch()
 
975
         * @see #addBatch()
 
976
         */
 
977
        public BindValue[] getParameterBindValues() {
 
978
                return parameterBindings;
950
979
        }
951
980
 
952
981
        /**
953
982
         * @see com.mysql.jdbc.PreparedStatement#getBytes(int)
954
983
         */
955
 
        synchronized byte[] getBytes(int parameterIndex) throws SQLException {
956
 
                BindValue bindValue = getBinding(parameterIndex, false);
957
 
 
958
 
                if (bindValue.isNull) {
959
 
                        return null;
960
 
                } else if (bindValue.isLongData) {
961
 
                        throw SQLError.notImplemented();
962
 
                } else {
963
 
                        if (this.outByteBuffer == null) {
964
 
                                this.outByteBuffer = new Buffer(this.connection
965
 
                                                .getNetBufferLength());
 
984
        byte[] getBytes(int parameterIndex) throws SQLException {
 
985
                synchronized (checkClosed().getConnectionMutex()) {
 
986
                        BindValue bindValue = getBinding(parameterIndex, false);
 
987
        
 
988
                        if (bindValue.isNull) {
 
989
                                return null;
 
990
                        } else if (bindValue.isLongData) {
 
991
                                throw SQLError.notImplemented();
 
992
                        } else {
 
993
                                if (this.outByteBuffer == null) {
 
994
                                        this.outByteBuffer = new Buffer(this.connection
 
995
                                                        .getNetBufferLength());
 
996
                                }
 
997
        
 
998
                                this.outByteBuffer.clear();
 
999
        
 
1000
                                int originalPosition = this.outByteBuffer.getPosition();
 
1001
        
 
1002
                                storeBinding(this.outByteBuffer, bindValue, this.connection.getIO());
 
1003
        
 
1004
                                int newPosition = this.outByteBuffer.getPosition();
 
1005
        
 
1006
                                int length = newPosition - originalPosition;
 
1007
        
 
1008
                                byte[] valueAsBytes = new byte[length];
 
1009
        
 
1010
                                System.arraycopy(this.outByteBuffer.getByteBuffer(),
 
1011
                                                originalPosition, valueAsBytes, 0, length);
 
1012
        
 
1013
                                return valueAsBytes;
966
1014
                        }
967
 
 
968
 
                        this.outByteBuffer.clear();
969
 
 
970
 
                        int originalPosition = this.outByteBuffer.getPosition();
971
 
 
972
 
                        storeBinding(this.outByteBuffer, bindValue, this.connection.getIO());
973
 
 
974
 
                        int newPosition = this.outByteBuffer.getPosition();
975
 
 
976
 
                        int length = newPosition - originalPosition;
977
 
 
978
 
                        byte[] valueAsBytes = new byte[length];
979
 
 
980
 
                        System.arraycopy(this.outByteBuffer.getByteBuffer(),
981
 
                                        originalPosition, valueAsBytes, 0, length);
982
 
 
983
 
                        return valueAsBytes;
984
1015
                }
985
1016
        }
986
1017
 
987
1018
        /**
988
1019
         * @see java.sql.PreparedStatement#getMetaData()
989
1020
         */
990
 
        public synchronized java.sql.ResultSetMetaData getMetaData() throws SQLException {
991
 
                checkClosed();
 
1021
        public java.sql.ResultSetMetaData getMetaData() throws SQLException {
 
1022
                synchronized (checkClosed().getConnectionMutex()) {
992
1023
 
993
 
                if (this.resultFields == null) {
994
 
                        return null;
 
1024
                        if (this.resultFields == null) {
 
1025
                                return null;
 
1026
                        }
 
1027
        
 
1028
                        return new ResultSetMetaData(this.resultFields, 
 
1029
                                        this.connection.getUseOldAliasMetadataBehavior(), getExceptionInterceptor());
995
1030
                }
996
 
 
997
 
                return new ResultSetMetaData(this.resultFields, 
998
 
                                this.connection.getUseOldAliasMetadataBehavior(), getExceptionInterceptor());
999
1031
        }
1000
1032
 
1001
1033
        /**
1002
1034
         * @see java.sql.PreparedStatement#getParameterMetaData()
1003
1035
         */
1004
 
        public synchronized ParameterMetaData getParameterMetaData() throws SQLException {
1005
 
                checkClosed();
 
1036
        public ParameterMetaData getParameterMetaData() throws SQLException {
 
1037
                synchronized (checkClosed().getConnectionMutex()) {
1006
1038
                
1007
 
                if (this.parameterMetaData == null) {
1008
 
                        this.parameterMetaData = new MysqlParameterMetadata(
1009
 
                                        this.parameterFields, this.parameterCount, getExceptionInterceptor());
 
1039
                        if (this.parameterMetaData == null) {
 
1040
                                this.parameterMetaData = new MysqlParameterMetadata(
 
1041
                                                this.parameterFields, this.parameterCount, getExceptionInterceptor());
 
1042
                        }
 
1043
                        
 
1044
                        return this.parameterMetaData;
1010
1045
                }
1011
 
                
1012
 
                return this.parameterMetaData;
1013
1046
        }
1014
1047
 
1015
1048
        /**
1029
1062
         * @throws SQLException
1030
1063
         *             if an error occurs
1031
1064
         */
1032
 
        protected synchronized void realClose(boolean calledExplicitly, 
 
1065
        protected void realClose(boolean calledExplicitly, 
1033
1066
                        boolean closeOpenResults) throws SQLException {
1034
 
                if (this.isClosed) {
1035
 
                        return;
 
1067
                MySQLConnection locallyScopedConn;
 
1068
                
 
1069
                try {
 
1070
                        locallyScopedConn = checkClosed();
 
1071
                } catch (SQLException sqlEx) {
 
1072
                        return; // already closed
1036
1073
                }
1037
 
 
1038
 
                if (this.connection != null) {
1039
 
                        if (this.connection.getAutoGenerateTestcaseScript()) {
1040
 
                                dumpCloseForTestcase();
1041
 
                        }
1042
 
 
1043
 
                        //
1044
 
                        // Don't communicate with the server if we're being
1045
 
                        // called from the finalizer...
1046
 
                        // 
1047
 
                        // This will leak server resources, but if we don't do this,
1048
 
                        // we'll deadlock (potentially, because there's no guarantee
1049
 
                        // when, what order, and what concurrency finalizers will be
1050
 
                        // called with). Well-behaved programs won't rely on finalizers
1051
 
                        // to clean up their statements.
1052
 
                        //
1053
 
 
1054
 
                        SQLException exceptionDuringClose = null;
1055
 
 
1056
 
                        if (calledExplicitly && !this.connection.isClosed()) {
1057
 
                                synchronized (this.connection) {
1058
 
                                        try {
1059
 
 
1060
 
                                                MysqlIO mysql = this.connection.getIO();
1061
 
 
1062
 
                                                Buffer packet = mysql.getSharedSendPacket();
1063
 
 
1064
 
                                                packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT);
1065
 
                                                packet.writeLong(this.serverStatementId);
1066
 
 
1067
 
                                                mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null,
1068
 
                                                                packet, true, null, 0);
1069
 
                                        } catch (SQLException sqlEx) {
1070
 
                                                exceptionDuringClose = sqlEx;
 
1074
                
 
1075
                synchronized (locallyScopedConn.getConnectionMutex()) {
 
1076
 
 
1077
                        if (this.connection != null) {
 
1078
                                if (this.connection.getAutoGenerateTestcaseScript()) {
 
1079
                                        dumpCloseForTestcase();
 
1080
                                }
 
1081
        
 
1082
                                //
 
1083
                                // Don't communicate with the server if we're being
 
1084
                                // called from the finalizer...
 
1085
                                // 
 
1086
                                // This will leak server resources, but if we don't do this,
 
1087
                                // we'll deadlock (potentially, because there's no guarantee
 
1088
                                // when, what order, and what concurrency finalizers will be
 
1089
                                // called with). Well-behaved programs won't rely on finalizers
 
1090
                                // to clean up their statements.
 
1091
                                //
 
1092
        
 
1093
                                SQLException exceptionDuringClose = null;
 
1094
        
 
1095
                                if (calledExplicitly && !this.connection.isClosed()) {
 
1096
                                        synchronized (this.connection.getConnectionMutex()) {
 
1097
                                                try {
 
1098
        
 
1099
                                                        MysqlIO mysql = this.connection.getIO();
 
1100
        
 
1101
                                                        Buffer packet = mysql.getSharedSendPacket();
 
1102
        
 
1103
                                                        packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT);
 
1104
                                                        packet.writeLong(this.serverStatementId);
 
1105
        
 
1106
                                                        mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null,
 
1107
                                                                        packet, true, null, 0);
 
1108
                                                } catch (SQLException sqlEx) {
 
1109
                                                        exceptionDuringClose = sqlEx;
 
1110
                                                }
1071
1111
                                        }
1072
1112
                                }
1073
 
                        }
1074
 
 
1075
 
                        super.realClose(calledExplicitly, closeOpenResults);
1076
 
 
1077
 
                        clearParametersInternal(false);
1078
 
                        this.parameterBindings = null;
1079
 
 
1080
 
                        this.parameterFields = null;
1081
 
                        this.resultFields = null;
1082
 
 
1083
 
                        if (exceptionDuringClose != null) {
1084
 
                                throw exceptionDuringClose;
 
1113
        
 
1114
                                super.realClose(calledExplicitly, closeOpenResults);
 
1115
        
 
1116
                                clearParametersInternal(false);
 
1117
                                this.parameterBindings = null;
 
1118
        
 
1119
                                this.parameterFields = null;
 
1120
                                this.resultFields = null;
 
1121
        
 
1122
                                if (exceptionDuringClose != null) {
 
1123
                                        throw exceptionDuringClose;
 
1124
                                }
1085
1125
                        }
1086
1126
                }
1087
1127
        }
1093
1133
         * @throws SQLException
1094
1134
         *             if an error occurs.
1095
1135
         */
1096
 
        protected synchronized void rePrepare() throws SQLException {
1097
 
                this.invalidationException = null;
1098
 
 
1099
 
                try {
1100
 
                        serverPrepare(this.originalSql);
1101
 
                } catch (SQLException sqlEx) {
1102
 
                        // don't wrap SQLExceptions
1103
 
                        this.invalidationException = sqlEx;
1104
 
                } catch (Exception ex) {
1105
 
                        this.invalidationException = SQLError.createSQLException(ex.toString(),
1106
 
                                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
1107
 
                        this.invalidationException.initCause(ex);
1108
 
                }
1109
 
 
1110
 
                if (this.invalidationException != null) {
1111
 
                        this.invalid = true;
1112
 
 
1113
 
                        this.parameterBindings = null;
1114
 
 
1115
 
                        this.parameterFields = null;
1116
 
                        this.resultFields = null;
1117
 
 
1118
 
                        if (this.results != null) {
 
1136
        protected void rePrepare() throws SQLException {
 
1137
                synchronized (checkClosed().getConnectionMutex()) {
 
1138
                        this.invalidationException = null;
 
1139
        
 
1140
                        try {
 
1141
                                serverPrepare(this.originalSql);
 
1142
                        } catch (SQLException sqlEx) {
 
1143
                                // don't wrap SQLExceptions
 
1144
                                this.invalidationException = sqlEx;
 
1145
                        } catch (Exception ex) {
 
1146
                                this.invalidationException = SQLError.createSQLException(ex.toString(),
 
1147
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
1148
                                this.invalidationException.initCause(ex);
 
1149
                        }
 
1150
        
 
1151
                        if (this.invalidationException != null) {
 
1152
                                this.invalid = true;
 
1153
        
 
1154
                                this.parameterBindings = null;
 
1155
        
 
1156
                                this.parameterFields = null;
 
1157
                                this.resultFields = null;
 
1158
        
 
1159
                                if (this.results != null) {
 
1160
                                        try {
 
1161
                                                this.results.close();
 
1162
                                        } catch (Exception ex) {
 
1163
                                                ;
 
1164
                                        }
 
1165
                                }
 
1166
 
 
1167
                                if (this.generatedKeysResults != null) {
 
1168
                                        try {
 
1169
                                                this.generatedKeysResults.close();
 
1170
                                        } catch (Exception ex) {
 
1171
                                                ;
 
1172
                                        }
 
1173
                                }
 
1174
 
1119
1175
                                try {
1120
 
                                        this.results.close();
1121
 
                                } catch (Exception ex) {
 
1176
                                        closeAllOpenResults();
 
1177
                                } catch (Exception e) {
1122
1178
                                        ;
1123
1179
                                }
1124
 
                        }
1125
 
 
1126
 
                        if (this.connection != null) {
1127
 
                                if (this.maxRowsChanged) {
1128
 
                                        this.connection.unsetMaxRows(this);
1129
 
                                }
1130
 
 
1131
 
                                if (!this.connection.getDontTrackOpenResources()) {
1132
 
                                        this.connection.unregisterStatement(this);
 
1180
                                
 
1181
                                if (this.connection != null) {
 
1182
                                        if (this.maxRowsChanged) {
 
1183
                                                this.connection.unsetMaxRows(this);
 
1184
                                        }
 
1185
        
 
1186
                                        if (!this.connection.getDontTrackOpenResources()) {
 
1187
                                                this.connection.unregisterStatement(this);
 
1188
                                        }
1133
1189
                                }
1134
1190
                        }
1135
1191
                }
1168
1224
         * 
1169
1225
         * @throws SQLException
1170
1226
         */
1171
 
        private synchronized com.mysql.jdbc.ResultSetInternalMethods serverExecute(int maxRowsToRetrieve,
 
1227
        private com.mysql.jdbc.ResultSetInternalMethods serverExecute(int maxRowsToRetrieve,
1172
1228
                        boolean createStreamingResultSet, 
1173
1229
                        Field[] metadataFromCache) throws SQLException {
1174
 
                synchronized (this.connection) {
 
1230
                synchronized (checkClosed().getConnectionMutex()) {
1175
1231
                        MysqlIO mysql = this.connection.getIO();
1176
1232
 
1177
1233
                        if (mysql.shouldIntercept()) {
1196
1252
                                                                        .getString("ServerPreparedStatement.11") //$NON-NLS-1$
1197
1253
                                                                        + Messages.getString("ServerPreparedStatement.12"), //$NON-NLS-1$
1198
1254
                                                                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
1199
 
                                                } else {
1200
 
                                                        firstFound = true;
1201
 
                                                        boundTimeToCheck = this.parameterBindings[i].boundBeforeExecutionNum;
1202
1255
                                                }
 
1256
                                                firstFound = true;
 
1257
                                                boundTimeToCheck = this.parameterBindings[i].boundBeforeExecutionNum;
1203
1258
                                        }
1204
1259
                                }
1205
1260
                                
1243
1298
                        packet.writeByte((byte) MysqlDefs.COM_EXECUTE);
1244
1299
                        packet.writeLong(this.serverStatementId);
1245
1300
 
1246
 
                        boolean usingCursor = false;
 
1301
//                      boolean usingCursor = false;
1247
1302
 
1248
1303
                        if (this.connection.versionMeetsMinimum(4, 1, 2)) {
1249
1304
                                // we only create cursor-backed result sets if
1258
1313
                                                && getResultSetConcurrency() == ResultSet.CONCUR_READ_ONLY
1259
1314
                                                && getFetchSize() > 0) {
1260
1315
                                        packet.writeByte(MysqlDefs.OPEN_CURSOR_FLAG);
1261
 
                                        usingCursor = true;
 
1316
//                                      usingCursor = true;
1262
1317
                                } else {
1263
1318
                                        packet.writeByte((byte) 0); // placeholder for flags
1264
1319
                                }
1339
1394
                                                        this.timeoutInMillis);
1340
1395
                                }
1341
1396
                                
 
1397
                                statementBegins();
 
1398
 
1342
1399
                                Buffer resultPacket = mysql.sendCommand(MysqlDefs.COM_EXECUTE,
1343
1400
                                        null, packet, false, null, 0);
1344
1401
                                
1416
1473
                                                                                getId(), 0, System.currentTimeMillis(),
1417
1474
                                                                                elapsedTime, mysql
1418
1475
                                                                                                .getQueryTimingUnits(), null,
1419
 
                                                                                new Throwable(), mesgBuf.toString()));
 
1476
                                                                                                LogUtils.findCallingClassAndMethod(new Throwable()), mesgBuf.toString()));
1420
1477
                                        }
1421
1478
 
1422
1479
                                        if (gatherPerformanceMetrics) {
1434
1491
                                                        ProfilerEvent.TYPE_EXECUTE,
1435
1492
                                                        "", this.currentCatalog, //$NON-NLS-1$
1436
1493
                                                        this.connectionId, this.statementId, -1, System
1437
 
                                                                        .currentTimeMillis(), (int) (mysql
1438
 
                                                                        .getCurrentTimeNanosOrMillis() - begin),
1439
 
                                                        mysql.getQueryTimingUnits(), null, new Throwable(),
 
1494
                                                                        .currentTimeMillis(), mysql
 
1495
                                                                        .getCurrentTimeNanosOrMillis() - begin,
 
1496
                                                        mysql.getQueryTimingUnits(), null, LogUtils.findCallingClassAndMethod(new Throwable()),
1440
1497
                                                        truncateQueryToLog(asSql(true))));
1441
1498
                                }
1442
1499
        
1464
1521
                                                        getId(), 0 /* FIXME rs.resultId */, System.currentTimeMillis(),
1465
1522
                                                        (fetchEndTime - queryEndTime), mysql
1466
1523
                                                                        .getQueryTimingUnits(), null,
1467
 
                                                        new Throwable(), null));
 
1524
                                                                        LogUtils.findCallingClassAndMethod(new Throwable()), null));
1468
1525
                                }
1469
1526
        
1470
1527
                                if (queryWasSlow && this.connection.getExplainSlowQueries()) {
1471
1528
                                        String queryAsString = asSql(true);
1472
1529
 
1473
 
                                        mysql.explainSlowQuery(queryAsString.getBytes(),
 
1530
                                        mysql.explainSlowQuery(StringUtils.getBytes(queryAsString),
1474
1531
                                                        queryAsString);
1475
1532
                                }
1476
1533
                                
1495
1552
                                
1496
1553
                                throw sqlEx;
1497
1554
                        } finally {
 
1555
                                this.statementExecuting.set(false);
 
1556
                                
1498
1557
                                if (timeoutTask != null) {
1499
1558
                                        timeoutTask.cancel();
1500
1559
                                        this.connection.getCancelTimer().purge();
1530
1589
         * @throws SQLException
1531
1590
         *             if an error occurs.
1532
1591
         */
1533
 
        private synchronized void serverLongData(int parameterIndex, BindValue longData)
 
1592
        private void serverLongData(int parameterIndex, BindValue longData)
1534
1593
                        throws SQLException {
1535
 
                synchronized (this.connection) {
 
1594
                synchronized (checkClosed().getConnectionMutex()) {
1536
1595
                        MysqlIO mysql = this.connection.getIO();
1537
1596
 
1538
1597
                        Buffer packet = mysql.getSharedSendPacket();
1565
1624
                }
1566
1625
        }
1567
1626
 
1568
 
        private synchronized void serverPrepare(String sql) throws SQLException {
1569
 
                synchronized (this.connection) {
 
1627
        private void serverPrepare(String sql) throws SQLException {
 
1628
                synchronized (checkClosed().getConnectionMutex()) {
1570
1629
                        MysqlIO mysql = this.connection.getIO();
1571
1630
 
1572
1631
                        if (this.connection.getAutoGenerateTestcaseScript()) {
1629
1688
                                                        System.currentTimeMillis(), 
1630
1689
                                                        mysql.getCurrentTimeNanosOrMillis() - begin, 
1631
1690
                                                        mysql.getQueryTimingUnits(), null,
1632
 
                                                        new Throwable(), truncateQueryToLog(sql)));
 
1691
                                                        LogUtils.findCallingClassAndMethod(new Throwable()), truncateQueryToLog(sql)));
1633
1692
                                }
1634
1693
 
1635
1694
                                if (this.parameterCount > 0) {
1687
1746
                }
1688
1747
        }
1689
1748
 
1690
 
        private synchronized String truncateQueryToLog(String sql) {
1691
 
                String query = null;
1692
 
                
1693
 
                if (sql.length() > this.connection.getMaxQuerySizeToLog()) {
1694
 
                        StringBuffer queryBuf = new StringBuffer(
1695
 
                                        this.connection.getMaxQuerySizeToLog() + 12);
1696
 
                        queryBuf.append(sql.substring(0, this.connection.getMaxQuerySizeToLog()));
1697
 
                        queryBuf.append(Messages.getString("MysqlIO.25"));
1698
 
                        
1699
 
                        query = queryBuf.toString();
1700
 
                } else {
1701
 
                        query = sql;
 
1749
        private String truncateQueryToLog(String sql) throws SQLException {
 
1750
                synchronized (checkClosed().getConnectionMutex()) {
 
1751
                        String query = null;
 
1752
                        
 
1753
                        if (sql.length() > this.connection.getMaxQuerySizeToLog()) {
 
1754
                                StringBuffer queryBuf = new StringBuffer(
 
1755
                                                this.connection.getMaxQuerySizeToLog() + 12);
 
1756
                                queryBuf.append(sql.substring(0, this.connection.getMaxQuerySizeToLog()));
 
1757
                                queryBuf.append(Messages.getString("MysqlIO.25"));
 
1758
                                
 
1759
                                query = queryBuf.toString();
 
1760
                        } else {
 
1761
                                query = sql;
 
1762
                        }
 
1763
                        
 
1764
                        return query;
1702
1765
                }
1703
 
                
1704
 
                return query;
1705
1766
        }
1706
1767
 
1707
 
        private synchronized void serverResetStatement() throws SQLException {
1708
 
                synchronized (this.connection) {
 
1768
        private void serverResetStatement() throws SQLException {
 
1769
                synchronized (checkClosed().getConnectionMutex()) {
1709
1770
 
1710
1771
                        MysqlIO mysql = this.connection.getIO();
1711
1772
 
1743
1804
         * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream,
1744
1805
         *      int)
1745
1806
         */
1746
 
        public synchronized void setAsciiStream(int parameterIndex, InputStream x, int length)
 
1807
        public void setAsciiStream(int parameterIndex, InputStream x, int length)
1747
1808
                        throws SQLException {
1748
 
                checkClosed();
1749
 
 
1750
 
                if (x == null) {
1751
 
                        setNull(parameterIndex, java.sql.Types.BINARY);
1752
 
                } else {
1753
 
                        BindValue binding = getBinding(parameterIndex, true);
1754
 
                        setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
1755
 
 
1756
 
                        binding.value = x;
1757
 
                        binding.isNull = false;
1758
 
                        binding.isLongData = true;
1759
 
 
1760
 
                        if (this.connection.getUseStreamLengthsInPrepStmts()) {
1761
 
                                binding.bindLength = length;
 
1809
                synchronized (checkClosed().getConnectionMutex()) {
 
1810
                        if (x == null) {
 
1811
                                setNull(parameterIndex, java.sql.Types.BINARY);
1762
1812
                        } else {
1763
 
                                binding.bindLength = -1;
 
1813
                                BindValue binding = getBinding(parameterIndex, true);
 
1814
                                setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
 
1815
        
 
1816
                                binding.value = x;
 
1817
                                binding.isNull = false;
 
1818
                                binding.isLongData = true;
 
1819
        
 
1820
                                if (this.connection.getUseStreamLengthsInPrepStmts()) {
 
1821
                                        binding.bindLength = length;
 
1822
                                } else {
 
1823
                                        binding.bindLength = -1;
 
1824
                                }
1764
1825
                        }
1765
1826
                }
1766
1827
        }
1768
1829
        /**
1769
1830
         * @see java.sql.PreparedStatement#setBigDecimal(int, java.math.BigDecimal)
1770
1831
         */
1771
 
        public synchronized void setBigDecimal(int parameterIndex, BigDecimal x)
 
1832
        public void setBigDecimal(int parameterIndex, BigDecimal x)
1772
1833
                        throws SQLException {
1773
 
                checkClosed();
1774
 
 
1775
 
                if (x == null) {
1776
 
                        setNull(parameterIndex, java.sql.Types.DECIMAL);
1777
 
                } else {
1778
 
                
1779
 
                        BindValue binding = getBinding(parameterIndex, false);
1780
 
 
1781
 
                        if (this.connection.versionMeetsMinimum(5, 0, 3)) {
1782
 
                                setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL);
 
1834
                synchronized (checkClosed().getConnectionMutex()) {
 
1835
 
 
1836
                        if (x == null) {
 
1837
                                setNull(parameterIndex, java.sql.Types.DECIMAL);
1783
1838
                        } else {
1784
 
                                setType(binding, this.stringTypeCode);
 
1839
                        
 
1840
                                BindValue binding = getBinding(parameterIndex, false);
 
1841
        
 
1842
                                if (this.connection.versionMeetsMinimum(5, 0, 3)) {
 
1843
                                        setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL);
 
1844
                                } else {
 
1845
                                        setType(binding, this.stringTypeCode);
 
1846
                                }
 
1847
        
 
1848
                                binding.value = StringUtils
 
1849
                                        .fixDecimalExponent(StringUtils.consistentToString(x));
 
1850
                                binding.isNull = false;
 
1851
                                binding.isLongData = false;
1785
1852
                        }
1786
 
 
1787
 
                        binding.value = StringUtils
1788
 
                                .fixDecimalExponent(StringUtils.consistentToString(x));
1789
 
                        binding.isNull = false;
1790
 
                        binding.isLongData = false;
1791
1853
                }
1792
1854
        }
1793
1855
 
1795
1857
         * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream,
1796
1858
         *      int)
1797
1859
         */
1798
 
        public synchronized void setBinaryStream(int parameterIndex, InputStream x, int length)
 
1860
        public void setBinaryStream(int parameterIndex, InputStream x, int length)
1799
1861
                        throws SQLException {
1800
 
                checkClosed();
1801
 
 
1802
 
                if (x == null) {
1803
 
                        setNull(parameterIndex, java.sql.Types.BINARY);
1804
 
                } else {
1805
 
                        BindValue binding = getBinding(parameterIndex, true);
1806
 
                        setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
1807
 
 
1808
 
                        binding.value = x;
1809
 
                        binding.isNull = false;
1810
 
                        binding.isLongData = true;
1811
 
 
1812
 
                        if (this.connection.getUseStreamLengthsInPrepStmts()) {
1813
 
                                binding.bindLength = length;
 
1862
                synchronized (checkClosed().getConnectionMutex()) {
 
1863
 
 
1864
                        if (x == null) {
 
1865
                                setNull(parameterIndex, java.sql.Types.BINARY);
1814
1866
                        } else {
1815
 
                                binding.bindLength = -1;
 
1867
                                BindValue binding = getBinding(parameterIndex, true);
 
1868
                                setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
 
1869
        
 
1870
                                binding.value = x;
 
1871
                                binding.isNull = false;
 
1872
                                binding.isLongData = true;
 
1873
        
 
1874
                                if (this.connection.getUseStreamLengthsInPrepStmts()) {
 
1875
                                        binding.bindLength = length;
 
1876
                                } else {
 
1877
                                        binding.bindLength = -1;
 
1878
                                }
1816
1879
                        }
1817
1880
                }
1818
1881
        }
1820
1883
        /**
1821
1884
         * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob)
1822
1885
         */
1823
 
        public synchronized void setBlob(int parameterIndex, Blob x) throws SQLException {
1824
 
                checkClosed();
1825
 
 
1826
 
                if (x == null) {
1827
 
                        setNull(parameterIndex, java.sql.Types.BINARY);
1828
 
                } else {
1829
 
                        BindValue binding = getBinding(parameterIndex, true);
1830
 
                        setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
1831
 
 
1832
 
                        binding.value = x;
1833
 
                        binding.isNull = false;
1834
 
                        binding.isLongData = true;
1835
 
 
1836
 
                        if (this.connection.getUseStreamLengthsInPrepStmts()) {
1837
 
                                binding.bindLength = x.length();
 
1886
        public void setBlob(int parameterIndex, Blob x) throws SQLException {
 
1887
                synchronized (checkClosed().getConnectionMutex()) {
 
1888
 
 
1889
                        if (x == null) {
 
1890
                                setNull(parameterIndex, java.sql.Types.BINARY);
1838
1891
                        } else {
1839
 
                                binding.bindLength = -1;
 
1892
                                BindValue binding = getBinding(parameterIndex, true);
 
1893
                                setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
 
1894
        
 
1895
                                binding.value = x;
 
1896
                                binding.isNull = false;
 
1897
                                binding.isLongData = true;
 
1898
        
 
1899
                                if (this.connection.getUseStreamLengthsInPrepStmts()) {
 
1900
                                        binding.bindLength = x.length();
 
1901
                                } else {
 
1902
                                        binding.bindLength = -1;
 
1903
                                }
1840
1904
                        }
1841
1905
                }
1842
1906
        }
1858
1922
                setType(binding, MysqlDefs.FIELD_TYPE_TINY);
1859
1923
 
1860
1924
                binding.value = null;
1861
 
                binding.byteBinding = x;
 
1925
                binding.longBinding = x;
1862
1926
                binding.isNull = false;
1863
1927
                binding.isLongData = false;
1864
1928
        }
1885
1949
         * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader,
1886
1950
         *      int)
1887
1951
         */
1888
 
        public synchronized void setCharacterStream(int parameterIndex, Reader reader, int length)
 
1952
        public void setCharacterStream(int parameterIndex, Reader reader, int length)
1889
1953
                        throws SQLException {
1890
 
                checkClosed();
1891
 
 
1892
 
                if (reader == null) {
1893
 
                        setNull(parameterIndex, java.sql.Types.BINARY);
1894
 
                } else {
1895
 
                        BindValue binding = getBinding(parameterIndex, true);
1896
 
                        setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
1897
 
 
1898
 
                        binding.value = reader;
1899
 
                        binding.isNull = false;
1900
 
                        binding.isLongData = true;
1901
 
 
1902
 
                        if (this.connection.getUseStreamLengthsInPrepStmts()) {
1903
 
                                binding.bindLength = length;
 
1954
                synchronized (checkClosed().getConnectionMutex()) {
 
1955
 
 
1956
                        if (reader == null) {
 
1957
                                setNull(parameterIndex, java.sql.Types.BINARY);
1904
1958
                        } else {
1905
 
                                binding.bindLength = -1;
 
1959
                                BindValue binding = getBinding(parameterIndex, true);
 
1960
                                setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
 
1961
        
 
1962
                                binding.value = reader;
 
1963
                                binding.isNull = false;
 
1964
                                binding.isLongData = true;
 
1965
        
 
1966
                                if (this.connection.getUseStreamLengthsInPrepStmts()) {
 
1967
                                        binding.bindLength = length;
 
1968
                                } else {
 
1969
                                        binding.bindLength = -1;
 
1970
                                }
1906
1971
                        }
1907
1972
                }
1908
1973
        }
1910
1975
        /**
1911
1976
         * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob)
1912
1977
         */
1913
 
        public synchronized void setClob(int parameterIndex, Clob x) throws SQLException {
1914
 
                checkClosed();
1915
 
 
1916
 
                if (x == null) {
1917
 
                        setNull(parameterIndex, java.sql.Types.BINARY);
1918
 
                } else {
1919
 
                        BindValue binding = getBinding(parameterIndex, true);
1920
 
                        setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
1921
 
 
1922
 
                        binding.value = x.getCharacterStream();
1923
 
                        binding.isNull = false;
1924
 
                        binding.isLongData = true;
1925
 
 
1926
 
                        if (this.connection.getUseStreamLengthsInPrepStmts()) {
1927
 
                                binding.bindLength = x.length();
 
1978
        public void setClob(int parameterIndex, Clob x) throws SQLException {
 
1979
                synchronized (checkClosed().getConnectionMutex()) {
 
1980
 
 
1981
                        if (x == null) {
 
1982
                                setNull(parameterIndex, java.sql.Types.BINARY);
1928
1983
                        } else {
1929
 
                                binding.bindLength = -1;
 
1984
                                BindValue binding = getBinding(parameterIndex, true);
 
1985
                                setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
 
1986
        
 
1987
                                binding.value = x.getCharacterStream();
 
1988
                                binding.isNull = false;
 
1989
                                binding.isLongData = true;
 
1990
        
 
1991
                                if (this.connection.getUseStreamLengthsInPrepStmts()) {
 
1992
                                        binding.bindLength = x.length();
 
1993
                                } else {
 
1994
                                        binding.bindLength = -1;
 
1995
                                }
1930
1996
                        }
1931
1997
                }
1932
1998
        }
1978
2044
        /**
1979
2045
         * @see java.sql.PreparedStatement#setDouble(int, double)
1980
2046
         */
1981
 
        public synchronized void setDouble(int parameterIndex, double x) throws SQLException {
1982
 
                checkClosed();
1983
 
 
1984
 
                if (!this.connection.getAllowNanAndInf()
1985
 
                                && (x == Double.POSITIVE_INFINITY
1986
 
                                                || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) {
1987
 
                        throw SQLError.createSQLException("'" + x
1988
 
                                        + "' is not a valid numeric or approximate numeric value",
1989
 
                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
1990
 
 
 
2047
        public void setDouble(int parameterIndex, double x) throws SQLException {
 
2048
                synchronized (checkClosed().getConnectionMutex()) {
 
2049
 
 
2050
                        if (!this.connection.getAllowNanAndInf()
 
2051
                                        && (x == Double.POSITIVE_INFINITY
 
2052
                                                        || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) {
 
2053
                                throw SQLError.createSQLException("'" + x
 
2054
                                                + "' is not a valid numeric or approximate numeric value",
 
2055
                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
 
2056
        
 
2057
                        }
 
2058
        
 
2059
                        BindValue binding = getBinding(parameterIndex, false);
 
2060
                        setType(binding, MysqlDefs.FIELD_TYPE_DOUBLE);
 
2061
        
 
2062
                        binding.value = null;
 
2063
                        binding.doubleBinding = x;
 
2064
                        binding.isNull = false;
 
2065
                        binding.isLongData = false;
1991
2066
                }
1992
 
 
1993
 
                BindValue binding = getBinding(parameterIndex, false);
1994
 
                setType(binding, MysqlDefs.FIELD_TYPE_DOUBLE);
1995
 
 
1996
 
                binding.value = null;
1997
 
                binding.doubleBinding = x;
1998
 
                binding.isNull = false;
1999
 
                binding.isLongData = false;
2000
2067
        }
2001
2068
 
2002
2069
        /**
2024
2091
                setType(binding, MysqlDefs.FIELD_TYPE_LONG);
2025
2092
 
2026
2093
                binding.value = null;
2027
 
                binding.intBinding = x;
 
2094
                binding.longBinding = x;
2028
2095
                binding.isNull = false;
2029
2096
                binding.isLongData = false;
2030
2097
        }
2104
2171
                setType(binding, MysqlDefs.FIELD_TYPE_SHORT);
2105
2172
 
2106
2173
                binding.value = null;
2107
 
                binding.shortBinding = x;
 
2174
                binding.longBinding = x;
2108
2175
                binding.isNull = false;
2109
2176
                binding.isLongData = false;
2110
2177
        }
2139
2206
         * @throws SQLException
2140
2207
         *             if a database access error occurs
2141
2208
         */
2142
 
        public synchronized void setTime(int parameterIndex, java.sql.Time x)
 
2209
        public void setTime(int parameterIndex, java.sql.Time x)
2143
2210
                        throws SQLException {
2144
 
                setTimeInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false);
 
2211
                synchronized (checkClosed().getConnectionMutex()) {
 
2212
                        setTimeInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false);
 
2213
                }
2145
2214
        }
2146
2215
 
2147
2216
        /**
2179
2248
         * @throws SQLException
2180
2249
         *             if a database access error occurs
2181
2250
         */
2182
 
        protected synchronized void setTimeInternal(int parameterIndex, java.sql.Time x,
 
2251
        protected void setTimeInternal(int parameterIndex, java.sql.Time x,
2183
2252
                        Calendar targetCalendar,
2184
2253
                        TimeZone tz, boolean rollForward) throws SQLException {
2185
 
                if (x == null) {
2186
 
                        setNull(parameterIndex, java.sql.Types.TIME);
2187
 
                } else {
2188
 
                        BindValue binding = getBinding(parameterIndex, false);
2189
 
                        setType(binding, MysqlDefs.FIELD_TYPE_TIME);
2190
 
 
2191
 
                        if (!this.useLegacyDatetimeCode) {
2192
 
                                binding.value = x;
 
2254
                synchronized (checkClosed().getConnectionMutex()) {
 
2255
                        if (x == null) {
 
2256
                                setNull(parameterIndex, java.sql.Types.TIME);
2193
2257
                        } else {
2194
 
                                Calendar sessionCalendar = getCalendarInstanceForSessionOrNew();
2195
 
                                
2196
 
                                synchronized (sessionCalendar) {
 
2258
                                BindValue binding = getBinding(parameterIndex, false);
 
2259
                                setType(binding, MysqlDefs.FIELD_TYPE_TIME);
 
2260
        
 
2261
                                if (!this.useLegacyDatetimeCode) {
 
2262
                                        binding.value = x;
 
2263
                                } else {
 
2264
                                        Calendar sessionCalendar = getCalendarInstanceForSessionOrNew();
 
2265
 
2197
2266
                                        binding.value = TimeUtil.changeTimezone(this.connection, 
2198
2267
                                                        sessionCalendar,
2199
2268
                                                        targetCalendar,
2201
2270
                                                        this.connection.getServerTimezoneTZ(), 
2202
2271
                                                        rollForward);
2203
2272
                                }
 
2273
                                
 
2274
                                binding.isNull = false;
 
2275
                                binding.isLongData = false;
2204
2276
                        }
2205
 
                        
2206
 
                        binding.isNull = false;
2207
 
                        binding.isLongData = false;
2208
2277
                }
2209
2278
        }
2210
2279
 
2220
2289
         * @throws SQLException
2221
2290
         *             if a database-access error occurs.
2222
2291
         */
2223
 
        public synchronized void setTimestamp(int parameterIndex, java.sql.Timestamp x)
 
2292
        public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
2224
2293
                        throws SQLException {
2225
 
                setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false);
 
2294
                synchronized (checkClosed().getConnectionMutex()) {
 
2295
                        setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false);
 
2296
                }
2226
2297
        }
2227
2298
 
2228
2299
        /**
2241
2312
         */
2242
2313
        public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
2243
2314
                        Calendar cal) throws SQLException {
2244
 
                setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true);
 
2315
                synchronized (checkClosed().getConnectionMutex()) {
 
2316
                        setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true);
 
2317
                }
2245
2318
        }
2246
2319
 
2247
 
        protected synchronized void setTimestampInternal(int parameterIndex,
 
2320
        protected void setTimestampInternal(int parameterIndex,
2248
2321
                        java.sql.Timestamp x, Calendar targetCalendar,
2249
2322
                        TimeZone tz, boolean rollForward)
2250
2323
                        throws SQLException {
2251
 
                if (x == null) {
2252
 
                        setNull(parameterIndex, java.sql.Types.TIMESTAMP);
2253
 
                } else {
2254
 
                        BindValue binding = getBinding(parameterIndex, false);
2255
 
                        setType(binding, MysqlDefs.FIELD_TYPE_DATETIME);
2256
 
 
2257
 
                        if (!this.useLegacyDatetimeCode) {
2258
 
                                binding.value = x;
 
2324
                synchronized (checkClosed().getConnectionMutex()) {
 
2325
                        if (x == null) {
 
2326
                                setNull(parameterIndex, java.sql.Types.TIMESTAMP);
2259
2327
                        } else {
2260
 
                                Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
2261
 
                                                this.connection.getUtcCalendar() : 
2262
 
                                                        getCalendarInstanceForSessionOrNew();
2263
 
                                
2264
 
                                synchronized (sessionCalendar) {
 
2328
                                BindValue binding = getBinding(parameterIndex, false);
 
2329
                                setType(binding, MysqlDefs.FIELD_TYPE_DATETIME);
 
2330
        
 
2331
                                if (!this.useLegacyDatetimeCode) {
 
2332
                                        binding.value = x;
 
2333
                                } else {
 
2334
                                        Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
 
2335
                                                        this.connection.getUtcCalendar() : 
 
2336
                                                                getCalendarInstanceForSessionOrNew();
 
2337
                                        
2265
2338
                                        binding.value = TimeUtil.changeTimezone(this.connection, 
2266
2339
                                                        sessionCalendar,
2267
2340
                                                        targetCalendar,
2268
2341
                                                        x, tz,
2269
2342
                                                        this.connection.getServerTimezoneTZ(), 
2270
2343
                                                        rollForward);
 
2344
 
 
2345
                                        binding.isNull = false;
 
2346
                                        binding.isLongData = false;
2271
2347
                                }
2272
 
                                
2273
 
                                binding.isNull = false;
2274
 
                                binding.isLongData = false;
2275
2348
                        }
2276
2349
                }
2277
2350
        }
2278
2351
 
2279
 
        protected synchronized void setType(BindValue oldValue, int bufferType) {
2280
 
                if (oldValue.bufferType != bufferType) {
2281
 
                        this.sendTypesToServer = true;
 
2352
        protected void setType(BindValue oldValue, int bufferType) throws SQLException {
 
2353
                synchronized (checkClosed().getConnectionMutex()) {
 
2354
                        if (oldValue.bufferType != bufferType) {
 
2355
                                this.sendTypesToServer = true;
 
2356
                        }
 
2357
        
 
2358
                        oldValue.bufferType = bufferType;
2282
2359
                }
2283
 
 
2284
 
                oldValue.bufferType = bufferType;
2285
2360
        }
2286
2361
 
2287
2362
        /**
2330
2405
         * @throws SQLException
2331
2406
         *             DOCUMENT ME!
2332
2407
         */
2333
 
        private synchronized void storeBinding(Buffer packet, BindValue bindValue, MysqlIO mysql)
2334
 
                        throws SQLException {
2335
 
                try {
2336
 
                        Object value = bindValue.value;
2337
 
 
2338
 
                        //
2339
 
                        // Handle primitives first
2340
 
                        //
2341
 
                        switch (bindValue.bufferType) {
2342
 
 
2343
 
                        case MysqlDefs.FIELD_TYPE_TINY:
2344
 
                                packet.writeByte(bindValue.byteBinding);
2345
 
                                return;
2346
 
                        case MysqlDefs.FIELD_TYPE_SHORT:
2347
 
                                packet.ensureCapacity(2);
2348
 
                                packet.writeInt(bindValue.shortBinding);
2349
 
                                return;
2350
 
                        case MysqlDefs.FIELD_TYPE_LONG:
2351
 
                                packet.ensureCapacity(4);
2352
 
                                packet.writeLong(bindValue.intBinding);
2353
 
                                return;
2354
 
                        case MysqlDefs.FIELD_TYPE_LONGLONG:
2355
 
                                packet.ensureCapacity(8);
2356
 
                                packet.writeLongLong(bindValue.longBinding);
2357
 
                                return;
2358
 
                        case MysqlDefs.FIELD_TYPE_FLOAT:
2359
 
                                packet.ensureCapacity(4);
2360
 
                                packet.writeFloat(bindValue.floatBinding);
2361
 
                                return;
2362
 
                        case MysqlDefs.FIELD_TYPE_DOUBLE:
2363
 
                                packet.ensureCapacity(8);
2364
 
                                packet.writeDouble(bindValue.doubleBinding);
2365
 
                                return;
2366
 
                        case MysqlDefs.FIELD_TYPE_TIME:
2367
 
                                storeTime(packet, (Time) value);
2368
 
                                return;
2369
 
                        case MysqlDefs.FIELD_TYPE_DATE:
2370
 
                        case MysqlDefs.FIELD_TYPE_DATETIME:
2371
 
                        case MysqlDefs.FIELD_TYPE_TIMESTAMP:
2372
 
                                storeDateTime(packet, (java.util.Date) value, mysql, bindValue.bufferType);
2373
 
                                return;
2374
 
                        case MysqlDefs.FIELD_TYPE_VAR_STRING:
2375
 
                        case MysqlDefs.FIELD_TYPE_STRING:
2376
 
                        case MysqlDefs.FIELD_TYPE_VARCHAR:
2377
 
                        case MysqlDefs.FIELD_TYPE_DECIMAL:
2378
 
                        case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
2379
 
                                if (value instanceof byte[]) {
2380
 
                                        packet.writeLenBytes((byte[]) value);
2381
 
                                } else if (!this.isLoadDataQuery) {
2382
 
                                        packet.writeLenString((String) value, this.charEncoding,
2383
 
                                                        this.connection.getServerCharacterEncoding(),
2384
 
                                                        this.charConverter, this.connection
2385
 
                                                                        .parserKnowsUnicode(),
2386
 
                                                                        this.connection);
 
2408
        private void storeBinding(Buffer packet, BindValue bindValue, MysqlIO mysql)
 
2409
                        throws SQLException {
 
2410
                synchronized (checkClosed().getConnectionMutex()) {
 
2411
                        try {
 
2412
                                Object value = bindValue.value;
 
2413
        
 
2414
                                //
 
2415
                                // Handle primitives first
 
2416
                                //
 
2417
                                switch (bindValue.bufferType) {
 
2418
        
 
2419
                                case MysqlDefs.FIELD_TYPE_TINY:
 
2420
                                        packet.writeByte((byte)bindValue.longBinding);
 
2421
                                        return;
 
2422
                                case MysqlDefs.FIELD_TYPE_SHORT:
 
2423
                                        packet.ensureCapacity(2);
 
2424
                                        packet.writeInt((int)bindValue.longBinding);
 
2425
                                        return;
 
2426
                                case MysqlDefs.FIELD_TYPE_LONG:
 
2427
                                        packet.ensureCapacity(4);
 
2428
                                        packet.writeLong((int)bindValue.longBinding);
 
2429
                                        return;
 
2430
                                case MysqlDefs.FIELD_TYPE_LONGLONG:
 
2431
                                        packet.ensureCapacity(8);
 
2432
                                        packet.writeLongLong(bindValue.longBinding);
 
2433
                                        return;
 
2434
                                case MysqlDefs.FIELD_TYPE_FLOAT:
 
2435
                                        packet.ensureCapacity(4);
 
2436
                                        packet.writeFloat(bindValue.floatBinding);
 
2437
                                        return;
 
2438
                                case MysqlDefs.FIELD_TYPE_DOUBLE:
 
2439
                                        packet.ensureCapacity(8);
 
2440
                                        packet.writeDouble(bindValue.doubleBinding);
 
2441
                                        return;
 
2442
                                case MysqlDefs.FIELD_TYPE_TIME:
 
2443
                                        storeTime(packet, (Time) value);
 
2444
                                        return;
 
2445
                                case MysqlDefs.FIELD_TYPE_DATE:
 
2446
                                case MysqlDefs.FIELD_TYPE_DATETIME:
 
2447
                                case MysqlDefs.FIELD_TYPE_TIMESTAMP:
 
2448
                                        storeDateTime(packet, (java.util.Date) value, mysql, bindValue.bufferType);
 
2449
                                        return;
 
2450
                                case MysqlDefs.FIELD_TYPE_VAR_STRING:
 
2451
                                case MysqlDefs.FIELD_TYPE_STRING:
 
2452
                                case MysqlDefs.FIELD_TYPE_VARCHAR:
 
2453
                                case MysqlDefs.FIELD_TYPE_DECIMAL:
 
2454
                                case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
 
2455
                                        if (value instanceof byte[]) {
 
2456
                                                packet.writeLenBytes((byte[]) value);
 
2457
                                        } else if (!this.isLoadDataQuery) {
 
2458
                                                packet.writeLenString((String) value, this.charEncoding,
 
2459
                                                                this.connection.getServerCharacterEncoding(),
 
2460
                                                                this.charConverter, this.connection
 
2461
                                                                                .parserKnowsUnicode(),
 
2462
                                                                                this.connection);
 
2463
                                        } else {
 
2464
                                                packet.writeLenBytes(StringUtils.getBytes((String) value));
 
2465
                                        }
 
2466
        
 
2467
                                        return;
 
2468
                                }
 
2469
        
 
2470
                                
 
2471
                        } catch (UnsupportedEncodingException uEE) {
 
2472
                                throw SQLError.createSQLException(Messages
 
2473
                                                .getString("ServerPreparedStatement.22") //$NON-NLS-1$
 
2474
                                                + this.connection.getEncoding() + "'", //$NON-NLS-1$
 
2475
                                                SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
2476
                        }
 
2477
                }
 
2478
        }
 
2479
 
 
2480
        private void storeDateTime412AndOlder(Buffer intoBuf, java.util.Date dt, int bufferType)
 
2481
                        throws SQLException {
 
2482
                synchronized (checkClosed().getConnectionMutex()) {
 
2483
                        Calendar sessionCalendar = null;
 
2484
                        
 
2485
                        if (!this.useLegacyDatetimeCode) {
 
2486
                                if (bufferType == MysqlDefs.FIELD_TYPE_DATE) {
 
2487
                                        sessionCalendar = getDefaultTzCalendar();
2387
2488
                                } else {
2388
 
                                        packet.writeLenBytes(((String) value).getBytes());
 
2489
                                        sessionCalendar = getServerTzCalendar();
2389
2490
                                }
2390
 
 
2391
 
                                return;
2392
 
                        }
2393
 
 
2394
 
                        
2395
 
                } catch (UnsupportedEncodingException uEE) {
2396
 
                        throw SQLError.createSQLException(Messages
2397
 
                                        .getString("ServerPreparedStatement.22") //$NON-NLS-1$
2398
 
                                        + this.connection.getEncoding() + "'", //$NON-NLS-1$
2399
 
                                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
2400
 
                }
2401
 
        }
2402
 
 
2403
 
        private synchronized void storeDateTime412AndOlder(Buffer intoBuf, java.util.Date dt, int bufferType)
2404
 
                        throws SQLException {
2405
 
                
2406
 
                Calendar sessionCalendar = null;
2407
 
                
2408
 
                if (!this.useLegacyDatetimeCode) {
2409
 
                        if (bufferType == MysqlDefs.FIELD_TYPE_DATE) {
2410
 
                                sessionCalendar = getDefaultTzCalendar();
2411
2491
                        } else {
2412
 
                                sessionCalendar = getServerTzCalendar();
 
2492
                                sessionCalendar = (dt instanceof Timestamp && 
 
2493
                                        this.connection.getUseJDBCCompliantTimezoneShift()) ? 
 
2494
                                        this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew();
2413
2495
                        }
2414
 
                } else {
2415
 
                        sessionCalendar = (dt instanceof Timestamp && 
2416
 
                                this.connection.getUseJDBCCompliantTimezoneShift()) ? 
2417
 
                                this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew();
2418
 
                }
2419
 
                
2420
 
                synchronized (sessionCalendar) {
 
2496
 
2421
2497
                        java.util.Date oldTime = sessionCalendar.getTime();
2422
2498
                        
2423
2499
                        try {
2452
2528
                }
2453
2529
        }
2454
2530
 
2455
 
        private synchronized void storeDateTime(Buffer intoBuf, java.util.Date dt, MysqlIO mysql, int bufferType)
 
2531
        /**
 
2532
         * 
 
2533
         * @param intoBuf
 
2534
         * @param dt
 
2535
         * @param mysql
 
2536
         * @param bufferType
 
2537
         * @throws SQLException
 
2538
         */
 
2539
        private void storeDateTime(Buffer intoBuf, java.util.Date dt, MysqlIO mysql, int bufferType)
2456
2540
                        throws SQLException {
2457
 
                if (this.connection.versionMeetsMinimum(4, 1, 3)) {
2458
 
                        storeDateTime413AndNewer(intoBuf, dt, bufferType);
2459
 
                } else {
2460
 
                        storeDateTime412AndOlder(intoBuf, dt, bufferType);
 
2541
                synchronized (checkClosed().getConnectionMutex()) {
 
2542
                        if (this.connection.versionMeetsMinimum(4, 1, 3)) {
 
2543
                                storeDateTime413AndNewer(intoBuf, dt, bufferType);
 
2544
                        } else {
 
2545
                                storeDateTime412AndOlder(intoBuf, dt, bufferType);
 
2546
                        }
2461
2547
                }
2462
2548
        }
2463
2549
 
2464
 
        private synchronized void storeDateTime413AndNewer(Buffer intoBuf, java.util.Date dt, int bufferType)
 
2550
        private void storeDateTime413AndNewer(Buffer intoBuf, java.util.Date dt, int bufferType)
2465
2551
                        throws SQLException {
2466
 
                Calendar sessionCalendar = null;
2467
 
                
2468
 
                if (!this.useLegacyDatetimeCode) {
2469
 
                        if (bufferType == MysqlDefs.FIELD_TYPE_DATE) {
2470
 
                                sessionCalendar = getDefaultTzCalendar();
 
2552
                synchronized (checkClosed().getConnectionMutex()) {
 
2553
                        Calendar sessionCalendar = null;
 
2554
                        
 
2555
                        if (!this.useLegacyDatetimeCode) {
 
2556
                                if (bufferType == MysqlDefs.FIELD_TYPE_DATE) {
 
2557
                                        sessionCalendar = getDefaultTzCalendar();
 
2558
                                } else {
 
2559
                                        sessionCalendar = getServerTzCalendar();
 
2560
                                }
2471
2561
                        } else {
2472
 
                                sessionCalendar = getServerTzCalendar();
 
2562
                                sessionCalendar = (dt instanceof Timestamp && 
 
2563
                                        this.connection.getUseJDBCCompliantTimezoneShift()) ? 
 
2564
                                        this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew();
2473
2565
                        }
2474
 
                } else {
2475
 
                        sessionCalendar = (dt instanceof Timestamp && 
2476
 
                                this.connection.getUseJDBCCompliantTimezoneShift()) ? 
2477
 
                                this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew();
2478
 
                }
2479
 
                
2480
 
                synchronized (sessionCalendar) {
 
2566
                        
 
2567
 
2481
2568
                        java.util.Date oldTime = sessionCalendar.getTime();
2482
2569
 
2483
2570
                        try {
2531
2618
                }
2532
2619
        }
2533
2620
 
2534
 
        private Calendar getServerTzCalendar() {
2535
 
                synchronized (this) {
 
2621
        private Calendar getServerTzCalendar() throws SQLException {
 
2622
                synchronized (checkClosed().getConnectionMutex()) {
2536
2623
                        if (serverTzCalendar == null) {
2537
2624
                                serverTzCalendar = new GregorianCalendar(this.connection.getServerTimezoneTZ());
2538
2625
                        }
2541
2628
                }
2542
2629
        }
2543
2630
        
2544
 
        private Calendar getDefaultTzCalendar() {
2545
 
                synchronized (this) {
 
2631
        private Calendar getDefaultTzCalendar() throws SQLException {
 
2632
                synchronized (checkClosed().getConnectionMutex()) {
2546
2633
                        if (defaultTzCalendar == null) {
2547
2634
                                defaultTzCalendar = new GregorianCalendar(TimeZone.getDefault());
2548
2635
                        }
2554
2641
        //
2555
2642
        // TO DO: Investigate using NIO to do this faster
2556
2643
        //
2557
 
        private synchronized void storeReader(MysqlIO mysql, int parameterIndex, Buffer packet,
 
2644
        private void storeReader(MysqlIO mysql, int parameterIndex, Buffer packet,
2558
2645
                        Reader inStream) throws SQLException {
2559
 
                String forcedEncoding = this.connection.getClobCharacterEncoding();
2560
 
                
2561
 
                String clobEncoding = 
2562
 
                        (forcedEncoding == null ? this.connection.getEncoding() : forcedEncoding);
2563
 
                
2564
 
                int maxBytesChar = 2;
2565
 
                        
2566
 
                if (clobEncoding != null) {
2567
 
                        if (!clobEncoding.equals("UTF-16")) {
2568
 
                                maxBytesChar = this.connection.getMaxBytesPerChar(clobEncoding);
 
2646
                synchronized (checkClosed().getConnectionMutex()) {
 
2647
                        String forcedEncoding = this.connection.getClobCharacterEncoding();
 
2648
                        
 
2649
                        String clobEncoding = 
 
2650
                                (forcedEncoding == null ? this.connection.getEncoding() : forcedEncoding);
 
2651
                        
 
2652
                        int maxBytesChar = 2;
2569
2653
                                
2570
 
                                if (maxBytesChar == 1) {
2571
 
                                        maxBytesChar = 2; // for safety
2572
 
                                }
2573
 
                        } else {
2574
 
                                maxBytesChar = 4;
2575
 
                        }
2576
 
                }
2577
 
                        
2578
 
                char[] buf = new char[BLOB_STREAM_READ_BUF_SIZE / maxBytesChar];
2579
 
                
2580
 
                int numRead = 0;
2581
 
 
2582
 
                int bytesInPacket = 0;
2583
 
                int totalBytesRead = 0;
2584
 
                int bytesReadAtLastSend = 0;
2585
 
                int packetIsFullAt = this.connection.getBlobSendChunkSize();
2586
 
                
2587
 
                
2588
 
                
2589
 
                try {
2590
 
                        packet.clear();
2591
 
                        packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
2592
 
                        packet.writeLong(this.serverStatementId);
2593
 
                        packet.writeInt((parameterIndex));
2594
 
 
2595
 
                        boolean readAny = false;
2596
 
                        
2597
 
                        while ((numRead = inStream.read(buf)) != -1) {
2598
 
                                readAny = true;
2599
 
                        
2600
 
                                byte[] valueAsBytes = StringUtils.getBytes(buf, null,
2601
 
                                                clobEncoding, this.connection
2602
 
                                                                .getServerCharacterEncoding(), 0, numRead,
2603
 
                                                this.connection.parserKnowsUnicode(), getExceptionInterceptor());
2604
 
 
2605
 
                                packet.writeBytesNoNull(valueAsBytes, 0, valueAsBytes.length);
2606
 
 
2607
 
                                bytesInPacket += valueAsBytes.length;
2608
 
                                totalBytesRead += valueAsBytes.length;
2609
 
 
2610
 
                                if (bytesInPacket >= packetIsFullAt) {
2611
 
                                        bytesReadAtLastSend = totalBytesRead;
2612
 
 
2613
 
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet,
2614
 
                                                        true, null, 0);
2615
 
 
2616
 
                                        bytesInPacket = 0;
2617
 
                                        packet.clear();
2618
 
                                        packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
2619
 
                                        packet.writeLong(this.serverStatementId);
2620
 
                                        packet.writeInt((parameterIndex));
2621
 
                                }
2622
 
                        }
2623
 
 
2624
 
                        if (totalBytesRead != bytesReadAtLastSend) {
2625
 
                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
2626
 
                                                null, 0);
2627
 
                        }
2628
 
                        
2629
 
                        if (!readAny) {
2630
 
                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
2631
 
                                                null, 0);
2632
 
                        }
2633
 
                } catch (IOException ioEx) {
2634
 
                        SQLException sqlEx = SQLError.createSQLException(Messages
2635
 
                                        .getString("ServerPreparedStatement.24") //$NON-NLS-1$
2636
 
                                        + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
2637
 
                        sqlEx.initCause(ioEx);
2638
 
                        
2639
 
                        throw sqlEx;
2640
 
                } finally {
2641
 
                        if (this.connection.getAutoClosePStmtStreams()) {
2642
 
                                if (inStream != null) {
2643
 
                                        try {
2644
 
                                                inStream.close();
2645
 
                                        } catch (IOException ioEx) {
2646
 
                                                ; // ignore
 
2654
                        if (clobEncoding != null) {
 
2655
                                if (!clobEncoding.equals("UTF-16")) {
 
2656
                                        maxBytesChar = this.connection.getMaxBytesPerChar(clobEncoding);
 
2657
                                        
 
2658
                                        if (maxBytesChar == 1) {
 
2659
                                                maxBytesChar = 2; // for safety
2647
2660
                                        }
 
2661
                                } else {
 
2662
                                        maxBytesChar = 4;
2648
2663
                                }
2649
2664
                        }
2650
 
                }
2651
 
        }
2652
 
 
2653
 
        private synchronized void storeStream(MysqlIO mysql, int parameterIndex, Buffer packet,
2654
 
                        InputStream inStream) throws SQLException {
2655
 
                byte[] buf = new byte[BLOB_STREAM_READ_BUF_SIZE];
2656
 
 
2657
 
                int numRead = 0;
2658
 
                
2659
 
                try {
 
2665
                                
 
2666
                        char[] buf = new char[BLOB_STREAM_READ_BUF_SIZE / maxBytesChar];
 
2667
                        
 
2668
                        int numRead = 0;
 
2669
        
2660
2670
                        int bytesInPacket = 0;
2661
2671
                        int totalBytesRead = 0;
2662
2672
                        int bytesReadAtLastSend = 0;
2663
2673
                        int packetIsFullAt = this.connection.getBlobSendChunkSize();
2664
 
 
2665
 
                        packet.clear();
2666
 
                        packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
2667
 
                        packet.writeLong(this.serverStatementId);
2668
 
                        packet.writeInt((parameterIndex));
2669
 
 
2670
 
                        boolean readAny = false;
2671
 
                        
2672
 
                        while ((numRead = inStream.read(buf)) != -1) {
2673
 
 
2674
 
                                readAny = true;
2675
 
                                
2676
 
                                packet.writeBytesNoNull(buf, 0, numRead);
2677
 
                                bytesInPacket += numRead;
2678
 
                                totalBytesRead += numRead;
2679
 
 
2680
 
                                if (bytesInPacket >= packetIsFullAt) {
2681
 
                                        bytesReadAtLastSend = totalBytesRead;
2682
 
 
2683
 
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet,
2684
 
                                                        true, null, 0);
2685
 
 
2686
 
                                        bytesInPacket = 0;
2687
 
                                        packet.clear();
2688
 
                                        packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
2689
 
                                        packet.writeLong(this.serverStatementId);
2690
 
                                        packet.writeInt((parameterIndex));
2691
 
                                }
2692
 
                        }
2693
 
 
2694
 
                        if (totalBytesRead != bytesReadAtLastSend) {
2695
 
                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
2696
 
                                                null, 0);
2697
 
                        }
2698
 
                        
2699
 
                        if (!readAny) {
2700
 
                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
2701
 
                                                null, 0);
2702
 
                        }
2703
 
                } catch (IOException ioEx) {
2704
 
                        SQLException sqlEx = SQLError.createSQLException(Messages
2705
 
                                        .getString("ServerPreparedStatement.25") //$NON-NLS-1$
2706
 
                                        + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
2707
 
                        sqlEx.initCause(ioEx);
2708
 
                        
2709
 
                        throw sqlEx;
2710
 
                } finally {
2711
 
                        if (this.connection.getAutoClosePStmtStreams()) {
2712
 
                                if (inStream != null) {
2713
 
                                        try {
2714
 
                                                inStream.close();
2715
 
                                        } catch (IOException ioEx) {
2716
 
                                                ; // ignore
 
2674
                        
 
2675
                        
 
2676
                        
 
2677
                        try {
 
2678
                                packet.clear();
 
2679
                                packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
 
2680
                                packet.writeLong(this.serverStatementId);
 
2681
                                packet.writeInt((parameterIndex));
 
2682
        
 
2683
                                boolean readAny = false;
 
2684
                                
 
2685
                                while ((numRead = inStream.read(buf)) != -1) {
 
2686
                                        readAny = true;
 
2687
                                
 
2688
                                        byte[] valueAsBytes = StringUtils.getBytes(buf, null,
 
2689
                                                        clobEncoding, this.connection
 
2690
                                                                        .getServerCharacterEncoding(), 0, numRead,
 
2691
                                                        this.connection.parserKnowsUnicode(), getExceptionInterceptor());
 
2692
        
 
2693
                                        packet.writeBytesNoNull(valueAsBytes, 0, valueAsBytes.length);
 
2694
        
 
2695
                                        bytesInPacket += valueAsBytes.length;
 
2696
                                        totalBytesRead += valueAsBytes.length;
 
2697
        
 
2698
                                        if (bytesInPacket >= packetIsFullAt) {
 
2699
                                                bytesReadAtLastSend = totalBytesRead;
 
2700
        
 
2701
                                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet,
 
2702
                                                                true, null, 0);
 
2703
        
 
2704
                                                bytesInPacket = 0;
 
2705
                                                packet.clear();
 
2706
                                                packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
 
2707
                                                packet.writeLong(this.serverStatementId);
 
2708
                                                packet.writeInt((parameterIndex));
 
2709
                                        }
 
2710
                                }
 
2711
        
 
2712
                                if (totalBytesRead != bytesReadAtLastSend) {
 
2713
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
 
2714
                                                        null, 0);
 
2715
                                }
 
2716
                                
 
2717
                                if (!readAny) {
 
2718
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
 
2719
                                                        null, 0);
 
2720
                                }
 
2721
                        } catch (IOException ioEx) {
 
2722
                                SQLException sqlEx = SQLError.createSQLException(Messages
 
2723
                                                .getString("ServerPreparedStatement.24") //$NON-NLS-1$
 
2724
                                                + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
2725
                                sqlEx.initCause(ioEx);
 
2726
                                
 
2727
                                throw sqlEx;
 
2728
                        } finally {
 
2729
                                if (this.connection.getAutoClosePStmtStreams()) {
 
2730
                                        if (inStream != null) {
 
2731
                                                try {
 
2732
                                                        inStream.close();
 
2733
                                                } catch (IOException ioEx) {
 
2734
                                                        ; // ignore
 
2735
                                                }
 
2736
                                        }
 
2737
                                }
 
2738
                        }
 
2739
                }
 
2740
        }
 
2741
 
 
2742
        private void storeStream(MysqlIO mysql, int parameterIndex, Buffer packet,
 
2743
                        InputStream inStream) throws SQLException {
 
2744
                synchronized (checkClosed().getConnectionMutex()) {
 
2745
                        byte[] buf = new byte[BLOB_STREAM_READ_BUF_SIZE];
 
2746
        
 
2747
                        int numRead = 0;
 
2748
                        
 
2749
                        try {
 
2750
                                int bytesInPacket = 0;
 
2751
                                int totalBytesRead = 0;
 
2752
                                int bytesReadAtLastSend = 0;
 
2753
                                int packetIsFullAt = this.connection.getBlobSendChunkSize();
 
2754
        
 
2755
                                packet.clear();
 
2756
                                packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
 
2757
                                packet.writeLong(this.serverStatementId);
 
2758
                                packet.writeInt((parameterIndex));
 
2759
        
 
2760
                                boolean readAny = false;
 
2761
                                
 
2762
                                while ((numRead = inStream.read(buf)) != -1) {
 
2763
        
 
2764
                                        readAny = true;
 
2765
                                        
 
2766
                                        packet.writeBytesNoNull(buf, 0, numRead);
 
2767
                                        bytesInPacket += numRead;
 
2768
                                        totalBytesRead += numRead;
 
2769
        
 
2770
                                        if (bytesInPacket >= packetIsFullAt) {
 
2771
                                                bytesReadAtLastSend = totalBytesRead;
 
2772
        
 
2773
                                                mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet,
 
2774
                                                                true, null, 0);
 
2775
        
 
2776
                                                bytesInPacket = 0;
 
2777
                                                packet.clear();
 
2778
                                                packet.writeByte((byte) MysqlDefs.COM_LONG_DATA);
 
2779
                                                packet.writeLong(this.serverStatementId);
 
2780
                                                packet.writeInt((parameterIndex));
 
2781
                                        }
 
2782
                                }
 
2783
        
 
2784
                                if (totalBytesRead != bytesReadAtLastSend) {
 
2785
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
 
2786
                                                        null, 0);
 
2787
                                }
 
2788
                                
 
2789
                                if (!readAny) {
 
2790
                                        mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true,
 
2791
                                                        null, 0);
 
2792
                                }
 
2793
                        } catch (IOException ioEx) {
 
2794
                                SQLException sqlEx = SQLError.createSQLException(Messages
 
2795
                                                .getString("ServerPreparedStatement.25") //$NON-NLS-1$
 
2796
                                                + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
2797
                                sqlEx.initCause(ioEx);
 
2798
                                
 
2799
                                throw sqlEx;
 
2800
                        } finally {
 
2801
                                if (this.connection.getAutoClosePStmtStreams()) {
 
2802
                                        if (inStream != null) {
 
2803
                                                try {
 
2804
                                                        inStream.close();
 
2805
                                                } catch (IOException ioEx) {
 
2806
                                                        ; // ignore
 
2807
                                                }
2717
2808
                                        }
2718
2809
                                }
2719
2810
                        }
2747
2838
        private boolean hasCheckedRewrite = false;
2748
2839
        private boolean canRewrite = false;
2749
2840
        
2750
 
        public synchronized boolean canRewriteAsMultiValueInsertAtSqlLevel() throws SQLException {
2751
 
                if (!hasCheckedRewrite) {
2752
 
                        this.hasCheckedRewrite = true;
2753
 
                        this.canRewrite = canRewrite(this.originalSql, isOnDuplicateKeyUpdate(), getLocationOfOnDuplicateKeyUpdate(), 0);
2754
 
                        // We need to client-side parse this to get the VALUES clause, etc.
2755
 
                        this.parseInfo = new ParseInfo(this.originalSql, this.connection, this.connection.getMetaData(), this.charEncoding, this.charConverter);
 
2841
        public boolean canRewriteAsMultiValueInsertAtSqlLevel() throws SQLException {
 
2842
                synchronized (checkClosed().getConnectionMutex()) {
 
2843
                        if (!hasCheckedRewrite) {
 
2844
                                this.hasCheckedRewrite = true;
 
2845
                                this.canRewrite = canRewrite(this.originalSql, isOnDuplicateKeyUpdate(), getLocationOfOnDuplicateKeyUpdate(), 0);
 
2846
                                // We need to client-side parse this to get the VALUES clause, etc.
 
2847
                                this.parseInfo = new ParseInfo(this.originalSql, this.connection, this.connection.getMetaData(), this.charEncoding, this.charConverter);
 
2848
                        }
 
2849
                        
 
2850
                        return this.canRewrite;
2756
2851
                }
2757
 
                
2758
 
                return this.canRewrite;
2759
2852
        }
2760
2853
 
2761
2854
        
2762
 
        public synchronized boolean canRewriteAsMultivalueInsertStatement() throws SQLException {
2763
 
                if (!canRewriteAsMultiValueInsertAtSqlLevel()) {
2764
 
                        return false;
2765
 
                }
2766
 
        
2767
 
                BindValue[] currentBindValues = null;
2768
 
                BindValue[] previousBindValues = null;
2769
 
        
2770
 
                int nbrCommands = this.batchedArgs.size();
2771
 
        
2772
 
                // Can't have type changes between sets of bindings for this to work...
2773
 
        
2774
 
                for (int commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
2775
 
                        Object arg = this.batchedArgs.get(commandIndex);
2776
 
        
2777
 
                        if (!(arg instanceof String)) {
2778
 
        
2779
 
                                currentBindValues = ((BatchedBindValues) arg).batchedParameterValues;
2780
 
        
2781
 
                                // We need to check types each time, as
2782
 
                                // the user might have bound different
2783
 
                                // types in each addBatch()
2784
 
        
2785
 
                                if (previousBindValues != null) {
2786
 
                                        for (int j = 0; j < this.parameterBindings.length; j++) {
2787
 
                                                if (currentBindValues[j].bufferType != previousBindValues[j].bufferType) {
2788
 
                                                        return false;
 
2855
        public boolean canRewriteAsMultivalueInsertStatement() throws SQLException {
 
2856
                synchronized (checkClosed().getConnectionMutex()) {
 
2857
                        if (!canRewriteAsMultiValueInsertAtSqlLevel()) {
 
2858
                                return false;
 
2859
                        }
 
2860
                
 
2861
                        BindValue[] currentBindValues = null;
 
2862
                        BindValue[] previousBindValues = null;
 
2863
                
 
2864
                        int nbrCommands = this.batchedArgs.size();
 
2865
                
 
2866
                        // Can't have type changes between sets of bindings for this to work...
 
2867
                
 
2868
                        for (int commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
 
2869
                                Object arg = this.batchedArgs.get(commandIndex);
 
2870
                
 
2871
                                if (!(arg instanceof String)) {
 
2872
                
 
2873
                                        currentBindValues = ((BatchedBindValues) arg).batchedParameterValues;
 
2874
                
 
2875
                                        // We need to check types each time, as
 
2876
                                        // the user might have bound different
 
2877
                                        // types in each addBatch()
 
2878
                
 
2879
                                        if (previousBindValues != null) {
 
2880
                                                for (int j = 0; j < this.parameterBindings.length; j++) {
 
2881
                                                        if (currentBindValues[j].bufferType != previousBindValues[j].bufferType) {
 
2882
                                                                return false;
 
2883
                                                        }
2789
2884
                                                }
2790
2885
                                        }
2791
2886
                                }
2792
2887
                        }
 
2888
                        
 
2889
                        
 
2890
                        
 
2891
                        return true;
2793
2892
                }
2794
 
                
2795
 
                
2796
 
                
2797
 
                return true;
2798
2893
        }
2799
2894
        
2800
2895
        private int locationOfOnDuplicateKeyUpdate = -2;
2801
2896
        
2802
 
        protected synchronized int getLocationOfOnDuplicateKeyUpdate() {
2803
 
                if (this.locationOfOnDuplicateKeyUpdate == -2) {
2804
 
                        this.locationOfOnDuplicateKeyUpdate = getOnDuplicateKeyLocation(this.originalSql);
 
2897
        protected int getLocationOfOnDuplicateKeyUpdate() throws SQLException {
 
2898
                synchronized (checkClosed().getConnectionMutex()) {
 
2899
                        if (this.locationOfOnDuplicateKeyUpdate == -2) {
 
2900
                                this.locationOfOnDuplicateKeyUpdate = getOnDuplicateKeyLocation(this.originalSql);
 
2901
                        }
 
2902
                        
 
2903
                        return this.locationOfOnDuplicateKeyUpdate;
2805
2904
                }
2806
 
                
2807
 
                return this.locationOfOnDuplicateKeyUpdate;
2808
2905
        }
2809
2906
        
2810
 
        protected synchronized boolean isOnDuplicateKeyUpdate() {
2811
 
                return getLocationOfOnDuplicateKeyUpdate() != -1;
 
2907
        protected boolean isOnDuplicateKeyUpdate() throws SQLException {
 
2908
                synchronized (checkClosed().getConnectionMutex()) {
 
2909
                        return getLocationOfOnDuplicateKeyUpdate() != -1;
 
2910
                }
2812
2911
        }
2813
2912
 
2814
2913
        
2817
2916
        /** 
2818
2917
         *  Computes the maximum parameter set size, and entire batch size given 
2819
2918
         *  the number of arguments in the batch.
 
2919
         * @throws SQLException 
2820
2920
         */
2821
 
        protected synchronized long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) {
2822
 
                long sizeOfEntireBatch = 1 + /* com_execute */ + 4 /* stmt id */ + 1 /* flags */ + 4 /* batch count padding */; 
2823
 
                long maxSizeOfParameterSet = 0;
2824
 
                
2825
 
                for (int i = 0; i < numBatchedArgs; i++) {
2826
 
                        BindValue[] paramArg = ((BatchedBindValues) this.batchedArgs.get(i)).batchedParameterValues;
2827
 
        
2828
 
                        long sizeOfParameterSet = 0;
2829
 
                        
2830
 
                        sizeOfParameterSet += (this.parameterCount + 7) / 8; // for isNull
2831
 
                        
2832
 
                        sizeOfParameterSet += this.parameterCount * 2; // have to send types
2833
 
                        
2834
 
                        for (int j = 0; j < this.parameterBindings.length; j++) {
2835
 
                                if (!paramArg[j].isNull) {
2836
 
        
2837
 
                                        long size = paramArg[j].getBoundLength();
2838
 
                                        
2839
 
                                        if (paramArg[j].isLongData) {
2840
 
                                                if (size != -1) {
 
2921
        protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) throws SQLException {
 
2922
                synchronized (checkClosed().getConnectionMutex()) {
 
2923
                        long sizeOfEntireBatch = 1 + /* com_execute */ + 4 /* stmt id */ + 1 /* flags */ + 4 /* batch count padding */; 
 
2924
                        long maxSizeOfParameterSet = 0;
 
2925
                        
 
2926
                        for (int i = 0; i < numBatchedArgs; i++) {
 
2927
                                BindValue[] paramArg = ((BatchedBindValues) this.batchedArgs.get(i)).batchedParameterValues;
 
2928
                
 
2929
                                long sizeOfParameterSet = 0;
 
2930
                                
 
2931
                                sizeOfParameterSet += (this.parameterCount + 7) / 8; // for isNull
 
2932
                                
 
2933
                                sizeOfParameterSet += this.parameterCount * 2; // have to send types
 
2934
                                
 
2935
                                for (int j = 0; j < this.parameterBindings.length; j++) {
 
2936
                                        if (!paramArg[j].isNull) {
 
2937
                
 
2938
                                                long size = paramArg[j].getBoundLength();
 
2939
                                                
 
2940
                                                if (paramArg[j].isLongData) {
 
2941
                                                        if (size != -1) {
 
2942
                                                                sizeOfParameterSet += size;
 
2943
                                                        }
 
2944
                                                } else {
2841
2945
                                                        sizeOfParameterSet += size;
2842
2946
                                                }
2843
 
                                        } else {
2844
 
                                                sizeOfParameterSet += size;
2845
2947
                                        }
2846
2948
                                }
2847
 
                        }
2848
 
                        
2849
 
                        sizeOfEntireBatch += sizeOfParameterSet;
2850
 
                        
2851
 
                        if (sizeOfParameterSet > maxSizeOfParameterSet) {
2852
 
                                maxSizeOfParameterSet = sizeOfParameterSet;
2853
 
                        }
2854
 
                }       
2855
 
                
2856
 
                return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch};
 
2949
                                
 
2950
                                sizeOfEntireBatch += sizeOfParameterSet;
 
2951
                                
 
2952
                                if (sizeOfParameterSet > maxSizeOfParameterSet) {
 
2953
                                        maxSizeOfParameterSet = sizeOfParameterSet;
 
2954
                                }
 
2955
                        }       
 
2956
                        
 
2957
                        return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch};
 
2958
                }
2857
2959
        }
2858
2960
 
2859
2961
        protected int setOneBatchedParameterSet(
2883
2985
        
2884
2986
                                        case MysqlDefs.FIELD_TYPE_TINY:
2885
2987
                                                batchedStatement.setByte(batchedParamIndex++,
2886
 
                                                                paramArg[j].byteBinding);
 
2988
                                                                (byte)paramArg[j].longBinding);
2887
2989
                                                break;
2888
2990
                                        case MysqlDefs.FIELD_TYPE_SHORT:
2889
2991
                                                batchedStatement.setShort(batchedParamIndex++,
2890
 
                                                                paramArg[j].shortBinding);
 
2992
                                                                (short)paramArg[j].longBinding);
2891
2993
                                                break;
2892
2994
                                        case MysqlDefs.FIELD_TYPE_LONG:
2893
2995
                                                batchedStatement.setInt(batchedParamIndex++,
2894
 
                                                                paramArg[j].intBinding);
 
2996
                                                                (int)paramArg[j].longBinding);
2895
2997
                                                break;
2896
2998
                                        case MysqlDefs.FIELD_TYPE_LONGLONG:
2897
2999
                                                batchedStatement.setLong(batchedParamIndex++,
2962
3064
                return this.hasOnDuplicateKeyUpdate;
2963
3065
        }
2964
3066
        
2965
 
        protected synchronized PreparedStatement prepareBatchedInsertSQL(MySQLConnection localConn, int numBatches) throws SQLException {
2966
 
                try {
2967
 
                        PreparedStatement pstmt = new ServerPreparedStatement(localConn, this.parseInfo.getSqlForBatch(numBatches), this.currentCatalog, this.resultSetConcurrency, this.resultSetType);
2968
 
                        pstmt.setRetrieveGeneratedKeys(this.retrieveGeneratedKeys);
2969
 
                        
2970
 
                        return pstmt;
2971
 
                } catch (UnsupportedEncodingException e) {
2972
 
                        SQLException sqlEx = SQLError.createSQLException("Unable to prepare batch statement", SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
2973
 
                        sqlEx.initCause(e);
2974
 
                        
2975
 
                        throw sqlEx;
 
3067
        protected PreparedStatement prepareBatchedInsertSQL(MySQLConnection localConn, int numBatches) throws SQLException {
 
3068
                synchronized (checkClosed().getConnectionMutex()) {
 
3069
                        try {
 
3070
                                PreparedStatement pstmt = new ServerPreparedStatement(localConn, this.parseInfo.getSqlForBatch(numBatches), this.currentCatalog, this.resultSetConcurrency, this.resultSetType);
 
3071
                                pstmt.setRetrieveGeneratedKeys(this.retrieveGeneratedKeys);
 
3072
                                
 
3073
                                return pstmt;
 
3074
                        } catch (UnsupportedEncodingException e) {
 
3075
                                SQLException sqlEx = SQLError.createSQLException("Unable to prepare batch statement", SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
 
3076
                                sqlEx.initCause(e);
 
3077
                                
 
3078
                                throw sqlEx;
 
3079
                        }
2976
3080
                }
2977
 
                
2978
3081
        }
2979
3082
}