001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbcp2; 018 019import java.sql.Connection; 020import java.sql.SQLException; 021import java.sql.Statement; 022import java.util.Arrays; 023import java.util.Objects; 024 025import org.apache.commons.dbcp2.PoolingConnection.StatementType; 026 027/** 028 * A key uniquely identifying {@link java.sql.PreparedStatement PreparedStatement}s. 029 * 030 * @since 2.0 031 */ 032public class PStmtKey { 033 034 /** 035 * Builder for prepareCall(String sql). 036 */ 037 private class PreparedCallSQL implements StatementBuilder { 038 @Override 039 public Statement createStatement(final Connection connection) throws SQLException { 040 return connection.prepareCall(sql); 041 } 042 } 043 044 /** 045 * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency). 046 */ 047 private class PreparedCallWithResultSetConcurrency implements StatementBuilder { 048 @Override 049 public Statement createStatement(final Connection connection) throws SQLException { 050 return connection.prepareCall(sql, resultSetType, resultSetConcurrency); 051 } 052 } 053 054 /** 055 * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). 056 */ 057 private class PreparedCallWithResultSetHoldability implements StatementBuilder { 058 @Override 059 public Statement createStatement(final Connection connection) throws SQLException { 060 return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); 061 } 062 } 063 064 /** 065 * Builder for prepareStatement(String sql). 066 */ 067 private class PreparedStatementSQL implements StatementBuilder { 068 @Override 069 public Statement createStatement(final Connection connection) throws SQLException { 070 return connection.prepareStatement(sql); 071 } 072 } 073 074 /** 075 * Builder for prepareStatement(String sql, int autoGeneratedKeys). 076 */ 077 private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder { 078 @Override 079 public Statement createStatement(final Connection connection) throws SQLException { 080 return connection.prepareStatement(sql, autoGeneratedKeys); 081 } 082 } 083 084 /** 085 * Builder for prepareStatement(String sql, int[] columnIndexes). 086 */ 087 private class PreparedStatementWithColumnIndexes implements StatementBuilder { 088 @Override 089 public Statement createStatement(final Connection connection) throws SQLException { 090 return connection.prepareStatement(sql, columnIndexes); 091 } 092 } 093 094 /** 095 * Builder for prepareStatement(String sql, String[] columnNames). 096 */ 097 private class PreparedStatementWithColumnNames implements StatementBuilder { 098 @Override 099 public Statement createStatement(final Connection connection) throws SQLException { 100 return connection.prepareStatement(sql, columnNames); 101 } 102 } 103 104 /** 105 * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency). 106 */ 107 private class PreparedStatementWithResultSetConcurrency implements StatementBuilder { 108 @Override 109 public Statement createStatement(final Connection connection) throws SQLException { 110 return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); 111 } 112 } 113 114 /** 115 * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). 116 */ 117 private class PreparedStatementWithResultSetHoldability implements StatementBuilder { 118 @Override 119 public Statement createStatement(final Connection connection) throws SQLException { 120 return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); 121 } 122 } 123 124 /** 125 * Interface for Prepared or Callable Statement. 126 */ 127 private interface StatementBuilder { 128 Statement createStatement(Connection connection) throws SQLException; 129 } 130 131 /** 132 * SQL defining Prepared or Callable Statement 133 */ 134 private final String sql; 135 136 /** 137 * Result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, 138 * or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 139 */ 140 private final Integer resultSetType; 141 142 /** 143 * Result set concurrency. A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 144 * <code>ResultSet.CONCUR_UPDATABLE</code>. 145 */ 146 private final Integer resultSetConcurrency; 147 148 /** 149 * Result set holdability. One of the following <code>ResultSet</code> constants: 150 * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 151 */ 152 private final Integer resultSetHoldability; 153 154 /** Database catalog. */ 155 private final String catalog; 156 157 /** Database schema. */ 158 private final String schema; 159 160 /** 161 * A flag indicating whether auto-generated keys should be returned; one of 162 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 163 */ 164 private final Integer autoGeneratedKeys; 165 166 /** 167 * An array of column indexes indicating the columns that should be returned from the inserted row or rows. 168 */ 169 private final int[] columnIndexes; 170 171 /** 172 * An array of column names indicating the columns that should be returned from the inserted row or rows. 173 */ 174 private final String[] columnNames; 175 176 /** 177 * Statement type, prepared or callable. 178 */ 179 private final StatementType statementType; 180 181 /** Statement builder */ 182 private transient StatementBuilder builder; 183 184 /** 185 * Constructs a key to uniquely identify a prepared statement. 186 * 187 * @param sql 188 * The SQL statement. 189 * @deprecated Use {@link #PStmtKey(String, String, String)}. 190 */ 191 @Deprecated 192 public PStmtKey(final String sql) { 193 this(sql, null, StatementType.PREPARED_STATEMENT); 194 } 195 196 /** 197 * Constructs a key to uniquely identify a prepared statement. 198 * 199 * @param sql 200 * The SQL statement. 201 * @param resultSetType 202 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 203 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 204 * @param resultSetConcurrency 205 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 206 * <code>ResultSet.CONCUR_UPDATABLE</code>. 207 * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. 208 */ 209 @Deprecated 210 public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) { 211 this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 212 } 213 214 /** 215 * Constructs a key to uniquely identify a prepared statement. 216 * 217 * @param sql 218 * The SQL statement. 219 * @param catalog 220 * The catalog. 221 * @deprecated Use {@link #PStmtKey(String, String, String)}. 222 */ 223 @Deprecated 224 public PStmtKey(final String sql, final String catalog) { 225 this(sql, catalog, StatementType.PREPARED_STATEMENT); 226 } 227 228 /** 229 * Constructs a key to uniquely identify a prepared statement. 230 * 231 * @param sql 232 * The SQL statement. 233 * @param catalog 234 * The catalog. 235 * @param autoGeneratedKeys 236 * A flag indicating whether auto-generated keys should be returned; one of 237 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 238 * @deprecated Use {@link #PStmtKey(String, String, String, int)}. 239 */ 240 @Deprecated 241 public PStmtKey(final String sql, final String catalog, final int autoGeneratedKeys) { 242 this(sql, catalog, StatementType.PREPARED_STATEMENT, autoGeneratedKeys); 243 } 244 245 /** 246 * Constructs a key to uniquely identify a prepared statement. 247 * 248 * @param sql 249 * The SQL statement. 250 * @param catalog 251 * The catalog. 252 * @param resultSetType 253 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 254 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 255 * @param resultSetConcurrency 256 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 257 * <code>ResultSet.CONCUR_UPDATABLE</code>. 258 * @deprecated Use @link {@link #PStmtKey(String, String, String, int, int)}. 259 */ 260 @Deprecated 261 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) { 262 this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 263 } 264 265 /** 266 * Constructs a key to uniquely identify a prepared statement. 267 * 268 * @param sql 269 * The SQL statement. 270 * @param catalog 271 * The catalog. 272 * @param resultSetType 273 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 274 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 275 * @param resultSetConcurrency 276 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 277 * <code>ResultSet.CONCUR_UPDATABLE</code> 278 * @param resultSetHoldability 279 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 280 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 281 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}. 282 */ 283 @Deprecated 284 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 285 final int resultSetHoldability) { 286 this(sql, catalog, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); 287 } 288 289 /** 290 * Constructs a key to uniquely identify a prepared statement. 291 * 292 * @param sql 293 * The SQL statement. 294 * @param catalog 295 * The catalog. 296 * @param resultSetType 297 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 298 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> 299 * @param resultSetConcurrency 300 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 301 * <code>ResultSet.CONCUR_UPDATABLE</code>. 302 * @param resultSetHoldability 303 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 304 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 305 * @param statementType 306 * The SQL statement type, prepared or callable. 307 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)} 308 */ 309 @Deprecated 310 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 311 final int resultSetHoldability, final StatementType statementType) { 312 this.sql = sql; 313 this.catalog = catalog; 314 this.schema = null; 315 this.resultSetType = resultSetType; 316 this.resultSetConcurrency = resultSetConcurrency; 317 this.resultSetHoldability = resultSetHoldability; 318 this.statementType = statementType; 319 this.autoGeneratedKeys = null; 320 this.columnIndexes = null; 321 this.columnNames = null; 322 // create builder 323 if (statementType == StatementType.PREPARED_STATEMENT) { 324 this.builder = new PreparedStatementWithResultSetHoldability(); 325 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 326 this.builder = new PreparedCallWithResultSetHoldability(); 327 } 328 } 329 330 /** 331 * Constructs a key to uniquely identify a prepared statement. 332 * 333 * @param sql 334 * The SQL statement. 335 * @param catalog 336 * The catalog. 337 * @param resultSetType 338 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 339 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 340 * @param resultSetConcurrency 341 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 342 * <code>ResultSet.CONCUR_UPDATABLE</code>. 343 * @param statementType 344 * The SQL statement type, prepared or callable. 345 * @deprecated Use {@link #PStmtKey(String, String, String, int, int, PoolingConnection.StatementType)}. 346 */ 347 @Deprecated 348 public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, 349 final StatementType statementType) { 350 this.sql = sql; 351 this.catalog = catalog; 352 this.schema = null; 353 this.resultSetType = resultSetType; 354 this.resultSetConcurrency = resultSetConcurrency; 355 this.resultSetHoldability = null; 356 this.statementType = statementType; 357 this.autoGeneratedKeys = null; 358 this.columnIndexes = null; 359 this.columnNames = null; 360 // create builder 361 if (statementType == StatementType.PREPARED_STATEMENT) { 362 this.builder = new PreparedStatementWithResultSetConcurrency(); 363 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 364 this.builder = new PreparedCallWithResultSetConcurrency(); 365 } 366 } 367 368 /** 369 * Constructs a key to uniquely identify a prepared statement. 370 * 371 * @param sql 372 * The SQL statement. 373 * @param catalog 374 * The catalog. 375 * @param columnIndexes 376 * An array of column indexes indicating the columns that should be returned from the inserted row or 377 * rows. 378 * @deprecated Use {@link #PStmtKey(String, String, String, int[])}. 379 */ 380 @Deprecated 381 public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) { 382 this.sql = sql; 383 this.catalog = catalog; 384 this.schema = null; 385 this.statementType = StatementType.PREPARED_STATEMENT; 386 this.autoGeneratedKeys = null; 387 this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); 388 this.columnNames = null; 389 this.resultSetType = null; 390 this.resultSetConcurrency = null; 391 this.resultSetHoldability = null; 392 // create builder 393 this.builder = new PreparedStatementWithColumnIndexes(); 394 } 395 396 /** 397 * Constructs a key to uniquely identify a prepared statement. 398 * 399 * @param sql 400 * The SQL statement. 401 * @param catalog 402 * The catalog. 403 * @param statementType 404 * The SQL statement type, prepared or callable. 405 * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType)}. 406 */ 407 @Deprecated 408 public PStmtKey(final String sql, final String catalog, final StatementType statementType) { 409 this.sql = sql; 410 this.catalog = catalog; 411 this.schema = null; 412 this.statementType = statementType; 413 this.autoGeneratedKeys = null; 414 this.columnIndexes = null; 415 this.columnNames = null; 416 this.resultSetType = null; 417 this.resultSetConcurrency = null; 418 this.resultSetHoldability = null; 419 // create builder 420 if (statementType == StatementType.PREPARED_STATEMENT) { 421 this.builder = new PreparedStatementSQL(); 422 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 423 this.builder = new PreparedCallSQL(); 424 } 425 } 426 427 /** 428 * Constructs a key to uniquely identify a prepared statement. 429 * 430 * @param sql 431 * The SQL statement. 432 * @param catalog 433 * The catalog. 434 * @param statementType 435 * The SQL statement type, prepared or callable. 436 * @param autoGeneratedKeys 437 * A flag indicating whether auto-generated keys should be returned; one of 438 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 439 * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType, Integer)} 440 */ 441 @Deprecated 442 public PStmtKey(final String sql, final String catalog, final StatementType statementType, 443 final Integer autoGeneratedKeys) { 444 this.sql = sql; 445 this.catalog = catalog; 446 this.schema = null; 447 this.statementType = statementType; 448 this.autoGeneratedKeys = autoGeneratedKeys; 449 this.columnIndexes = null; 450 this.columnNames = null; 451 this.resultSetType = null; 452 this.resultSetConcurrency = null; 453 this.resultSetHoldability = null; 454 // create builder 455 if (statementType == StatementType.PREPARED_STATEMENT) { 456 this.builder = new PreparedStatementWithAutoGeneratedKeys(); 457 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 458 this.builder = new PreparedCallSQL(); 459 } 460 } 461 462 /** 463 * Constructs a key to uniquely identify a prepared statement. 464 * 465 * @param sql 466 * The SQL statement. 467 * @param catalog 468 * The catalog. 469 * @param schema 470 * The schema 471 * @since 2.5.0 472 */ 473 public PStmtKey(final String sql, final String catalog, final String schema) { 474 this(sql, catalog, schema, StatementType.PREPARED_STATEMENT); 475 } 476 477 /** 478 * Constructs a key to uniquely identify a prepared statement. 479 * 480 * @param sql 481 * The SQL statement. 482 * @param catalog 483 * The catalog. 484 * @param schema 485 * The schema 486 * @param autoGeneratedKeys 487 * A flag indicating whether auto-generated keys should be returned; one of 488 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 489 * @since 2.5.0 490 */ 491 public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) { 492 this(sql, catalog, schema, StatementType.PREPARED_STATEMENT, autoGeneratedKeys); 493 } 494 495 /** 496 * Constructs a key to uniquely identify a prepared statement. 497 * 498 * @param sql 499 * The SQL statement. 500 * @param catalog 501 * The catalog. 502 * @param schema 503 * The schema 504 * @param resultSetType 505 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 506 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 507 * @param resultSetConcurrency 508 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 509 * <code>ResultSet.CONCUR_UPDATABLE</code>. 510 */ 511 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) { 512 this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); 513 } 514 515 /** 516 * Constructs a key to uniquely identify a prepared statement. 517 * 518 * @param sql 519 * The SQL statement. 520 * @param catalog 521 * The catalog. 522 * @param schema 523 * The schema 524 * @param resultSetType 525 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 526 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 527 * @param resultSetConcurrency 528 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 529 * <code>ResultSet.CONCUR_UPDATABLE</code> 530 * @param resultSetHoldability 531 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 532 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 533 * @since 2.5.0 534 */ 535 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 536 final int resultSetHoldability) { 537 this(sql, catalog, schema, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); 538 } 539 540 /** 541 * Constructs a key to uniquely identify a prepared statement. 542 * 543 * @param sql 544 * The SQL statement. 545 * @param catalog 546 * The catalog. 547 * @param schema 548 * The schema. 549 * @param resultSetType 550 * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 551 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> 552 * @param resultSetConcurrency 553 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 554 * <code>ResultSet.CONCUR_UPDATABLE</code>. 555 * @param resultSetHoldability 556 * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 557 * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 558 * @param statementType 559 * The SQL statement type, prepared or callable. 560 * @since 2.5.0 561 */ 562 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 563 final int resultSetHoldability, final StatementType statementType) { 564 this.sql = sql; 565 this.catalog = catalog; 566 this.schema = schema; 567 this.resultSetType = resultSetType; 568 this.resultSetConcurrency = resultSetConcurrency; 569 this.resultSetHoldability = resultSetHoldability; 570 this.statementType = statementType; 571 this.autoGeneratedKeys = null; 572 this.columnIndexes = null; 573 this.columnNames = null; 574 // create builder 575 if (statementType == StatementType.PREPARED_STATEMENT) { 576 this.builder = new PreparedStatementWithResultSetHoldability(); 577 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 578 this.builder = new PreparedCallWithResultSetHoldability(); 579 } 580 } 581 582 /** 583 * Constructs a key to uniquely identify a prepared statement. 584 * 585 * @param sql 586 * The SQL statement. 587 * @param catalog 588 * The catalog. 589 * @param schema 590 * The schema. 591 * @param resultSetType 592 * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 593 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 594 * @param resultSetConcurrency 595 * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 596 * <code>ResultSet.CONCUR_UPDATABLE</code>. 597 * @param statementType 598 * The SQL statement type, prepared or callable. 599 * @since 2.5.0 600 */ 601 public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, 602 final StatementType statementType) { 603 this.sql = sql; 604 this.catalog = catalog; 605 this.schema = schema; 606 this.resultSetType = resultSetType; 607 this.resultSetConcurrency = resultSetConcurrency; 608 this.resultSetHoldability = null; 609 this.statementType = statementType; 610 this.autoGeneratedKeys = null; 611 this.columnIndexes = null; 612 this.columnNames = null; 613 // create builder 614 if (statementType == StatementType.PREPARED_STATEMENT) { 615 this.builder = new PreparedStatementWithResultSetConcurrency(); 616 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 617 this.builder = new PreparedCallWithResultSetConcurrency(); 618 } 619 } 620 621 /** 622 * Constructs a key to uniquely identify a prepared statement. 623 * 624 * @param sql 625 * The SQL statement. 626 * @param catalog 627 * The catalog. 628 * @param schema 629 * The schema. 630 * @param columnIndexes 631 * An array of column indexes indicating the columns that should be returned from the inserted row or 632 * rows. 633 */ 634 public PStmtKey(final String sql, final String catalog, final String schema, final int[] columnIndexes) { 635 this.sql = sql; 636 this.catalog = catalog; 637 this.schema = schema; 638 this.statementType = StatementType.PREPARED_STATEMENT; 639 this.autoGeneratedKeys = null; 640 this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); 641 this.columnNames = null; 642 this.resultSetType = null; 643 this.resultSetConcurrency = null; 644 this.resultSetHoldability = null; 645 // create builder 646 this.builder = new PreparedStatementWithColumnIndexes(); 647 } 648 649 /** 650 * Constructs a key to uniquely identify a prepared statement. 651 * 652 * @param sql 653 * The SQL statement. 654 * @param catalog 655 * The catalog. 656 * @param schema 657 * The schema. 658 * @param statementType 659 * The SQL statement type, prepared or callable. 660 * @since 2.5.0 661 */ 662 public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType) { 663 this.sql = sql; 664 this.catalog = catalog; 665 this.schema = schema; 666 this.statementType = statementType; 667 this.autoGeneratedKeys = null; 668 this.columnIndexes = null; 669 this.columnNames = null; 670 this.resultSetType = null; 671 this.resultSetConcurrency = null; 672 this.resultSetHoldability = null; 673 // create builder 674 if (statementType == StatementType.PREPARED_STATEMENT) { 675 this.builder = new PreparedStatementSQL(); 676 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 677 this.builder = new PreparedCallSQL(); 678 } 679 } 680 681 /** 682 * Constructs a key to uniquely identify a prepared statement. 683 * 684 * @param sql 685 * The SQL statement. 686 * @param catalog 687 * The catalog. 688 * @param schema 689 * The schema. 690 * @param statementType 691 * The SQL statement type, prepared or callable. 692 * @param autoGeneratedKeys 693 * A flag indicating whether auto-generated keys should be returned; one of 694 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 695 * @since 2.5.0 696 */ 697 public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType, 698 final Integer autoGeneratedKeys) { 699 this.sql = sql; 700 this.catalog = catalog; 701 this.schema = schema; 702 this.statementType = statementType; 703 this.autoGeneratedKeys = autoGeneratedKeys; 704 this.columnIndexes = null; 705 this.columnNames = null; 706 this.resultSetType = null; 707 this.resultSetConcurrency = null; 708 this.resultSetHoldability = null; 709 // create builder 710 if (statementType == StatementType.PREPARED_STATEMENT) { 711 this.builder = new PreparedStatementWithAutoGeneratedKeys(); 712 } else if (statementType == StatementType.CALLABLE_STATEMENT) { 713 this.builder = new PreparedCallSQL(); 714 } 715 } 716 717 /** 718 * Constructs a key to uniquely identify a prepared statement. 719 * 720 * @param sql 721 * The SQL statement. 722 * @param catalog 723 * The catalog. 724 * @param schema 725 * The schema. 726 * @param columnNames 727 * An array of column names indicating the columns that should be returned from the inserted row or rows. 728 * @since 2.5.0 729 */ 730 public PStmtKey(final String sql, final String catalog, final String schema, final String[] columnNames) { 731 this.sql = sql; 732 this.catalog = catalog; 733 this.schema = schema; 734 this.statementType = StatementType.PREPARED_STATEMENT; 735 this.autoGeneratedKeys = null; 736 this.columnIndexes = null; 737 this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); 738 this.resultSetType = null; 739 this.resultSetConcurrency = null; 740 this.resultSetHoldability = null; 741 // create builder 742 builder = new PreparedStatementWithColumnNames(); 743 } 744 745 /** 746 * Constructs a key to uniquely identify a prepared statement. 747 * 748 * @param sql 749 * The SQL statement. 750 * @param catalog 751 * The catalog. 752 * @param columnNames 753 * An array of column names indicating the columns that should be returned from the inserted row or rows. 754 * @deprecated Use {@link #PStmtKey(String, String, String, String[])}. 755 */ 756 @Deprecated 757 public PStmtKey(final String sql, final String catalog, final String[] columnNames) { 758 this.sql = sql; 759 this.catalog = catalog; 760 this.schema = null; 761 this.statementType = StatementType.PREPARED_STATEMENT; 762 this.autoGeneratedKeys = null; 763 this.columnIndexes = null; 764 this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); 765 this.resultSetType = null; 766 this.resultSetConcurrency = null; 767 this.resultSetHoldability = null; 768 // create builder 769 builder = new PreparedStatementWithColumnNames(); 770 } 771 772 /** 773 * Creates a new Statement from the given Connection. 774 * 775 * @param connection 776 * The Connection to use to create the statement. 777 * @return The statement. 778 * @throws SQLException 779 * Thrown when there is a problem creating the statement. 780 */ 781 public Statement createStatement(final Connection connection) throws SQLException { 782 if (builder == null) { 783 throw new IllegalStateException("Prepared statement key is invalid."); 784 } 785 return builder.createStatement(connection); 786 } 787 788 @Override 789 public boolean equals(final Object obj) { 790 if (this == obj) { 791 return true; 792 } 793 if (obj == null) { 794 return false; 795 } 796 if (getClass() != obj.getClass()) { 797 return false; 798 } 799 final PStmtKey other = (PStmtKey) obj; 800 if (!Objects.equals(autoGeneratedKeys, other.autoGeneratedKeys)) { 801 return false; 802 } 803 if (!Objects.equals(catalog, other.catalog)) { 804 return false; 805 } 806 if (!Arrays.equals(columnIndexes, other.columnIndexes)) { 807 return false; 808 } 809 if (!Arrays.equals(columnNames, other.columnNames)) { 810 return false; 811 } 812 if (!Objects.equals(resultSetConcurrency, other.resultSetConcurrency)) { 813 return false; 814 } 815 if (!Objects.equals(resultSetHoldability, other.resultSetHoldability)) { 816 return false; 817 } 818 if (!Objects.equals(resultSetType, other.resultSetType)) { 819 return false; 820 } 821 if (!Objects.equals(schema, other.schema)) { 822 return false; 823 } 824 if (!Objects.equals(sql, other.sql)) { 825 return false; 826 } 827 return statementType == other.statementType; 828 } 829 830 /** 831 * Gets a flag indicating whether auto-generated keys should be returned; one of 832 * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>. 833 * 834 * @return a flag indicating whether auto-generated keys should be returned. 835 */ 836 public Integer getAutoGeneratedKeys() { 837 return autoGeneratedKeys; 838 } 839 840 /** 841 * The catalog. 842 * 843 * @return The catalog. 844 */ 845 public String getCatalog() { 846 return catalog; 847 } 848 849 /** 850 * Gets an array of column indexes indicating the columns that should be returned from the inserted row or rows. 851 * 852 * @return An array of column indexes. 853 */ 854 public int[] getColumnIndexes() { 855 return columnIndexes == null ? null : columnIndexes.clone(); 856 } 857 858 /** 859 * Gets an array of column names indicating the columns that should be returned from the inserted row or rows. 860 * 861 * @return An array of column names. 862 */ 863 public String[] getColumnNames() { 864 return columnNames == null ? null : columnNames.clone(); 865 } 866 867 /** 868 * Gets the result set concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or 869 * <code>ResultSet.CONCUR_UPDATABLE</code>. 870 * 871 * @return The result set concurrency type. 872 */ 873 public Integer getResultSetConcurrency() { 874 return resultSetConcurrency; 875 } 876 877 /** 878 * Gets the result set holdability, one of the following <code>ResultSet</code> constants: 879 * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. 880 * 881 * @return The result set holdability. 882 */ 883 public Integer getResultSetHoldability() { 884 return resultSetHoldability; 885 } 886 887 /** 888 * Gets the result set type, one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 889 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. 890 * 891 * @return the result set type. 892 */ 893 public Integer getResultSetType() { 894 return resultSetType; 895 } 896 897 /** 898 * The schema. 899 * 900 * @return The catalog. 901 */ 902 public String getSchema() { 903 return schema; 904 } 905 906 /** 907 * Gets the SQL statement. 908 * 909 * @return the SQL statement. 910 */ 911 public String getSql() { 912 return sql; 913 } 914 915 /** 916 * The SQL statement type. 917 * 918 * @return The SQL statement type. 919 */ 920 public StatementType getStmtType() { 921 return statementType; 922 } 923 924 @Override 925 public int hashCode() { 926 return Objects.hash(autoGeneratedKeys, catalog, Arrays.hashCode(columnIndexes), Arrays.hashCode(columnNames), 927 resultSetConcurrency, resultSetHoldability, resultSetType, schema, sql, statementType); 928 } 929 930 @Override 931 public String toString() { 932 final StringBuilder buf = new StringBuilder(); 933 buf.append("PStmtKey: sql="); 934 buf.append(sql); 935 buf.append(", catalog="); 936 buf.append(catalog); 937 buf.append(", schema="); 938 buf.append(schema); 939 buf.append(", resultSetType="); 940 buf.append(resultSetType); 941 buf.append(", resultSetConcurrency="); 942 buf.append(resultSetConcurrency); 943 buf.append(", resultSetHoldability="); 944 buf.append(resultSetHoldability); 945 buf.append(", autoGeneratedKeys="); 946 buf.append(autoGeneratedKeys); 947 buf.append(", columnIndexes="); 948 buf.append(Arrays.toString(columnIndexes)); 949 buf.append(", columnNames="); 950 buf.append(Arrays.toString(columnNames)); 951 buf.append(", statementType="); 952 buf.append(statementType); 953 return buf.toString(); 954 } 955}