~maria-captains/mariadb-java-client/trunk

« back to all changes in this revision

Viewing changes to src/main/java/org/mariadb/jdbc/MySQLPreparedStatement.java

  • Committer: Massimo Siani
  • Date: 2014-07-11 08:45:03 UTC
  • mfrom: (513 mariadb-java-client)
  • mto: This revision was merged to the branch mainline in revision 525.
  • Revision ID: massimo.siani@skysql.com-20140711084503-2p57d2w803h5m09a
Fix for CONJ-99:
- rewriteBatchedStatements=true implies allowMultiQueries;
- INSERT statements are inserted as a long INSERT;
- test case.

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
    private boolean useFractionalSeconds;
76
76
    boolean parametersCleared;
77
77
    List<MySQLPreparedStatement> batchPreparedStatements;
 
78
    private boolean isRewriteable = true;
 
79
    private String firstRewrite = null;
78
80
 
79
81
 
80
82
    public MySQLPreparedStatement(MySQLConnection connection,
194
196
            batchPreparedStatements = new ArrayList<MySQLPreparedStatement>();
195
197
        }
196
198
        batchPreparedStatements.add(new MySQLPreparedStatement(connection,sql, dQuery, useFractionalSeconds));
 
199
        isInsertRewriteable(sql);
197
200
    }
198
201
    public void addBatch(final String sql) throws SQLException {
199
202
        if (batchPreparedStatements == null) {
200
203
            batchPreparedStatements = new ArrayList<MySQLPreparedStatement>();
201
204
        }
202
205
        batchPreparedStatements.add(new MySQLPreparedStatement(connection, sql));
 
206
        isInsertRewriteable(sql);
203
207
    }
204
208
 
205
209
    public void clearBatch() {
206
210
        if (batchPreparedStatements != null) {
207
211
            batchPreparedStatements.clear();
208
212
        }
 
213
        firstRewrite = null;
 
214
        isRewriteable = true;
 
215
    }
 
216
    
 
217
    /**
 
218
     * Parses the sql string to understand whether it is compatible with rewritten batches.
 
219
     * @param sql the sql string
 
220
     */
 
221
    private void isInsertRewriteable(String sql) {
 
222
        if (!isRewriteable) {
 
223
                return;
 
224
        }
 
225
        int index = getInsertIncipit(sql);
 
226
        if (index == -1) {
 
227
                isRewriteable = false;
 
228
                return;
 
229
        }
 
230
        if (firstRewrite == null) {
 
231
                firstRewrite = sql.substring(0, index);
 
232
        }
 
233
        boolean isRewrite = sql.startsWith(firstRewrite);
 
234
        if (isRewrite) {
 
235
                isRewriteable = isRewriteable && true;
 
236
        }
 
237
    }
 
238
    
 
239
    /**
 
240
     * If the batch array contains only rewriteable sql strings, returns the rewritten statement.
 
241
     * @return the rewritten statement
 
242
     */
 
243
    private String rewrittenBatch() {
 
244
        StringBuilder result = null;
 
245
        if(isRewriteable) {
 
246
                result = new StringBuilder("");
 
247
                result.append(firstRewrite);
 
248
                for (MySQLPreparedStatement mySQLPS : batchPreparedStatements) {
 
249
                        String query = mySQLPS.dQuery.toSQL();
 
250
                        result.append(query.substring(getInsertIncipit(query)));
 
251
                        result.append(",");
 
252
                }
 
253
                result.deleteCharAt(result.length() - 1);
 
254
        }
 
255
        return (result == null ? null : result.toString());
209
256
    }
210
257
 
211
258
    @Override
216
263
        int[] ret = new int[batchPreparedStatements.size()];
217
264
        int i = 0;
218
265
        try {
219
 
            synchronized (this.getProtocol()) {
220
 
                for(; i < batchPreparedStatements.size(); i++)  {
221
 
                    PreparedStatement ps =  batchPreparedStatements.get(i);
222
 
                    ps.execute();
223
 
                    int updateCount = ps.getUpdateCount();
224
 
                    if (updateCount == -1) {
225
 
                        ret[i] = SUCCESS_NO_INFO;
226
 
                    } else {
227
 
                        ret[i] = updateCount;
228
 
                    }
229
 
                }
230
 
            }
 
266
                        synchronized (this.getProtocol()) {
 
267
                                if (getProtocol().getInfo().getProperty("rewriteBatchedStatements") != null
 
268
                                                && "true".equalsIgnoreCase(getProtocol().getInfo().getProperty("rewriteBatchedStatements"))) {
 
269
                                        ret = executeBatchAsMultiQueries();
 
270
                                } else {
 
271
                                        for (; i < batchPreparedStatements.size(); i++) {
 
272
                                                PreparedStatement ps = batchPreparedStatements.get(i);
 
273
                                                ps.execute();
 
274
                                                int updateCount = ps.getUpdateCount();
 
275
                                                if (updateCount == -1) {
 
276
                                                        ret[i] = SUCCESS_NO_INFO;
 
277
                                                } else {
 
278
                                                        ret[i] = updateCount;
 
279
                                                }
 
280
                                        }
 
281
                                }
 
282
                        }
231
283
        } catch (SQLException sqle) {
232
284
            throw new BatchUpdateException(sqle.getMessage(), sqle.getSQLState(), Arrays.copyOf(ret, i), sqle);
233
285
        } finally {
235
287
        }
236
288
        return ret;
237
289
    }
 
290
    
 
291
        /**
 
292
         * Builds a new statement which contains the batched Statements and executes it.
 
293
         * @return an array of update counts containing one element for each command in the batch.
 
294
         *  The elements of the array are ordered according to the order in which commands were added to the batch.
 
295
         * @throws SQLException
 
296
         */
 
297
        private int[] executeBatchAsMultiQueries() throws SQLException {
 
298
                StringBuilder stringBuilder = new StringBuilder();
 
299
                int i = 0;
 
300
                String rewrite = rewrittenBatch();
 
301
                if (rewrite != null) {
 
302
                        stringBuilder.append(rewrite);
 
303
                        i++;
 
304
                } else {
 
305
                        for (; i < batchPreparedStatements.size(); i++) {
 
306
                                stringBuilder.append(batchPreparedStatements.get(i).dQuery.toSQL() + ";");
 
307
                        }
 
308
                }
 
309
                Statement ps = connection.createStatement();
 
310
                ps.execute(stringBuilder.toString());
 
311
                return getUpdateCounts(ps, i);
 
312
        }
238
313
 
239
314
 
240
315
    /**