1 2 12 package com.versant.core.jdbc.sql; 13 14 import com.versant.core.jdbc.metadata.*; 15 import com.versant.core.jdbc.sql.exp.SqlExp; 16 import com.versant.core.jdbc.sql.conv.DateTimestampConverter; 17 import com.versant.core.jdbc.sql.diff.TableDiff; 18 import com.versant.core.jdbc.sql.diff.ColumnDiff; 19 import com.versant.core.jdbc.sql.diff.ControlParams; 20 import com.versant.core.util.CharBuf; 21 22 import java.io.PrintWriter ; 23 import java.sql.*; 24 import java.util.HashMap ; 25 import java.util.Date ; 26 import java.util.ArrayList ; 27 import java.util.Iterator ; 28 29 import com.versant.core.util.CharBuf; 30 31 34 public class HypersonicSqlDriver extends SqlDriver { 35 36 39 public String getName() { 40 return "hypersonic"; 41 } 42 43 50 protected JdbcTypeMapping getTypeMapping(int jdbcType) { 51 switch (jdbcType) { 52 case Types.LONGVARBINARY: 53 case Types.BLOB: 54 return new JdbcTypeMapping("LONGVARBINARY", 55 0, 0, JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, 56 bytesConverterFactory); 57 case Types.CLOB: 58 case Types.LONGVARCHAR: 59 return new JdbcTypeMapping("LONGVARCHAR", 60 0, 0, JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, 61 null); 62 } 63 return super.getTypeMapping(jdbcType); 64 } 65 66 71 public HashMap getJavaTypeMappings() { 72 HashMap ans = super.getJavaTypeMappings(); 73 74 DateTimestampConverter.Factory dtcf = new DateTimestampConverter.Factory(); 75 ((JdbcJavaTypeMapping)ans.get(Date .class)).setConverterFactory(dtcf); 76 77 return ans; 78 } 79 80 83 public void generateCreateTable(JdbcTable t, Statement stat, PrintWriter out, 84 boolean comments) 85 throws SQLException { 86 CharBuf s = new CharBuf(); 87 if (comments && isCommentSupported() && t.comment != null) { 88 s.append(comment(t.comment)); 89 s.append('\n'); 90 } 91 s.append("CREATE CACHED TABLE "); 92 s.append(t.name); 93 s.append(" (\n"); 94 JdbcColumn[] cols = t.getColsForCreateTable(); 95 int nc = cols.length; 96 boolean first = true; 97 for (int i = 0; i < nc; i++) { 98 if (first) { 99 first = false; 100 } else { 101 s.append("\n"); 102 } 103 s.append(" "); 104 appendCreateColumn(t, cols[i], s, comments); 105 } 106 s.append("\n "); 107 appendPrimaryKeyConstraint(t, s); 108 appendIndexesInCreateTable(t, s); 109 s.append("\n)"); 110 appendTableType(t, s); 111 String sql = s.toString(); 112 if (out != null) print(out, sql); 113 if (stat != null) stat.execute(sql); 114 } 115 116 119 public boolean isSetTransactionIsolationLevelSupported() { 120 return false; 121 } 122 123 127 public boolean isAnsiJoinSyntax() { 128 return true; 129 } 130 131 135 public boolean isSubQueryJoinMayUseOuterQueryCols() { 136 return false; 137 } 138 139 142 public boolean isNullForeignKeyOk() { 143 return true; 144 } 145 146 151 public char[] getSelectForUpdate() { 152 return null; 153 } 154 155 158 public boolean isFetchSizeSupported() { 159 return false; 160 } 161 162 167 public boolean isUseIndexesForOrderCols() { 168 return true; 169 } 170 171 175 public boolean isLikeStupid() { 176 return true; 177 } 178 179 183 public boolean isPreparedStatementPoolingOK() { 184 return false; 185 } 186 187 190 public boolean isInsertBatchingSupported() { 191 return true; 192 } 193 194 197 public boolean isUpdateBatchingSupported() { 198 return true; 199 } 200 201 205 public JdbcNameGenerator createJdbcNameGenerator() { 206 DefaultJdbcNameGenerator n = createDefaultJdbcNameGenerator(); 207 n.setMaxColumnNameLength(31); 208 n.setMaxTableNameLength(31); 209 n.setMaxConstraintNameLength(31); 210 n.setMaxIndexNameLength(31); 211 return n; 212 } 213 214 218 protected void appendCreateColumnNulls(JdbcTable t, JdbcColumn c, 219 CharBuf s) { 220 if (c.nulls) { 221 s.append(" NULL"); 222 } else { 223 s.append(" NOT NULL"); 224 } 225 } 226 227 230 protected void appendPrimaryKeyConstraint(JdbcTable t, CharBuf s) { 231 s.append("CONSTRAINT "); 232 s.append(t.pkConstraintName); 233 s.append(" PRIMARY KEY ("); 234 appendColumnNameList(t.pk, s); 235 s.append(')'); 236 } 237 238 public void generateConstraints(JdbcTable t, Statement stat, 239 PrintWriter out, boolean comments) throws SQLException { 240 } 243 244 public boolean checkDDL(ArrayList tables, Connection con, 245 PrintWriter errors, PrintWriter fix, ControlParams params) 246 throws SQLException { 247 params.setCheckConstraint(false); 250 return super.checkDDL(tables, con, errors, fix, params); 251 } 252 253 271 272 275 protected void print(PrintWriter out, String sql) { 276 out.print(sql); 277 out.println(";"); 278 out.println(); 279 } 280 281 284 public void appendSqlFrom(JdbcTable table, String alias, 285 CharBuf s) { 286 s.append(table.name); 287 if (alias != null) { 288 s.append(" AS "); 289 s.append(alias); 290 } 291 } 292 293 protected boolean isValidSchemaTable(String tableName) { 294 if (tableName.startsWith("SYSTEM_")) { 295 return false; 296 } 297 return true; 298 } 299 300 307 public void appendSqlFromJoin(JdbcTable table, String alias, SqlExp exp, 308 boolean outer, CharBuf s) { 309 if (outer) { 310 s.append(" LEFT JOIN "); 311 } else { 312 s.append(" JOIN "); 313 } 314 s.append(table.name); 315 if (alias != null) { 316 s.append(" AS "); 317 s.append(alias); 318 } 319 if (exp != null) { 320 s.append(" ON ("); 321 exp.appendSQL(this, s, null); 322 s.append(')'); 323 } 324 } 325 326 330 public void dropTable(Connection con, String table, Statement stat) throws SQLException { 331 ResultSet rs = null; 332 try { 333 stat = con.createStatement(); 334 rs = stat.executeQuery( 335 "SELECT FKTABLE_NAME,FK_NAME\n" + 336 " FROM SYSTEM_CROSSREFERENCE\n" + 337 " WHERE PKTABLE_NAME = '" + table.toUpperCase().trim() + "'"); 338 ArrayList a = new ArrayList (); 339 for (; rs.next();) { 340 String tableName = rs.getString(1); 341 String conName = rs.getString(2); 342 a.add( 343 "ALTER TABLE " + tableName + " DROP CONSTRAINT " + conName); 344 345 } 346 rs.close(); 347 for (Iterator i = a.iterator(); i.hasNext();) { 348 String sql = (String )i.next(); 349 try { 350 stat.execute(sql); 351 } catch (SQLException e) { 352 353 } 354 } 355 stat.execute("DROP TABLE " + table); 356 } finally { 357 if (rs != null) { 358 try { 359 rs.close(); 360 } catch (SQLException x) { 361 } 363 } 364 } 365 } 366 367 boolean isDirectTypeColumnChangesSupported(JdbcColumn ourCol, 368 JdbcColumn dbCol) { 369 return false; 370 } 371 372 boolean isDirectNullColumnChangesSupported() { 373 return false; 374 } 375 376 boolean isDirectScaleColumnChangesSupported(JdbcColumn ourCol, 377 JdbcColumn dbCol) { 378 return false; 379 } 380 381 boolean isDirectLenghtColumnChangesSupported(JdbcColumn ourCol, 382 JdbcColumn dbCol) { 383 return false; 384 } 385 386 boolean isDropPrimaryKeySupported() { 387 return false; 388 } 389 390 boolean isDropConstraintsForDropTableSupported() { 391 return false; 392 } 393 394 397 protected void appendAddNewColumn(JdbcTable t, JdbcColumn c, 398 CharBuf s, boolean comments) { 399 if (comments && isCommentSupported() && c.comment != null) { 400 s.append(comment("add column for field " + c.comment)); 401 } 402 403 s.append("\n"); 404 if (isAddSequenceColumn(c)) { 405 addSequenceColumn(t, c, s, comments); 406 } else { 407 s.append("ALTER TABLE "); 408 s.append(t.name); 409 s.append(" ADD COLUMN "); 410 s.append(c.name); 411 s.append(' '); 412 appendColumnType(c, s); 413 if (!c.nulls) { 414 s.append(" DEFAULT "); 415 String _default = getDefaultForType(c); 416 if (_default.startsWith("'")) { 417 s.append(_default); 418 } else { 419 s.append("'"); 420 s.append(_default); 421 s.append("'"); 422 } 423 s.append(" NOT NULL"); 424 } 425 s.append(getRunCommand()); 426 } 427 } 428 429 432 protected void appendDropColumn(TableDiff tableDiff, JdbcColumn c, 433 CharBuf s, boolean comments) { 434 if (comments && isCommentSupported()) { 435 s.append(comment("dropping unknown column " + c.name)); 436 } 437 s.append("\n"); 438 if (isDropSequenceColumn(tableDiff, c)) { 439 dropSequenceColumn(tableDiff.getOurTable(), c, s, comments); 440 } else { 441 s.append("ALTER TABLE "); 442 s.append(tableDiff.getOurTable().name); 443 s.append(" DROP COLUMN "); 444 s.append(c.name); 445 } 446 } 447 448 451 protected void appendRefDropConstraint(CharBuf s, JdbcConstraint c, 452 boolean comments) { 453 s.append("ALTER TABLE "); 454 s.append(c.src.name); 455 s.append(" DROP CONSTRAINT "); 456 s.append(c.name); 457 } 458 459 462 protected void appendDropIndex(CharBuf s, JdbcTable t, JdbcIndex idx, 463 boolean comments) { 464 s.append("DROP INDEX "); 465 s.append(idx.name); 466 } 467 468 protected void fixColumnsNonDirect(TableDiff tableDiff, PrintWriter out) { 469 JdbcTable ourTable = tableDiff.getOurTable(); 470 String tempTableName = getTempTableName(ourTable, 31); 471 472 CharBuf s = new CharBuf(); 473 s.append("CREATE CACHED TABLE "); 474 s.append(tempTableName); s.append(" ("); 476 JdbcColumn[] cols = ourTable.getColsForCreateTable(); 477 int nc = cols.length; 478 for (int i = 0; i < nc; i++) { 479 s.append("\n "); 480 appendCreateColumn(ourTable, cols[i], s, false); 481 } 482 s.append("\n "); 483 appendPrimaryKeyConstraint(ourTable, s); 484 s.append(")"); 485 s.append(getRunCommand()); 486 487 s.append("INSERT INTO "); 488 s.append(tempTableName); s.append(" ("); 490 for (int i = 0; i < nc; i++) { 491 s.append(cols[i].name); 492 if ((i + 1) != nc) { 493 s.append(", "); 494 } 495 } 496 s.append(") "); 497 498 s.append("\n"); 500 s.append("SELECT "); 501 for (int i = 0; i < nc; i++) { 502 ColumnDiff diff = getColumnDiffForName(tableDiff, cols[i].name); 503 if (diff == null) { 504 if (i != 0) { 505 s.append(" "); 506 } 507 s.append(cols[i].name); 508 } else { 509 if (diff.isMissingCol()) { 510 if (diff.getOurCol().nulls) { 511 if (i != 0) { 512 s.append(" "); 513 } 514 s.append("CAST( NULL AS "); 515 appendColumnType(cols[i], s); 516 s.append(")"); 517 518 } else { 519 if (i != 0) { 520 s.append(" "); 521 } 522 s.append(getDefaultForType(diff.getOurCol())); 523 } 524 525 } else if ((diff.isLenghtDiff() || diff.isScaleDiff() || diff.isTypeDiff()) && diff.isNullDiff()) { 526 if (cols[i].nulls) { 527 if (i != 0) { 528 s.append(" "); 529 } 530 s.append("CAST("); 531 s.append(cols[i].name); 532 s.append(" AS "); 533 appendColumnType(cols[i], s); 534 s.append(")"); 535 } else { 536 if (i != 0) { 537 s.append(" "); 538 } 539 540 541 s.append("CAST( "); 542 s.append("IFNULL("); 543 s.append(cols[i].name); 544 s.append(","); 545 s.append(getDefaultForType(diff.getOurCol())); 546 s.append(") AS "); 547 appendColumnType(cols[i], s); 548 s.append(")"); 549 } 550 551 } else if ((diff.isLenghtDiff() || diff.isScaleDiff() || diff.isTypeDiff()) && !diff.isNullDiff()) { 552 if (i != 0) { 553 s.append(" "); 554 } 555 s.append("CAST("); 556 s.append(cols[i].name); 557 s.append(" AS "); 558 appendColumnType(cols[i], s); 559 s.append(")"); 560 } else if (diff.isNullDiff()) { 561 if (cols[i].nulls) { 562 if (i != 0) { 563 s.append(" "); 564 } 565 s.append(cols[i].name); 566 } else { 567 if (i != 0) { 568 s.append(" "); 569 } 570 s.append("IFNULL("); 571 s.append(cols[i].name); 572 s.append(","); 573 s.append(getDefaultForType(diff.getOurCol())); 574 s.append(")"); 575 } 576 } 577 } 578 579 if ((i + 1) != nc) { 580 s.append(", "); 581 s.append("\n"); } 583 } 584 s.append("\n"); s.append(" FROM "); 586 s.append(ourTable.name); 587 s.append(getRunCommand()); 588 589 s.append("DROP TABLE "); 590 s.append(ourTable.name); 591 s.append(getRunCommand()); 592 593 s.append("ALTER TABLE "); 594 s.append(tempTableName); 595 s.append(" RENAME TO "); 596 s.append(ourTable.name); 597 s.append(getRunCommand()); 598 599 out.println(s.toString()); 600 } 601 602 605 protected void dropSequenceColumn(JdbcTable t, JdbcColumn c, CharBuf s, 606 boolean comments) { 607 String tempTableName = getTempTableName(t, 31); 608 609 s.append(comment("create a temp table to store old table values.")); 610 s.append("\n"); 611 612 s.append("CREATE CACHED TABLE "); 613 s.append(tempTableName); 614 s.append(" (\n"); 615 JdbcColumn[] cols = t.getColsForCreateTable(); 616 int nc = cols.length; 617 boolean first = true; 618 for (int i = 0; i < nc; i++) { 619 if (first) { 620 first = false; 621 } else { 622 s.append("\n"); 623 } 624 s.append(" "); 625 appendCreateColumn(t, cols[i], s, comments); 626 } 627 s.append("\n "); 628 appendPrimaryKeyConstraint(t, s); 629 s.append("\n)"); 630 s.append(getRunCommand()); 631 632 s.append(comment("insert a distinct list into the temp table.")); 633 s.append("\n"); 634 s.append("INSERT INTO "); 635 s.append(tempTableName); 636 s.append("("); 637 for (int i = 0; i < nc; i++) { 638 s.append(cols[i].name); 639 if ((i + 1) != nc) { 640 s.append(", "); 641 } 642 } 643 s.append(")"); 644 s.append("\nSELECT DISTINCT "); 645 for (int i = 0; i < nc; i++) { 646 if (i != 0) { 647 s.append("\n "); 648 } 649 s.append(cols[i].name); 650 if ((i + 1) != nc) { 651 s.append(", "); 652 } 653 } 654 s.append("\n FROM "); 655 s.append(t.name); 656 657 s.append(getRunCommand()); 658 659 s.append(comment("drop main table.")); 660 s.append("\n"); 661 s.append("DROP TABLE "); 662 s.append(t.name); 663 s.append(getRunCommand()); 664 665 s.append(comment("rename temp table to main table.")); 666 s.append("\n"); 667 s.append("ALTER TABLE "); 668 s.append(tempTableName); 669 s.append(" RENAME TO "); 670 s.append(t.name); 671 672 } 673 674 677 protected void addSequenceColumn(JdbcTable t, JdbcColumn c, CharBuf s, 678 boolean comments) { 679 680 String mainTempTableName = getTempTableName(t, 31); 681 String minTempTableName = getTempTableName(t, 31); 682 String identityColumnName = getTempColumnName(t); 683 684 JdbcColumn indexColumn = null; 685 JdbcColumn sequenceColumn = null; 686 JdbcColumn[] cols = t.getColsForCreateTable(); 687 int nc = cols.length; 688 for (int i = 0; i < nc; i++) { 689 if (isAddSequenceColumn(cols[i])) { 690 sequenceColumn = cols[i]; 691 } else if (t.isInPrimaryKey(cols[i].name)) { 692 indexColumn = cols[i]; 693 } 694 } 695 696 s.append( 697 comment( 698 "Generate a sequence number so that we can implement a List.")); 699 s.append("\n"); 700 s.append(comment("create a temp table with a extra identity column.")); 701 s.append("\n"); 702 s.append("CREATE CACHED TABLE "); 703 s.append(mainTempTableName); 704 s.append(" (\n "); 705 s.append(identityColumnName); 707 s.append(" IDENTITY,"); 708 for (int i = 0; i < nc; i++) { 709 s.append("\n "); 710 appendCreateColumn(t, cols[i], s, comments); 711 } 712 int lastIndex = s.toString().lastIndexOf(','); 713 s.replace(lastIndex, lastIndex + 1, ' '); s.append("\n)"); 715 716 s.append(getRunCommand()); 717 718 s.append( 719 comment( 720 "insert a '0' in the sequence column and copy the rest of the old table into the temp table.")); 721 s.append("\n"); 722 s.append("INSERT INTO "); 723 s.append(mainTempTableName); 724 s.append("("); 725 for (int i = 0; i < nc; i++) { 726 s.append(cols[i].name); 727 if ((i + 1) != nc) { 728 s.append(", "); 729 } 730 } 731 s.append(")"); 732 s.append("\nSELECT "); 733 for (int i = 0; i < nc; i++) { 734 if (i != 0) { 735 s.append("\n "); 736 } 737 if (isAddSequenceColumn(cols[i])) { 738 s.append('0'); 739 } else { 740 s.append(cols[i].name); 741 } 742 if ((i + 1) != nc) { 743 s.append(", "); 744 } 745 } 746 s.append("\n FROM "); 747 s.append(t.name); 748 s.append("\n ORDER BY "); 749 s.append(indexColumn.name); 750 751 s.append(getRunCommand()); 752 753 s.append(comment("create a temp table to store the minimum id.")); 754 s.append("\n"); 755 s.append("CREATE CACHED TABLE "); 756 s.append(minTempTableName); 757 s.append(" (\n "); 758 s.append(indexColumn.name); 759 s.append(' '); 760 appendColumnType(indexColumn, s); 761 appendCreateColumnNulls(t, indexColumn, s); 762 s.append(",\n "); 763 s.append("min_id"); 764 s.append(" INTEGER\n)"); 765 766 s.append(getRunCommand()); 767 768 s.append(comment("store the minimum id.")); 769 s.append("\n"); 770 s.append("INSERT INTO "); 771 s.append(minTempTableName); 772 s.append(" ("); 773 s.append(indexColumn.name); 774 s.append(", "); 775 s.append("min_id"); 776 s.append(")\n"); 777 s.append("SELECT "); 778 s.append(indexColumn.name); 779 s.append(",\n "); 780 s.append("MIN("); 781 s.append(identityColumnName); 782 s.append(")\n"); 783 s.append(" FROM "); 784 s.append(mainTempTableName); 785 s.append("\n"); 786 s.append(" GROUP BY "); 787 s.append(indexColumn.name); 788 789 s.append(getRunCommand()); 790 791 s.append(comment("drop main table " + t.name + ".")); 792 s.append("\n"); 793 s.append("DROP TABLE "); 794 s.append(t.name); 795 796 s.append(getRunCommand()); 797 798 s.append(comment("recreate table " + t.name + ".")); 799 s.append("\n"); 800 s.append("CREATE TABLE "); 801 s.append(t.name); 802 s.append(" (\n"); 803 boolean first = true; 804 for (int i = 0; i < nc; i++) { 805 if (first) { 806 first = false; 807 } else { 808 s.append("\n"); 809 } 810 s.append(" "); 811 appendCreateColumn(t, cols[i], s, comments); 812 } 813 s.append("\n "); 814 appendPrimaryKeyConstraint(t, s); 815 s.append("\n)"); 816 appendTableType(t, s); 817 818 s.append(getRunCommand()); 819 820 s.append( 821 comment( 822 "populate table " + t.name + " with the new sequence column.")); 823 s.append("\n"); 824 s.append("INSERT INTO "); 825 s.append(t.name); 826 s.append("("); 827 for (int i = 0; i < nc; i++) { 828 s.append(cols[i].name); 829 if ((i + 1) != nc) { 830 s.append(", "); 831 } 832 } 833 s.append(")"); 834 s.append("\nSELECT "); 835 for (int i = 0; i < nc; i++) { 836 if (i != 0) { 837 s.append("\n "); 838 } 839 840 if (isAddSequenceColumn(cols[i])) { 841 s.append("(a."); 842 s.append(identityColumnName); 843 s.append(" - b.min_id)"); 844 } else { 845 s.append("a."); 846 s.append(cols[i].name); 847 } 848 849 if ((i + 1) != nc) { 850 s.append(", "); 851 } 852 } 853 s.append("\n FROM "); 854 s.append(mainTempTableName); 855 s.append(" a,\n "); 856 s.append(minTempTableName); 857 s.append(" b\n WHERE a."); 858 s.append(indexColumn.name); 859 s.append(" = b."); 860 s.append(indexColumn.name); 861 862 s.append(getRunCommand()); 863 864 s.append(comment("drop temp tables.")); 865 s.append("\n"); 866 s.append("DROP TABLE "); 867 s.append(mainTempTableName); 868 s.append(getRunCommand()); 869 870 s.append("DROP TABLE "); 871 s.append(minTempTableName); 872 873 s.append(getRunCommand()); 874 } 875 876 } 877 | Popular Tags |