1 package SQLite.JDBC2x; 2 3 import java.sql.*; 4 import java.math.BigDecimal; 5 import java.util.*; 6 7 class BatchArg { 8 String arg; 9 boolean blob; 10 BatchArg(String arg, boolean blob)11 BatchArg(String arg, boolean blob) { 12 if (arg == null) { 13 this.arg = null; 14 } else { 15 this.arg = new String(arg); 16 } 17 this.blob = blob; 18 } 19 } 20 21 public class JDBCPreparedStatement extends JDBCStatement 22 implements java.sql.PreparedStatement { 23 24 private String sql; 25 private String args[]; 26 private boolean blobs[]; 27 private ArrayList batch; 28 private static final boolean nullrepl = 29 SQLite.Database.version().compareTo("2.5.0") < 0; 30 31 public JDBCPreparedStatement(JDBCConnection conn, String sql) { 32 super(conn); 33 this.args = null; 34 this.blobs = null; 35 this.batch = null; 36 this.sql = fixup(sql); 37 } 38 39 private String fixup(String sql) { 40 StringBuffer sb = new StringBuffer(sql.length()); 41 boolean inq = false; 42 int nparm = 0; 43 int iscreate = -1; 44 for (int i = 0; i < sql.length(); i++) { 45 char c = sql.charAt(i); 46 if (c == '\'') { 47 if (inq) { 48 char nextChar = 0; 49 if(i + 1 < sql.length()) { 50 nextChar = sql.charAt(i + 1); 51 } 52 if (nextChar == '\'') { 53 sb.append(c); 54 sb.append(nextChar); 55 i++; 56 } else { 57 inq = false; 58 sb.append(c); 59 } 60 } else { 61 inq = true; 62 sb.append(c); 63 } 64 } else if (c == '?') { 65 if (inq) { 66 sb.append(c); 67 } else { 68 ++nparm; 69 sb.append(nullrepl ? "'%q'" : "%Q"); 70 } 71 } else if (c == ';') { 72 if (!inq) { 73 if (iscreate < 0) { 74 int ii = 0; 75 while (sb.charAt(ii) == ' ' || 76 sb.charAt(ii) == '\t' || 77 sb.charAt(ii) == '\n' || 78 sb.charAt(ii) == '\r') { 79 ++ii; 80 } 81 String t = sb.substring(ii, ii + 6); 82 if (t.compareToIgnoreCase("create") == 0) { 83 iscreate = 1; 84 } else { 85 iscreate = 0; 86 } 87 } 88 if (iscreate == 0) { 89 break; 90 } 91 } 92 sb.append(c); 93 } else if (c == '%') { 94 sb.append("%%"); 95 } else { 96 sb.append(c); 97 } 98 } 99 args = new String[nparm]; 100 blobs = new boolean[nparm]; 101 try { 102 clearParameters(); 103 } catch (SQLException e) { 104 } 105 return sb.toString(); 106 } 107 108 private String fixup2(String sql) { 109 if (!conn.db.is3()) { 110 return sql; 111 } 112 StringBuffer sb = new StringBuffer(sql.length()); 113 int parm = -1; 114 for (int i = 0; i < sql.length(); i++) { 115 char c = sql.charAt(i); 116 if (c == '%') { 117 sb.append(c); 118 ++i; 119 c = sql.charAt(i); 120 if (c == 'Q') { 121 parm++; 122 if (blobs[parm]) { 123 c = 's'; 124 } 125 } 126 } 127 sb.append(c); 128 } 129 return sb.toString(); 130 } 131 132 public ResultSet executeQuery() throws SQLException { 133 return executeQuery(fixup2(sql), args, false); 134 } 135 136 public int executeUpdate() throws SQLException { 137 executeQuery(fixup2(sql), args, true); 138 return updcnt; 139 } 140 141 public void setNull(int parameterIndex, int sqlType) throws SQLException { 142 if (parameterIndex < 1 || parameterIndex > args.length) { 143 throw new SQLException("bad parameter index"); 144 } 145 args[parameterIndex - 1] = nullrepl ? "" : null; 146 blobs[parameterIndex - 1] = false; 147 } 148 149 public void setBoolean(int parameterIndex, boolean x) 150 throws SQLException { 151 if (parameterIndex < 1 || parameterIndex > args.length) { 152 throw new SQLException("bad parameter index"); 153 } 154 args[parameterIndex - 1] = x ? "1" : "0"; 155 blobs[parameterIndex - 1] = false; 156 } 157 158 public void setByte(int parameterIndex, byte x) throws SQLException { 159 if (parameterIndex < 1 || parameterIndex > args.length) { 160 throw new SQLException("bad parameter index"); 161 } 162 args[parameterIndex - 1] = "" + x; 163 blobs[parameterIndex - 1] = false; 164 } 165 166 public void setShort(int parameterIndex, short x) throws SQLException { 167 if (parameterIndex < 1 || parameterIndex > args.length) { 168 throw new SQLException("bad parameter index"); 169 } 170 args[parameterIndex - 1] = "" + x; 171 blobs[parameterIndex - 1] = false; 172 } 173 174 public void setInt(int parameterIndex, int x) throws SQLException { 175 if (parameterIndex < 1 || parameterIndex > args.length) { 176 throw new SQLException("bad parameter index"); 177 } 178 args[parameterIndex - 1] = "" + x; 179 blobs[parameterIndex - 1] = false; 180 } 181 182 public void setLong(int parameterIndex, long x) throws SQLException { 183 if (parameterIndex < 1 || parameterIndex > args.length) { 184 throw new SQLException("bad parameter index"); 185 } 186 args[parameterIndex - 1] = "" + x; 187 blobs[parameterIndex - 1] = false; 188 } 189 190 public void setFloat(int parameterIndex, float x) throws SQLException { 191 if (parameterIndex < 1 || parameterIndex > args.length) { 192 throw new SQLException("bad parameter index"); 193 } 194 args[parameterIndex - 1] = "" + x; 195 blobs[parameterIndex - 1] = false; 196 } 197 198 public void setDouble(int parameterIndex, double x) throws SQLException { 199 if (parameterIndex < 1 || parameterIndex > args.length) { 200 throw new SQLException("bad parameter index"); 201 } 202 args[parameterIndex - 1] = "" + x; 203 blobs[parameterIndex - 1] = false; 204 } 205 206 public void setBigDecimal(int parameterIndex, BigDecimal x) 207 throws SQLException { 208 if (parameterIndex < 1 || parameterIndex > args.length) { 209 throw new SQLException("bad parameter index"); 210 } 211 if (x == null) { 212 args[parameterIndex - 1] = nullrepl ? "" : null; 213 } else { 214 args[parameterIndex - 1] = "" + x; 215 } 216 blobs[parameterIndex - 1] = false; 217 } 218 219 public void setString(int parameterIndex, String x) throws SQLException { 220 if (parameterIndex < 1 || parameterIndex > args.length) { 221 throw new SQLException("bad parameter index"); 222 } 223 if (x == null) { 224 args[parameterIndex - 1] = nullrepl ? "" : null; 225 } else { 226 args[parameterIndex - 1] = x; 227 } 228 blobs[parameterIndex - 1] = false; 229 } 230 231 public void setBytes(int parameterIndex, byte x[]) throws SQLException { 232 if (parameterIndex < 1 || parameterIndex > args.length) { 233 throw new SQLException("bad parameter index"); 234 } 235 blobs[parameterIndex - 1] = false; 236 if (x == null) { 237 args[parameterIndex - 1] = nullrepl ? "" : null; 238 } else { 239 if (conn.db.is3()) { 240 args[parameterIndex - 1] = SQLite.StringEncoder.encodeX(x); 241 blobs[parameterIndex - 1] = true; 242 } else { 243 args[parameterIndex - 1] = SQLite.StringEncoder.encode(x); 244 } 245 } 246 } 247 248 public void setDate(int parameterIndex, java.sql.Date x) 249 throws SQLException { 250 if (parameterIndex < 1 || parameterIndex > args.length) { 251 throw new SQLException("bad parameter index"); 252 } 253 if (x == null) { 254 args[parameterIndex - 1] = nullrepl ? "" : null; 255 } else { 256 if (conn.useJulian) { 257 args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime())); 258 } else { 259 args[parameterIndex - 1] = x.toString(); 260 } 261 } 262 blobs[parameterIndex - 1] = false; 263 } 264 265 public void setTime(int parameterIndex, java.sql.Time x) 266 throws SQLException { 267 if (parameterIndex < 1 || parameterIndex > args.length) { 268 throw new SQLException("bad parameter index"); 269 } 270 if (x == null) { 271 args[parameterIndex - 1] = nullrepl ? "" : null; 272 } else { 273 if (conn.useJulian) { 274 args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime())); 275 } else { 276 args[parameterIndex - 1] = x.toString(); 277 } 278 } 279 blobs[parameterIndex - 1] = false; 280 } 281 282 public void setTimestamp(int parameterIndex, java.sql.Timestamp x) 283 throws SQLException { 284 if (parameterIndex < 1 || parameterIndex > args.length) { 285 throw new SQLException("bad parameter index"); 286 } 287 if (x == null) { 288 args[parameterIndex - 1] = nullrepl ? "" : null; 289 } else { 290 if (conn.useJulian) { 291 args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime())); 292 } else { 293 args[parameterIndex - 1] = x.toString(); 294 } 295 } 296 blobs[parameterIndex - 1] = false; 297 } 298 299 public void setAsciiStream(int parameterIndex, java.io.InputStream x, 300 int length) throws SQLException { 301 throw new SQLException("not supported"); 302 } 303 304 public void setUnicodeStream(int parameterIndex, java.io.InputStream x, 305 int length) throws SQLException { 306 throw new SQLException("not supported"); 307 } 308 309 public void setBinaryStream(int parameterIndex, java.io.InputStream x, 310 int length) throws SQLException { 311 try { 312 byte[] data = new byte[length]; 313 x.read(data, 0, length); 314 setBytes(parameterIndex, data); 315 } catch (java.io.IOException e) { 316 throw new SQLException("I/O failed: " + e.toString()); 317 } 318 } 319 320 public void clearParameters() throws SQLException { 321 for (int i = 0; i < args.length; i++) { 322 args[i] = nullrepl ? "" : null; 323 blobs[i] = false; 324 } 325 } 326 327 public void setObject(int parameterIndex, Object x, int targetSqlType, 328 int scale) throws SQLException { 329 if (parameterIndex < 1 || parameterIndex > args.length) { 330 throw new SQLException("bad parameter index"); 331 } 332 if (x == null) { 333 args[parameterIndex - 1] = nullrepl ? "" : null; 334 } else { 335 if (x instanceof byte[]) { 336 byte[] bx = (byte[]) x; 337 if (conn.db.is3()) { 338 args[parameterIndex - 1] = 339 SQLite.StringEncoder.encodeX(bx); 340 blobs[parameterIndex - 1] = true; 341 return; 342 } 343 args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx); 344 } else { 345 args[parameterIndex - 1] = x.toString(); 346 } 347 } 348 blobs[parameterIndex - 1] = false; 349 } 350 351 public void setObject(int parameterIndex, Object x, int targetSqlType) 352 throws SQLException { 353 if (parameterIndex < 1 || parameterIndex > args.length) { 354 throw new SQLException("bad parameter index"); 355 } 356 if (x == null) { 357 args[parameterIndex - 1] = nullrepl ? "" : null; 358 } else { 359 if (x instanceof byte[]) { 360 byte[] bx = (byte[]) x; 361 if (conn.db.is3()) { 362 args[parameterIndex - 1] = 363 SQLite.StringEncoder.encodeX(bx); 364 blobs[parameterIndex - 1] = true; 365 return; 366 } 367 args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx); 368 } else { 369 args[parameterIndex - 1] = x.toString(); 370 } 371 } 372 blobs[parameterIndex - 1] = false; 373 } 374 375 public void setObject(int parameterIndex, Object x) throws SQLException { 376 if (parameterIndex < 1 || parameterIndex > args.length) { 377 throw new SQLException("bad parameter index"); 378 } 379 if (x == null) { 380 args[parameterIndex - 1] = nullrepl ? "" : null; 381 } else { 382 if (x instanceof byte[]) { 383 byte[] bx = (byte[]) x; 384 if (conn.db.is3()) { 385 args[parameterIndex - 1] = 386 SQLite.StringEncoder.encodeX(bx); 387 blobs[parameterIndex - 1] = true; 388 return; 389 } 390 args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx); 391 } else { 392 args[parameterIndex - 1] = x.toString(); 393 } 394 } 395 blobs[parameterIndex - 1] = false; 396 } 397 398 public boolean execute() throws SQLException { 399 return executeQuery(fixup2(sql), args, false) != null; 400 } 401 402 public void addBatch() throws SQLException { 403 if (batch == null) { 404 batch = new ArrayList(args.length); 405 } 406 if (args.length == 0) { 407 batch.add(new BatchArg(null, false)); 408 } else { 409 for (int i = 0; i < args.length; i++) { 410 batch.add(new BatchArg(args[i], blobs[i])); 411 } 412 } 413 } 414 415 public int[] executeBatch() throws SQLException { 416 if (batch == null) { 417 return new int[0]; 418 } 419 int[] ret; 420 if (args.length == 0) { 421 ret = new int[batch.size()]; 422 } else { 423 ret = new int[batch.size() / args.length]; 424 } 425 for (int i = 0; i < ret.length; i++) { 426 ret[i] = EXECUTE_FAILED; 427 } 428 int errs = 0; 429 int index = 0; 430 for (int i = 0; i < ret.length; i++) { 431 for (int k = 0; k < args.length; k++) { 432 BatchArg b = (BatchArg) batch.get(index++); 433 args[k] = b.arg; 434 blobs[k] = b.blob; 435 } 436 try { 437 ret[i] = executeUpdate(); 438 } catch (SQLException e) { 439 ++errs; 440 } 441 } 442 if (errs > 0) { 443 throw new BatchUpdateException("batch failed", ret); 444 } 445 return ret; 446 } 447 448 public void clearBatch() throws SQLException { 449 if (batch != null) { 450 batch.clear(); 451 batch = null; 452 } 453 } 454 455 public void close() throws SQLException { 456 clearBatch(); 457 super.close(); 458 } 459 460 public void setCharacterStream(int parameterIndex, 461 java.io.Reader reader, 462 int length) throws SQLException { 463 try { 464 char[] data = new char[length]; 465 reader.read(data); 466 setString(parameterIndex, new String(data)); 467 } catch (java.io.IOException e) { 468 throw new SQLException("I/O failed: " + e.toString()); 469 } 470 } 471 472 public void setRef(int i, Ref x) throws SQLException { 473 throw new SQLException("not supported"); 474 } 475 476 public void setBlob(int i, Blob x) throws SQLException { 477 throw new SQLException("not supported"); 478 } 479 480 public void setClob(int i, Clob x) throws SQLException { 481 throw new SQLException("not supported"); 482 } 483 484 public void setArray(int i, Array x) throws SQLException { 485 throw new SQLException("not supported"); 486 } 487 488 public ResultSetMetaData getMetaData() throws SQLException { 489 return rs.getMetaData(); 490 } 491 492 public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) 493 throws SQLException { 494 setDate(parameterIndex, x); 495 } 496 497 public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) 498 throws SQLException { 499 setTime(parameterIndex, x); 500 } 501 502 public void setTimestamp(int parameterIndex, java.sql.Timestamp x, 503 Calendar cal) throws SQLException { 504 setTimestamp(parameterIndex, x); 505 } 506 507 public void setNull(int parameterIndex, int sqlType, String typeName) 508 throws SQLException { 509 setNull(parameterIndex, sqlType); 510 } 511 512 public ParameterMetaData getParameterMetaData() throws SQLException { 513 throw new SQLException("not supported"); 514 } 515 516 public void registerOutputParameter(String parameterName, int sqlType) 517 throws SQLException { 518 throw new SQLException("not supported"); 519 } 520 521 public void registerOutputParameter(String parameterName, int sqlType, 522 int scale) 523 throws SQLException { 524 throw new SQLException("not supported"); 525 } 526 527 public void registerOutputParameter(String parameterName, int sqlType, 528 String typeName) 529 throws SQLException { 530 throw new SQLException("not supported"); 531 } 532 533 public java.net.URL getURL(int parameterIndex) throws SQLException { 534 throw new SQLException("not supported"); 535 } 536 537 public void setURL(int parameterIndex, java.net.URL url) 538 throws SQLException { 539 throw new SQLException("not supported"); 540 } 541 542 public void setNull(String parameterName, int sqlType) 543 throws SQLException { 544 throw new SQLException("not supported"); 545 } 546 547 public void setBoolean(String parameterName, boolean val) 548 throws SQLException { 549 throw new SQLException("not supported"); 550 } 551 552 public void setByte(String parameterName, byte val) 553 throws SQLException { 554 throw new SQLException("not supported"); 555 } 556 557 public void setShort(String parameterName, short val) 558 throws SQLException { 559 throw new SQLException("not supported"); 560 } 561 562 public void setInt(String parameterName, int val) 563 throws SQLException { 564 throw new SQLException("not supported"); 565 } 566 567 public void setLong(String parameterName, long val) 568 throws SQLException { 569 throw new SQLException("not supported"); 570 } 571 572 public void setFloat(String parameterName, float val) 573 throws SQLException { 574 throw new SQLException("not supported"); 575 } 576 577 public void setDouble(String parameterName, double val) 578 throws SQLException { 579 throw new SQLException("not supported"); 580 } 581 582 public void setBigDecimal(String parameterName, BigDecimal val) 583 throws SQLException { 584 throw new SQLException("not supported"); 585 } 586 587 public void setString(String parameterName, String val) 588 throws SQLException { 589 throw new SQLException("not supported"); 590 } 591 592 public void setBytes(String parameterName, byte val[]) 593 throws SQLException { 594 throw new SQLException("not supported"); 595 } 596 597 public void setDate(String parameterName, java.sql.Date val) 598 throws SQLException { 599 throw new SQLException("not supported"); 600 } 601 602 public void setTime(String parameterName, java.sql.Time val) 603 throws SQLException { 604 throw new SQLException("not supported"); 605 } 606 607 public void setTimestamp(String parameterName, java.sql.Timestamp val) 608 throws SQLException { 609 throw new SQLException("not supported"); 610 } 611 612 public void setAsciiStream(String parameterName, 613 java.io.InputStream s, int length) 614 throws SQLException { 615 throw new SQLException("not supported"); 616 } 617 618 public void setBinaryStream(String parameterName, 619 java.io.InputStream s, int length) 620 throws SQLException { 621 throw new SQLException("not supported"); 622 } 623 624 public void setObject(String parameterName, Object val, int targetSqlType, 625 int scale) 626 throws SQLException { 627 throw new SQLException("not supported"); 628 } 629 630 public void setObject(String parameterName, Object val, int targetSqlType) 631 throws SQLException { 632 throw new SQLException("not supported"); 633 } 634 635 public void setObject(String parameterName, Object val) 636 throws SQLException { 637 throw new SQLException("not supported"); 638 } 639 640 public void setCharacterStream(String parameterName, 641 java.io.Reader r, int length) 642 throws SQLException { 643 throw new SQLException("not supported"); 644 } 645 646 public void setDate(String parameterName, java.sql.Date val, 647 Calendar cal) 648 throws SQLException { 649 throw new SQLException("not supported"); 650 } 651 652 public void setTime(String parameterName, java.sql.Time val, 653 Calendar cal) 654 throws SQLException { 655 throw new SQLException("not supported"); 656 } 657 658 public void setTimestamp(String parameterName, java.sql.Timestamp val, 659 Calendar cal) 660 throws SQLException { 661 throw new SQLException("not supported"); 662 } 663 664 public void setNull(String parameterName, int sqlType, String typeName) 665 throws SQLException { 666 throw new SQLException("not supported"); 667 } 668 669 public String getString(String parameterName) throws SQLException { 670 throw new SQLException("not supported"); 671 } 672 673 public boolean getBoolean(String parameterName) throws SQLException { 674 throw new SQLException("not supported"); 675 } 676 677 public byte getByte(String parameterName) throws SQLException { 678 throw new SQLException("not supported"); 679 } 680 681 public short getShort(String parameterName) throws SQLException { 682 throw new SQLException("not supported"); 683 } 684 685 public int getInt(String parameterName) throws SQLException { 686 throw new SQLException("not supported"); 687 } 688 689 public long getLong(String parameterName) throws SQLException { 690 throw new SQLException("not supported"); 691 } 692 693 public float getFloat(String parameterName) throws SQLException { 694 throw new SQLException("not supported"); 695 } 696 697 public double getDouble(String parameterName) throws SQLException { 698 throw new SQLException("not supported"); 699 } 700 701 public byte[] getBytes(String parameterName) throws SQLException { 702 throw new SQLException("not supported"); 703 } 704 705 public java.sql.Date getDate(String parameterName) throws SQLException { 706 throw new SQLException("not supported"); 707 } 708 709 public java.sql.Time getTime(String parameterName) throws SQLException { 710 throw new SQLException("not supported"); 711 } 712 713 public java.sql.Timestamp getTimestamp(String parameterName) 714 throws SQLException { 715 throw new SQLException("not supported"); 716 } 717 718 public Object getObject(String parameterName) throws SQLException { 719 throw new SQLException("not supported"); 720 } 721 722 public Object getObject(int parameterIndex) throws SQLException { 723 throw new SQLException("not supported"); 724 } 725 726 public BigDecimal getBigDecimal(String parameterName) throws SQLException { 727 throw new SQLException("not supported"); 728 } 729 730 public Object getObject(String parameterName, Map map) 731 throws SQLException { 732 throw new SQLException("not supported"); 733 } 734 735 public Object getObject(int parameterIndex, Map map) 736 throws SQLException { 737 throw new SQLException("not supported"); 738 } 739 740 public Ref getRef(int parameterIndex) throws SQLException { 741 throw new SQLException("not supported"); 742 } 743 744 public Ref getRef(String parameterName) throws SQLException { 745 throw new SQLException("not supported"); 746 } 747 748 public Blob getBlob(String parameterName) throws SQLException { 749 throw new SQLException("not supported"); 750 } 751 752 public Blob getBlob(int parameterIndex) throws SQLException { 753 throw new SQLException("not supported"); 754 } 755 756 public Clob getClob(String parameterName) throws SQLException { 757 throw new SQLException("not supported"); 758 } 759 760 public Clob getClob(int parameterIndex) throws SQLException { 761 throw new SQLException("not supported"); 762 } 763 764 public Array getArray(String parameterName) throws SQLException { 765 throw new SQLException("not supported"); 766 } 767 768 public Array getArray(int parameterIndex) throws SQLException { 769 throw new SQLException("not supported"); 770 } 771 772 public java.sql.Date getDate(String parameterName, Calendar cal) 773 throws SQLException { 774 throw new SQLException("not supported"); 775 } 776 777 public java.sql.Date getDate(int parameterIndex, Calendar cal) 778 throws SQLException { 779 throw new SQLException("not supported"); 780 } 781 782 public java.sql.Time getTime(String parameterName, Calendar cal) 783 throws SQLException { 784 throw new SQLException("not supported"); 785 } 786 787 public java.sql.Time getTime(int parameterIndex, Calendar cal) 788 throws SQLException { 789 throw new SQLException("not supported"); 790 } 791 792 public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal) 793 throws SQLException { 794 throw new SQLException("not supported"); 795 } 796 797 public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal) 798 throws SQLException { 799 throw new SQLException("not supported"); 800 } 801 802 public java.net.URL getURL(String parameterName) throws SQLException { 803 throw new SQLException("not supported"); 804 } 805 806 } 807