1 5 6 package com.hp.hpl.jena.db.impl; 7 8 import java.sql.Connection ; 9 import java.sql.DatabaseMetaData ; 10 import java.sql.PreparedStatement ; 11 import java.sql.ResultSet ; 12 import java.sql.SQLException ; 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 import java.util.zip.CRC32 ; 17 import java.lang.Thread ; 18 19 import com.hp.hpl.jena.datatypes.RDFDatatype; 20 import com.hp.hpl.jena.datatypes.TypeMapper; 21 import com.hp.hpl.jena.db.GraphRDB; 22 import com.hp.hpl.jena.db.IDBConnection; 23 import com.hp.hpl.jena.db.RDFRDBException; 24 import com.hp.hpl.jena.graph.Graph; 25 import com.hp.hpl.jena.graph.Node; 26 import com.hp.hpl.jena.graph.Node_Literal; 27 import com.hp.hpl.jena.graph.Node_URI; 28 import com.hp.hpl.jena.graph.Node_Variable; 29 import com.hp.hpl.jena.graph.impl.LiteralLabel; 30 import com.hp.hpl.jena.graph.query.ExpressionFunctionURIs; 31 32 import com.hp.hpl.jena.rdf.model.AnonId; 33 import com.hp.hpl.jena.shared.*; 34 35 import com.hp.hpl.jena.vocabulary.RDF; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 import org.apache.xerces.util.XMLChar; 40 41 57 58 public abstract class DriverRDB implements IRDBDriver { 59 60 66 protected DBPropDatabase m_dbProps; 67 68 71 protected String m_psetClassName; 72 73 76 protected String m_psetReifierClassName; 77 78 81 protected String m_lsetClassName; 82 83 86 protected String m_lsetReifierClassName; 87 88 89 protected String DRIVER_NAME; 90 92 93 protected String DATABASE_TYPE; 94 95 96 protected int INDEX_KEY_LENGTH; 97 98 99 protected int INDEX_KEY_LENGTH_MAX; 100 101 106 protected boolean IS_XACT_DB; 107 108 109 protected boolean STRINGS_TRIMMED; 110 113 114 protected String EOS = ""; 115 protected char EOS_CHAR = ':'; 116 protected int EOS_LEN = 0; 117 121 122 protected char QUOTE_CHAR = '\"'; 123 125 126 129 protected boolean DB_NAMES_TO_UPPER = false; 130 131 132 136 protected boolean URI_COMPRESS; 137 138 139 protected int URI_COMPRESS_LENGTH = 100; 140 143 protected int LONG_OBJECT_LENGTH; 144 145 146 protected int LONG_OBJECT_LENGTH_MAX; 147 148 149 protected String ID_SQL_TYPE; 150 151 152 protected boolean SKIP_DUPLICATE_CHECK; 153 154 155 protected boolean PRE_ALLOCATE_ID; 156 157 158 protected String SQL_FILE; 159 160 161 protected String DEFAULT_SQL_FILE = "etc/generic_generic.sql"; 162 163 164 170 protected String TABLE_NAME_PREFIX = "jena_"; 171 172 175 protected int TABLE_NAME_LENGTH_MAX; 176 177 178 protected String STMT_TABLE_NAME_SUFFIX = "_stmt"; 179 protected String REIF_TABLE_NAME_SUFFIX = "_reif"; 180 181 182 protected int MAXIMUM_INDEX_COLUMNS = 3; 183 184 185 protected int SYSTEM_TABLE_CNT = 0; 186 187 188 public String [] SYSTEM_TABLE_NAME; 189 190 191 protected boolean CACHE_PREPARED_STATEMENTS = true; 192 193 194 protected String LAYOUT_TYPE = "TripleStore"; 195 196 197 protected String SYSTEM_STMT_TABLE; 198 199 200 protected String LONG_LIT_TABLE; 201 202 203 protected String LONG_URI_TABLE; 204 205 206 protected String PREFIX_TABLE; 207 208 209 protected String GRAPH_TABLE; 210 211 212 protected String MUTEX_TABLE; 213 214 215 protected String STORE_WITH_MODEL = null; 216 217 219 protected final String DEFAULT_PROPS = "JENA_DEFAULT_GRAPH_PROPERTIES"; 220 221 222 protected final int DEFAULT_ID = 0; 223 224 225 226 protected final String VERSION = "2.0alpha"; 227 228 229 protected String LAYOUT_VERSION = "2.0"; 230 231 protected static Log logger = LogFactory.getLog( PSet_ReifStore_RDB.class ); 232 233 237 240 protected SQLCache m_sql = null; 241 242 243 protected SpecializedGraph m_sysProperties = null; 244 245 protected IDBConnection m_dbcon = null; 246 247 protected LRUCache prefixCache = null; 248 249 public static final int PREFIX_CACHE_SIZE = 50; 250 251 255 256 private Boolean m_transactionsSupported; 258 259 260 private boolean inTransaction = false; 261 262 263 264 268 269 273 public DriverRDB() { 274 } 275 276 280 283 public IDBConnection getConnection() { 284 return m_dbcon; 285 } 286 287 294 public SpecializedGraph getSystemSpecializedGraph(boolean doInit) { 295 296 SpecializedGraph res = null; 297 298 if (m_sysProperties != null) { 299 return m_sysProperties; 300 } 301 302 if (!isDBFormatOK()) { 303 lockDB(); 306 if (!isDBFormatOK()) { 307 if (doInit) { 308 try { 309 doCleanDB(false); 313 prefixCache = new LRUCache(PREFIX_CACHE_SIZE); 314 res = formatAndConstructSystemSpecializedGraph(); 315 } catch (Exception e) { 316 unlockDB(); 317 throw new JenaException( 321 "The database appears to be unformatted or corrupted and\n" 322 + "an attempt to automatically format the database has failed\n", e); 323 } 324 } 325 unlockDB(); 326 return res; 327 } 328 unlockDB(); 330 } 331 332 prefixCache = new LRUCache(PREFIX_CACHE_SIZE); 333 getDbInitTablesParams(); IPSet pSet = createIPSetInstanceFromName(m_psetClassName, 336 SYSTEM_STMT_TABLE); 337 m_sysProperties = createLSetInstanceFromName(m_lsetClassName, pSet, 338 DEFAULT_ID); 339 m_dbProps = new DBPropDatabase(m_sysProperties); 340 341 checkEngine(m_dbProps); 343 checkDriverVersion(m_dbProps); 344 checkLayoutVersion(m_dbProps); 345 String val = m_dbProps.getLongObjectLength(); 346 if (val == null) 347 throwBadFormat("long object length"); 348 else 349 LONG_OBJECT_LENGTH = Integer.parseInt(val); 350 val = m_dbProps.getIndexKeyLength(); 351 if (val == null) 352 throwBadFormat("index key length"); 353 else 354 INDEX_KEY_LENGTH = Integer.parseInt(val); 355 val = m_dbProps.getIsTransactionDb(); 356 if (val == null) 357 throwBadFormat("database supports transactions"); 358 else 359 IS_XACT_DB = Boolean.valueOf(val).booleanValue(); 360 val = m_dbProps.getDoCompressURI(); 361 if (val == null) 362 throwBadFormat("compress URIs"); 363 else 364 URI_COMPRESS = Boolean.valueOf(val).booleanValue(); 365 val = m_dbProps.getCompressURILength(); 366 if (val == null) 367 throwBadFormat("URI compress length"); 368 else 369 URI_COMPRESS_LENGTH = Integer.parseInt(val); 370 val = m_dbProps.getTableNamePrefix(); 371 if (val == null) 372 throwBadFormat("table name prefix"); 373 else 374 TABLE_NAME_PREFIX = val; 375 376 return m_sysProperties; 377 } 378 379 private void checkEngine ( DBProp dbProps ) { 380 String dbtype = m_dbProps.getEngineType(); 381 if ( dbtype == null ) throwBadFormat("database type"); 382 if ( !dbtype.equals(DATABASE_TYPE) ) { 383 throw new JenaException( 384 "Database created with incompatible database type for this version of Jena: " 385 + dbtype); 386 } 387 } 388 389 private void checkDriverVersion ( DBProp dbProps ) { 390 String vers = m_dbProps.getDriverVersion(); 391 if ( vers == null ) throwBadFormat("database version"); 392 if ( !vers.equals(VERSION) ) { 393 throw new JenaException( 394 "Models in the database were created with an incompatible version of Jena: " 395 + vers); 396 } 397 } 398 399 private void checkLayoutVersion ( DBProp dbProps ) { 400 String layout = m_dbProps.getLayoutVersion(); 401 if ( layout == null ) throwBadFormat("database layout"); 402 if ( !layout.equals(LAYOUT_VERSION) ) { 403 throw new JenaException( 404 "The database layout cannot be processed by this version of Jena: " 405 + layout); 406 } 407 408 } 409 410 private void throwBadFormat ( String prop ) { 411 throw new JenaException( 412 "The database appears to be unformatted or corrupted - could not find value\n" + 413 " for \"" + prop + "\" in Jena system properties table.\n" + 414 "If possible, call IDBConnection.cleanDB(). \n" + 415 "Warning: cleanDB will remove all Jena models from the databases."); 416 } 417 418 419 422 protected SpecializedGraph formatAndConstructSystemSpecializedGraph() { 423 String errMsg = null; 424 if (xactOp(xactIsActive)) 425 throw new RDFRDBException( 426 "Cannot intialize database while transaction is active.\n" 427 + "Commit or abort transaction before intializing database."); 428 429 boolean autoIsOn = xactOp(xactAutoOff); 430 try { 431 String [] params = getDbInitTablesParams(); 432 m_sql.runSQLGroup("initDBtables", params); 433 m_sql.runSQLGroup("initDBgenerators"); } catch (SQLException e) { 435 logger.warn("Problem formatting database", e); 436 errMsg = e.toString(); 437 } 438 439 if (errMsg == null) 440 try { 441 xactOp(xactCommit); 442 xactOp(xactBegin); 443 444 IPSet pSet = createIPSetInstanceFromName(m_psetClassName, 446 SYSTEM_STMT_TABLE); 447 m_sysProperties = createLSetInstanceFromName(m_lsetClassName, 448 pSet, DEFAULT_ID); 449 450 m_dbProps = new DBPropDatabase(m_sysProperties, m_dbcon 454 .getDatabaseType(), VERSION, LAYOUT_VERSION, String 455 .valueOf(LONG_OBJECT_LENGTH), String 456 .valueOf(INDEX_KEY_LENGTH), String.valueOf(IS_XACT_DB), 457 String.valueOf(URI_COMPRESS), String 458 .valueOf(URI_COMPRESS_LENGTH), 459 TABLE_NAME_PREFIX); 460 461 DBPropGraph def_prop = new DBPropGraph(m_sysProperties, 464 DEFAULT_PROPS, "generic"); 465 466 def_prop.addGraphId(DEFAULT_ID); 467 468 xactOp(xactCommit); 469 if (autoIsOn) 470 xactOp(xactAutoOn); 471 } catch (Exception e) { 472 errMsg = e.toString(); 473 } 474 475 if (errMsg != null) { 476 doCleanDB(false); 477 m_sysProperties = null; 478 throw new RDFRDBException(errMsg); 479 } 480 481 return m_sysProperties; 482 } 483 484 abstract String [] getDbInitTablesParams(); 485 486 abstract String [] getCreateTableParams( int graphId, boolean isReif ); 487 488 abstract public int graphIdAlloc ( String graphName ); 489 490 491 492 495 public List createSpecializedGraphs(String graphName, 496 Graph requestedProperties) { 497 498 518 519 String stmtTbl = null; 521 String reifTbl = null; 522 String dbSchema = STORE_WITH_MODEL; 523 boolean didGraphIdAlloc = false; 524 boolean didTableCreate = false; 525 String errMsg = null; 526 DBPropGraph graphProperties = null; 527 528 SpecializedGraph sysGraph = getSystemSpecializedGraph(false); 529 531 if (xactOp(xactIsActive)) 532 throw new RDFRDBException( 533 "Cannot create graph while transaction is active.\n" 534 + "Commit or abort transaction before creating graph"); 535 536 boolean autoOn = xactOp(xactAutoOff); 537 int graphId = -1; 539 try { 540 xactOp(xactBegin); 541 graphId = graphIdAlloc(graphName); 542 didGraphIdAlloc = true; 543 xactOp(xactCommit); 544 xactOp(xactBegin); 545 boolean useDefault = false; 546 547 if (((dbSchema == null) && graphName.equals(GraphRDB.DEFAULT))) { 553 useDefault = true; 554 dbSchema = DEFAULT_PROPS; } 557 if (dbSchema != null) { 564 DBPropGraph schProp = DBPropGraph.findPropGraphByName(sysGraph, 565 dbSchema); 566 if (schProp != null) { 567 reifTbl = schProp.getReifTable(); 568 stmtTbl = schProp.getStmtTable(); 569 } 570 if (((reifTbl == null) || (stmtTbl == null)) 571 && (useDefault == false)) 572 throw new RDFRDBException("Creating graph " + graphName 575 + ": referenced schema not found: " + dbSchema); 576 } 577 if ((reifTbl == null) || (stmtTbl == null)) { 578 didTableCreate = true; 579 reifTbl = createTable(graphId, true); 580 stmtTbl = createTable(graphId, false); 581 if ((reifTbl == null) || (stmtTbl == null)) 582 throw new RDFRDBException("Creating graph " + graphName 583 + ": cannot create tables"); 584 } 585 xactOp(xactCommit); } catch (Exception e) { 587 errMsg = e.toString(); 588 } 589 590 593 if (errMsg == null) 594 try { 595 xactOp(xactBegin); 596 597 graphProperties = new DBPropGraph(sysGraph, graphName, 598 requestedProperties); 599 graphProperties.addGraphId(graphId); 600 graphProperties.addStmtTable(stmtTbl); 601 graphProperties.addReifTable(reifTbl); 602 603 DBPropDatabase dbprop = new DBPropDatabase( 604 getSystemSpecializedGraph(true)); 605 dbprop.addGraph(graphProperties); 606 607 DBPropPSet pSetReifier = new DBPropPSet(m_sysProperties, 609 m_psetReifierClassName, reifTbl); 610 DBPropLSet lSetReifier = new DBPropLSet(m_sysProperties, 611 "LSET_" + graphProperties.getName() + "_REIFIER", 612 m_lsetReifierClassName); 613 lSetReifier.setPSet(pSetReifier); 614 graphProperties.addLSet(lSetReifier); 615 616 DBPropPSet pSet = new DBPropPSet(m_sysProperties, 618 m_psetClassName, stmtTbl); 619 DBPropLSet lSet = new DBPropLSet(m_sysProperties, "LSET_" 620 + graphProperties.getName(), m_lsetClassName); 621 lSet.setPSet(pSet); 622 graphProperties.addLSet(lSet); 623 624 xactOp(xactCommit); 625 if (autoOn) xactOp(xactAutoOn); 626 } catch (Exception e) { 627 errMsg = e.toString(); 628 } 629 630 if (errMsg == null) 631 return recreateSpecializedGraphs(graphProperties); 632 else { 633 xactOp(xactCommit); xactOp(xactBegin); 635 try { 636 if (didGraphIdAlloc) { 638 graphIdDealloc(graphId); 639 } 640 } catch ( Exception e ) { 641 } 642 if (didTableCreate) { 643 if (reifTbl != null) 646 try { deleteTable(reifTbl); } 647 catch ( Exception e ) {}; 648 if (stmtTbl != null) 649 try { deleteTable(stmtTbl); } 650 catch ( Exception e ) {}; 651 } 652 xactOp(xactCommit); 653 if (autoOn) xactOp(xactAutoOn); 654 return null; 655 } 656 } 657 658 665 public List recreateSpecializedGraphs(DBPropGraph graphProperties) { 666 667 List result = new ArrayList (); 668 int dbGraphId = graphProperties.getGraphId(); 669 670 String [] lsetTypes = {m_lsetClassName, m_lsetReifierClassName}; 672 int i; 673 for(i=0;i<2;i++) { 674 Iterator it = graphProperties.getAllLSets(); 675 while(it.hasNext() ) { 676 DBPropLSet lSetProps = (DBPropLSet)it.next(); 677 if ( lSetProps.getType().equals(lsetTypes[i]) ) continue; 678 DBPropPSet pSetProps = lSetProps.getPset(); 679 680 IPSet pSet = createIPSetInstanceFromName(pSetProps.getType(), pSetProps.getTable()); 681 result.add( createLSetInstanceFromName( lSetProps.getType(), pSet, dbGraphId)); 682 } 683 } 684 685 return result; 686 } 687 688 694 private IPSet createIPSetInstanceFromName(String className, String tblName) { 695 IPSet pSet = null; 696 try { 697 pSet = (IPSet) Class.forName(className).newInstance(); 699 pSet.setDriver(this); 700 pSet.setSQLType(ID_SQL_TYPE); 701 pSet.setSkipDuplicateCheck(SKIP_DUPLICATE_CHECK); 702 pSet.setSQLCache(m_sql); 703 pSet.setCachePreparedStatements(CACHE_PREPARED_STATEMENTS); 704 pSet.setTblName(tblName); 705 } catch (Exception e) { 706 logger.warn("Unable to create IPSet instance ", e); 707 } 708 return pSet; 709 } 710 711 private SpecializedGraph createLSetInstanceFromName(String lSetName, IPSet pset, int dbGraphID) { 712 SpecializedGraph sg = null; 713 try { 714 Class cls = Class.forName(lSetName); 715 Class [] params = {IPSet.class, Integer .class}; 716 java.lang.reflect.Constructor con = cls.getConstructor(params); 717 Object [] args = {pset, new Integer (dbGraphID)}; 718 sg = (SpecializedGraph) con.newInstance(args); 719 } catch (Exception e) { 720 logger.error("Unable to create instance of SpecializedGraph ", e); 721 } 722 return sg; 723 } 724 725 730 public void removeSpecializedGraphs( DBPropGraph graphProperties, 731 List specializedGraphs) { 732 733 int graphId = graphProperties.getGraphId(); 734 735 if (xactOp(xactIsActive)) 736 throw new RDFRDBException( 737 "Cannot remove graph while transaction is active.\n" 738 + "Commit or abort transaction before removing graph"); 739 740 boolean autoIsOn = xactOp(xactAutoOff); 741 xactOp(xactCommit); 742 xactOp(xactBegin); 743 744 String stmtTbl = graphProperties.getStmtTable(); 746 String reifTbl = graphProperties.getReifTable(); 747 748 m_dbProps.removeGraph(graphProperties); 752 753 if ( graphId != DEFAULT_ID ) graphIdDealloc(graphId); 754 755 xactOp(xactCommit); 756 xactOp(xactBegin); 757 758 763 764 boolean stInUse = true; 766 boolean rtInUse = true; 767 768 if ( graphId != DEFAULT_ID ) { 769 stInUse = false; 770 rtInUse = false; 771 Iterator it = m_dbProps.getAllGraphs(); 772 while ( it.hasNext() ) { 773 DBPropGraph gp = (DBPropGraph) it.next(); 774 if ( gp.getStmtTable().equals(stmtTbl) ) stInUse = true; 775 if ( gp.getReifTable().equals(reifTbl) ) rtInUse = true; 776 } 777 } 778 if ( stInUse || rtInUse ) { 780 Iterator it = specializedGraphs.iterator(); 781 while (it.hasNext()){ 782 SpecializedGraph sg = (SpecializedGraph) it.next(); 783 removeSpecializedGraph(sg); 784 } 785 } else { 786 deleteTable(stmtTbl); 787 deleteTable(reifTbl); 788 } 789 xactOp(xactCommit); 790 if ( autoIsOn ) xactOp(xactAutoOn); 791 } 792 793 794 798 private void removeSpecializedGraph(SpecializedGraph graph) { 799 graph.clear(); 800 } 801 802 809 public void setDatabaseProperties(Graph databaseProperties) { 810 SpecializedGraph toGraph = getSystemSpecializedGraph(true); 811 813 816 toGraph.clear(); 817 SpecializedGraph.CompletionFlag complete = new SpecializedGraph.CompletionFlag(); 818 toGraph.add(databaseProperties, complete); 819 820 824 } 826 827 828 835 public DBPropGraph getDefaultModelProperties() { 836 SpecializedGraph sg = getSystemSpecializedGraph(true); 837 DBPropGraph result = DBPropGraph.findPropGraphByName(sg, DEFAULT_PROPS); 838 if (result == null) { 839 logger.error("No default Model Properties found"); 840 } 845 return result; 846 } 847 848 853 public boolean isDBFormatOK() throws RDFRDBException { 854 boolean result = true; 855 boolean[] found = new boolean[SYSTEM_TABLE_CNT]; 856 int i = 0; 857 for (i = 0; i < SYSTEM_TABLE_CNT; i++) found[i] = false; 858 try { 859 ResultSet alltables = getAllTables(); 861 while (alltables.next()) { 862 String tblName = alltables.getString("TABLE_NAME"); 863 for (i = 0; i < SYSTEM_TABLE_CNT; i++) 864 if (SYSTEM_TABLE_NAME[i].equals(tblName)) 865 found[i] = true; 866 } 867 alltables.close(); 868 for (i = 0; i < SYSTEM_TABLE_CNT; i++) { 869 if (!found[i]) { 870 if (SYSTEM_TABLE_NAME[i].equals(MUTEX_TABLE)) 872 continue; 873 result = false; 874 } 875 } 876 } catch (Exception e1) { 877 throw new RDFRDBException( 880 "Exception while checking db format - " + e1); 881 } 882 return result; 883 } 884 885 888 public String stringToDBname(String aName) { 889 String result = (DB_NAMES_TO_UPPER) ? aName.toUpperCase() : aName; 890 return(result); 891 } 892 893 private static final int lockTryMax = 5; 895 896 899 900 public boolean tryLockDB() { 901 boolean res = true; 902 try { 903 m_sql.runSQLGroup("lockDatabase", MUTEX_TABLE); 904 } catch (SQLException e) { 905 res = false; 906 } 907 return res; 908 } 909 910 911 public void lockDB() throws RDFRDBException { 912 String err = ""; 913 int cnt = 0; 914 while ( cnt++ < lockTryMax ) { 915 if ( tryLockDB() ) 916 break; 917 try { 918 Thread.sleep((long)5000); 919 } catch (InterruptedException e) { 920 err = err + " lockDB sleep interrupted" + e; 921 } 922 } 923 if ( cnt >= lockTryMax ) { 924 err = "Failed to lock database after "+ lockTryMax + " attempts.\n" 925 + err + "\n." 926 + "Try later or else call DriverRDB.unlockDB() after ensuring\n" + 927 "that no other Jena applications are using the database."; 928 throw new RDFRDBException(err); 929 } 930 } 931 932 935 936 public void unlockDB() throws RDFRDBException { 937 String err; 938 int cnt = 0; 939 while ( cnt++ < lockTryMax ) { 940 try { 941 m_sql.runSQLGroup("unlockDatabase", MUTEX_TABLE); 942 break; 943 } catch (SQLException e) { 944 err = "Failed to unlock database after "+ lockTryMax + " attempts - " + e; 945 try { 946 Thread.sleep((long)5000); 947 } catch (InterruptedException e1) { 948 err = err + " sleep failed" + e; 949 } 950 } 951 if ( cnt >= lockTryMax ) 952 throw new RDFRDBException(err); 953 } 954 } 955 956 957 958 959 public boolean DBisLocked() throws RDFRDBException { 960 try { 961 DatabaseMetaData dbmd = m_dbcon.getConnection().getMetaData(); 962 String [] tableTypes = { "TABLE" }; 963 String prefixMatch = stringToDBname(TABLE_NAME_PREFIX + "%"); 964 ResultSet iter = dbmd.getTables(null, null, MUTEX_TABLE, tableTypes); 965 try { return iter.next(); } finally { iter.close(); } 966 } catch (SQLException e1) { 967 throw new RDFRDBException("Internal SQL error in driver" + e1); 968 } 969 } 970 971 974 public void cleanDB() { 975 976 try { 978 lockDB(); 979 } catch (RDFRDBException e) { 980 throw new RDFRDBException( 981 "DriverRDB.cleanDB() failed to acquire database lock:\n" 982 + "(" 983 + e 984 + ")\n." 985 + "Try again or call DriverRDB.unlockDB() if necessary."); 986 } 987 doCleanDB(true); 989 } 990 991 997 998 protected void doCleanDB( boolean dropMutex ) throws RDFRDBException { 999 try { 1000 if ( !DBisLocked() ) { 1001 throw new RDFRDBException( 1002 "Internal error in driver - database not locked for cleaning.\n"); 1003 } 1004 } catch ( RDFRDBException e ) { 1005 throw new RDFRDBException( 1006 "Exception when checking for database lock - \n" 1007 + e); 1008 } 1009 try { 1010 ResultSet alltables = getAllTables(); 1011 List tablesPresent = new ArrayList (10); 1012 while (alltables.next()) { 1013 tablesPresent.add(alltables.getString("TABLE_NAME")); 1014 } 1015 alltables.close(); 1016 Iterator it = tablesPresent.iterator(); 1017 while (it.hasNext()) { 1018 String tblName = (String ) it.next(); 1019 if ( tblName.equals(MUTEX_TABLE) && (dropMutex == false) ) 1020 continue; 1021 m_sql.runSQLGroup("dropTable", tblName); 1022 } 1023 if (PRE_ALLOCATE_ID) { 1024 clearSequences(); 1025 } 1026 } catch (SQLException e1) { 1027 throw new RDFRDBException("Internal error in driver while cleaning database\n" 1028 + "(" + e1 + ").\n" 1029 + "Database may be corrupted. Try cleanDB() again."); 1030 } 1031 m_sysProperties = null; 1032 if ( prefixCache != null ) prefixCache.clear(); 1033 prefixCache = null; 1034 } 1035 1036 private ResultSet getAllTables() { 1037 try { 1038 DatabaseMetaData dbmd = m_dbcon.getConnection().getMetaData(); 1039 String [] tableTypes = { "TABLE" }; 1040 String prefixMatch = stringToDBname(TABLE_NAME_PREFIX + "%"); 1041 return dbmd.getTables(null, null, prefixMatch, tableTypes); 1042 } catch (SQLException e1) { 1043 throw new RDFRDBException("Internal SQL error in driver - " + e1); 1044 } 1045 } 1046 1047 1051 public void clearSequences() { 1052 } 1053 1054 1058 public void removeSequence(String seqName) { 1059 if (sequenceExists(seqName)) { 1060 try { 1061 m_sql.runSQLGroup("DropSequence",seqName); 1062 } catch (Exception e) { 1063 logger.warn("Unable to drop sequence " + seqName, e); 1064 } 1065 } 1066 } 1067 1068 1072 public boolean sequenceExists(String seqName) { 1073 Object [] args = {seqName}; 1074 boolean result = false; 1075 try { 1076 String op = "SelectSequenceName"; 1077 PreparedStatement ps = m_sql.getPreparedSQLStatement(op); 1078 ps.setString(1,seqName); 1079 ResultSet rs = ps.executeQuery(); 1080 result = rs.next(); 1081 rs.close(); 1082 m_sql.returnPreparedSQLStatement(ps); 1083 } catch (Exception e) { 1084 logger.error("Unable to select sequence " + seqName, e); 1085 } 1086 return result; 1087 } 1088 1089 1093 public List getSequences() { 1094 List results = new ArrayList (10); 1095 Object [] args = {}; 1096 try { 1097 String opname = "SelectJenaSequences"; 1098 PreparedStatement ps = m_sql.getPreparedSQLStatement(opname, TABLE_NAME_PREFIX); 1099 ResultSet rs = ps.executeQuery(); 1100 while (rs.next()) results.add( rs.getString(1) ); 1101 rs.close(); 1102 m_sql.returnPreparedSQLStatement(ps); 1103 } catch (Exception e) { 1104 logger.error("Unable to select Jena sequences: ", e); 1105 } 1106 return results; 1107 } 1108 1109 1116 public void formatDB() throws RDFRDBException { 1117 } 1118 1119 1127 public String createTable( int graphId, boolean isReif) { 1128 String opname = isReif ? "createReifStatementTable" : "createStatementTable"; 1129 int i = 0; 1130 String params[]; 1131 while ( true ) { 1132 params = getCreateTableParams(graphId, isReif); 1133 try { 1134 m_sql.runSQLGroup(opname, params); 1135 break; 1136 } catch (SQLException e) { 1137 i++; 1138 if ( i > 5 ) { 1139 logger.warn("Problem creating table", e); 1140 throw new RDFRDBException("Failed to create table: " + params[0], e); 1141 } 1142 } 1143 } 1144 return params[0]; 1145 } 1146 1147 1148 1153 public void deleteTable( String tableName ) { 1154 1155 String opname = "dropTable"; 1156 try { 1157 PreparedStatement ps = m_sql.getPreparedSQLStatement(opname, tableName); 1158 ps.executeUpdate(); 1159 return; 1160 } catch (Exception e1) { 1161 throw new RDFRDBException("Failed to delete table ", e1); 1162 } 1163 } 1164 1165 1166 1167 1172 private void notSupported(String opName) 1173 { throw new UnsupportedOperationException (opName); } 1174 1175 1176 protected static final int xactBegin = 0; 1177 protected static final int xactCommit = 1; 1178 protected static final int xactAbort = 2; 1179 protected static final int xactIsActive = 3; 1180 protected static final int xactAutoOff = 4; 1181 protected static final int xactAutoOn = 5; 1182 1183 1184 1190 protected synchronized boolean xactOp(int op) throws RDFRDBException { 1191 boolean ret = true; 1192 try { 1193 if (op == xactBegin) { 1194 if (!inTransaction) { 1197 xactBegin(); 1198 inTransaction = true; 1199 } 1200 } else if (op == xactCommit) { 1201 if (inTransaction) { 1204 xactCommit(); 1205 inTransaction = false; 1206 } 1207 } else if (op == xactAbort) { 1208 if (inTransaction) { 1211 xactAbort(); 1212 inTransaction = false; 1213 } 1214 } else if (op == xactIsActive) { 1215 ret = inTransaction; 1217 } else if (op == xactAutoOff) { 1218 Connection c = m_sql.getConnection(); 1222 ret = c.getAutoCommit(); 1223 if ( ret ) 1224 xactBegin(); 1225 inTransaction = true; 1226 } else if (op == xactAutoOn) { 1227 if ( inTransaction ) 1230 throw new JenaException("Can't enable AutoCommit in middle of existing transaction"); 1231 Connection c = m_sql.getConnection(); 1232 c.setAutoCommit(true); 1233 ret = true; 1234 } else 1235 throw new JenaException("Unknown transaction operation: " + op); 1236 } catch (SQLException e) { 1237 throw new JenaException("Transaction support failed: ", e); 1238 } 1239 return ret; 1240 } 1241 1242 private void xactBegin() throws RDFRDBException { 1243 try { 1244 Connection c = m_sql.getConnection(); 1245 c.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); 1246 c.setAutoCommit(false); 1247 } catch (SQLException e) { 1254 throw new JenaException("Transaction begin failed: ", e); 1255 } 1256 } 1257 1258 private void xactAbort() throws RDFRDBException { 1259 try { 1260 Connection c = m_sql.getConnection(); 1261 c.rollback(); 1262 c.commit(); 1263 c.setAutoCommit(true); 1264 } catch (SQLException e) { 1265 throw new JenaException("Transaction rollback failed: ", e); 1266 } 1267 } 1268 1269 private void xactCommit() throws RDFRDBException { 1270 try { 1271 Connection c = m_sql.getConnection(); 1272 c.commit(); 1273 c.setAutoCommit(true); 1274 } catch (SQLException e) { 1278 throw new JenaException("Transaction commit failed: ", e); 1279 } 1280 } 1281 1282 1283 1288 public synchronized void begin() throws RDFRDBException { 1289 if (transactionsSupported()) { 1290 xactOp(xactBegin); 1291 } else { 1292 notSupported("begin transaction"); 1293 } 1294 } 1295 1296 1300 public void commit() throws RDFRDBException { 1301 if (transactionsSupported()) { 1302 xactOp(xactCommit); 1303 } else { 1304 notSupported("commit transaction"); 1305 } 1306 } 1307 1308 1312 public synchronized void abort() throws RDFRDBException { 1313 if (transactionsSupported()) { 1314 xactOp(xactAbort); 1315 } else { 1316 notSupported("abort transaction"); 1317 } 1318 } 1319 1320 1321 1322 1326 public String getDatabaseType() { 1327 return(DATABASE_TYPE); 1328 } 1329 1330 1333 public boolean transactionsSupported() { 1334 if (m_transactionsSupported != null) { 1335 return(m_transactionsSupported.booleanValue()); 1336 } 1337 1338 if (m_dbcon != null) { 1339 try { 1340 Connection c = m_sql.getConnection(); 1341 if ( c != null) { 1342 m_transactionsSupported = new Boolean (c.getMetaData().supportsMultipleTransactions()); 1343 return(m_transactionsSupported.booleanValue()); 1344 } 1345 } catch (SQLException e) { 1346 logger.error("SQL Exception caught ", e); 1347 } 1348 } 1349 return (false); 1350 1351 } 1352 1353 1354 1355 1357 1368 1369 public void close() throws RDFRDBException { 1370 } 1371 1372 1373 1378 1379 public boolean supportsMultipleModels() { 1380 return true; 1381 } 1382 1383 1391 1392 public boolean supportsJenaReification() { 1393 return false; 1394 } 1395 1396 1397 1483 1484 1485 1486 protected static String RDBCodeURI = "U"; 1487 protected static String RDBCodeBlank = "B"; 1488 protected static String RDBCodeLiteral = "L"; 1489 protected static String RDBCodeVariable = "V"; 1490 protected static String RDBCodeANY = "A"; 1491 protected static String RDBCodePrefix = "P"; 1492 protected static String RDBCodeValue = "v"; 1493 protected static String RDBCodeRef = "r"; 1494 protected static String RDBCodeDelim = ":"; 1495 protected static char RDBCodeDelimChar = ':'; 1496 protected static String RDBCodeInvalid = "X"; 1497 1498 1499 1500 1501 1507 public String nodeToRDBString ( Node node, boolean addIfLong ) throws RDFRDBException { 1508 String res = null; 1509 if ( node.isURI() ) { 1510 String uri = new String (((Node_URI) node).getURI()); 1511 if ( uri.startsWith(RDBCodeURI) ) { 1512 throw new RDFRDBException ("URI Node looks like a blank node: " + uri ); 1513 } 1514 int pos = 0; 1520 boolean noCompress; 1521 String pfx; 1522 String qname; 1523 if ( URI_COMPRESS == true ) { 1524 pos = dbSplitNamespace(uri); 1525 noCompress = (pos == uri.length()) || (pos <= URI_COMPRESS_LENGTH); 1526 } else 1527 noCompress = true; 1528 if ( noCompress ) { 1529 pfx = RDBCodeDelim + RDBCodeDelim; 1530 qname = uri; 1531 } else { 1532 DBIDInt pfxid = URItoPrefix(uri, pos, addIfLong); 1534 if ( pfxid == null ) return res; 1535 pfx = RDBCodeDelim + ((DBIDInt)pfxid).getIntID() + RDBCodeDelim; 1536 qname = uri.substring(pos); 1537 } 1538 int encodeLen = RDBCodeURI.length() + 1 + pfx.length() + EOS_LEN; 1539 boolean URIisLong = objectIsLong(encodeLen,qname); 1540 if ( URIisLong ) { 1541 int dbid; 1542 DBIDInt URIid = getURIID(qname,addIfLong); 1544 if ( URIid == null ) return res; 1545 dbid = URIid.getIntID(); 1546 res = new String (RDBCodeURI + RDBCodeRef + pfx + dbid); 1547 } else { 1548 res = RDBCodeURI + RDBCodeValue + pfx + qname + EOS; 1549 } 1550 } else if ( node.isLiteral() ){ 1551 Node_Literal litNode = (Node_Literal) node; 1553 LiteralLabel ll = litNode.getLiteral(); 1554 String lval = ll.getLexicalForm(); 1555 String lang = ll.language(); 1556 String dtype = ll.getDatatypeURI(); 1557 String ld = litLangTypeToRDBString(lang,dtype); 1558 int encodeLen = RDBCodeLiteral.length() + 2 + ld.length() + EOS_LEN; 1559 boolean litIsLong = objectIsLong(encodeLen,lval); 1560 if ( litIsLong ) { 1561 int dbid; 1562 DBIDInt lid = getLiteralID(litNode,addIfLong); 1564 if ( lid == null ) return res; 1565 dbid = lid.getIntID(); 1566 res = new String (RDBCodeLiteral + RDBCodeRef + RDBCodeDelim + dbid); 1567 } else { 1568 res = new String (RDBCodeLiteral + RDBCodeValue + RDBCodeDelim + ld + lval + EOS); 1569 } 1570 } else if ( node.isBlank() ) { 1571 String bnid = node.getBlankNodeId().toString(); 1572 String delims = "::"; 1573 int encodeLen = RDBCodeBlank.length() + 1 + delims.length() + EOS_LEN; 1574 boolean BisLong = objectIsLong(encodeLen,bnid); 1575 if ( BisLong ) { 1576 int dbid; 1577 DBIDInt URIid = getBlankID(bnid,addIfLong); 1579 if ( URIid == null ) return res; 1580 dbid = URIid.getIntID(); 1581 res = new String (RDBCodeBlank + RDBCodeRef + delims + dbid); 1582 } else { 1583 res = new String (RDBCodeBlank + RDBCodeValue + delims + bnid + EOS); 1584 } 1585 1586 } else if ( node.isVariable() ){ 1587 String name = ((Node_Variable)node).getName(); 1588 int len = name.length(); 1589 if ( (len + 3 + EOS_LEN) > LONG_OBJECT_LENGTH ) 1590 throw new JenaException ("Variable name too long: " + name ); 1591 res = RDBCodeVariable + RDBCodeValue + RDBCodeDelim + name + EOS; 1592 } else if ( node.equals(Node.ANY) ) { 1593 res = RDBCodeANY + RDBCodeValue + RDBCodeDelim; 1594 } else { 1595 throw new RDFRDBException ("Expected Concrete Node, got " + node.toString() ); 1596 } 1597 return res; 1598 } 1599 1600 1605 public Node RDBStringToNode ( String RDBString ) throws RDFRDBException { 1606 Node res = null; 1607 int len = RDBString.length(); 1608 if ( len < 3 ) 1609 throw new RDFRDBException("Bad RDBString Header: " + RDBString); 1610 String nodeType = RDBString.substring(0,1); 1611 String valType = RDBString.substring(1,2); 1612 if ( (!(valType.equals(RDBCodeRef) || valType.equals(RDBCodeValue))) || 1613 (RDBString.charAt(2) != RDBCodeDelimChar) ) 1614 throw new RDFRDBException("Bad RDBString Header: " + RDBString); 1615 1616 int pos = 3; 1617 int npos; 1618 1619 if ( nodeType.equals(RDBCodeURI) ) { 1620 ParseInt pi = new ParseInt(pos); 1621 String prefix = ""; 1622 RDBStringParseInt(RDBString, pi, false); 1623 if ( pi.val != null ) { 1624 if ( URI_COMPRESS == false ) 1625 throw new RDFRDBException("Bad URI: Prefix Compression Disabled: " + RDBString); 1626 prefix = IDtoPrefix(pi.val.intValue()); 1627 if ( prefix == null ) 1628 throw new RDFRDBException("Bad URI Prefix: " + RDBString); 1629 } 1630 pos = pi.pos + 1; 1631 String qname; 1632 if ( valType.equals(RDBCodeRef) ) { 1633 qname = IDtoURI(RDBString.substring(pos)); 1634 if ( qname == null ) 1635 throw new RDFRDBException("Bad URI: " + RDBString); 1636 } else 1637 qname = RDBString.substring(pos,len - EOS_LEN); 1638 1639 res = Node.createURI(prefix + qname); 1640 1641 } else if ( nodeType.equals(RDBCodeLiteral) ) { 1642 ParseInt pi = new ParseInt(pos); 1643 String litString = null; 1644 if ( valType.equals(RDBCodeRef) ) { 1645 RDBStringParseInt(RDBString,pi,true); 1646 if ( pi.val != null ) 1647 litString = IDtoLiteral(pi.val.intValue()); 1648 if ( litString == null ) 1649 throw new RDFRDBException("Bad Literal Reference: " + RDBString); 1650 } else 1651 litString = RDBString.substring(pos,len-EOS_LEN); 1652 len = litString.length(); 1653 String lang; 1654 String dtype; 1655 int langLen = 0; 1656 int dtypeLen = 0; 1657 LiteralLabel llabel; 1658 pi.pos = 0; 1659 RDBStringParseInt(litString, pi, false); 1660 if ( pi.val == null ) langLen = 0; 1661 else langLen = pi.val.intValue(); 1662 pi.pos = pi.pos + 1; 1663 RDBStringParseInt(litString, pi, false); 1664 if ( pi.val == null ) dtypeLen = 0; 1665 else dtypeLen = pi.val.intValue(); 1666 pos = pi.pos + 1; 1667 if ( (pos + langLen + dtypeLen) > len ) 1668 throw new RDFRDBException("Malformed Literal: " + litString); 1669 lang = litString.substring(pos,pos+langLen); 1670 pos = pos + langLen; 1671 dtype = litString.substring(pos,pos+dtypeLen); 1672 pos = pos + dtypeLen; 1673 1674 String val = litString.substring(pos); 1675 1676 if ( (dtype == null) || (dtype.equals("")) ) { 1677 llabel = new LiteralLabel(val, lang == null ? "" : lang); 1678 } else { 1679 RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(dtype); 1680 llabel = new LiteralLabel(val, lang == null ? "" : lang, dt); 1681 } 1682 res = Node.createLiteral(llabel); 1683 1684 } else if ( nodeType.equals(RDBCodeBlank) ) { 1685 String bstr = null; 1686 if ( valType.equals(RDBCodeValue) ) { 1687 bstr = RDBString.substring(4,len-EOS_LEN); 1688 } else { 1689 bstr = IDtoBlank(RDBString.substring(4)); 1690 if ( bstr == null ) 1691 throw new RDFRDBException("Bad URI: " + RDBString); 1692 } 1693 res = Node.createAnon( new AnonId (bstr) ); 1694 1695 } else if ( nodeType.equals(RDBCodeVariable) ) { 1696 String vname = RDBString.substring(3,len-EOS_LEN); 1697 res = Node.createVariable(vname); 1698 1699 } else if ( nodeType.equals(RDBCodeANY) ) { 1700 res = Node.ANY; 1701 1702 } else 1703 throw new RDFRDBException ("Invalid RDBString Prefix, " + RDBString ); 1704 return res; 1705 } 1706 1707 1724 public static int dbSplitNamespace(String uri) { 1725 char ch; 1726 int lg = uri.length(); 1727 if (lg == 0) 1728 return 0; 1729 int j; 1730 int i; 1731 for (i = lg - 1; i >= 1; i--) { 1732 ch = uri.charAt(i); 1733 if (!XMLChar.isNCName(ch)) 1734 break; 1735 } 1736 for (j = i + 1; j < lg; j++) { 1737 ch = uri.charAt(j); 1738 if (XMLChar.isNCNameStart(ch)) { 1739 if (uri.charAt(j - 1) == ':' 1740 && uri.lastIndexOf(':', j - 2) == -1) 1741 continue; else 1743 break; 1744 } 1745 } 1746 return j; 1747 } 1748 1749 1750 class ParseInt { 1751 int pos; 1752 Integer val; 1753 ParseInt(int p) {pos = p;} 1754 } 1755 1756 protected void RDBStringParseInt ( String RDBString, ParseInt pi, boolean toEnd ) { 1757 int npos = toEnd ? RDBString.length() : RDBString.indexOf(RDBCodeDelimChar,pi.pos); 1758 if ( npos < 0 ) { 1759 throw new RDFRDBException("Bad RDB String: " + RDBString); 1760 } 1761 String intStr = RDBString.substring(pi.pos,npos); 1762 pi.pos = npos; 1763 if ( intStr.equals("") ) 1764 pi.val = null; 1765 else try { 1766 pi.val = new Integer (intStr); 1767 } catch (NumberFormatException e1) { 1768 throw new RDFRDBException("Bad RDB String: " + RDBString); 1769 } 1770 return; 1771 } 1772 1773 1774 1775 DBIDInt URItoPrefix ( String uri, int pos, boolean add ) { 1776 DBIDInt res; 1777 Object key = prefixCache.getByValue(uri.substring(0,pos)); 1778 if ( key == null ) { 1779 RDBLongObject lobj = PrefixToLongObject(uri,pos); 1780 res = getLongObjectID(lobj, PREFIX_TABLE, add); 1781 if ( res != null ) 1782 prefixCache.put(res,uri.substring(0,pos)); 1783 } else 1784 res = (DBIDInt) key; 1785 return res; 1786 } 1787 1788 protected RDBLongObject PrefixToLongObject ( String prefix, int split ) { 1789 RDBLongObject res = new RDBLongObject(); 1790 int headLen; 1791 int avail; 1792 1793 res.head = RDBCodePrefix + RDBCodeValue + RDBCodeDelim; 1794 headLen = res.head.length(); 1795 avail = INDEX_KEY_LENGTH - (headLen + EOS_LEN); 1796 if ( split > avail ) { 1797 res.head = res.head + prefix.substring(0,avail); 1798 res.tail = prefix.substring(avail,split); 1799 res.hash = stringToHash(res.tail); 1800 } else { 1801 res.head = res.head + prefix.substring(0,split); 1802 res.tail = ""; 1803 } 1804 res.head = res.head + EOS; 1805 return res; 1806 } 1807 1808 1813 public String litLangTypeToRDBString ( String lang, String dtype ) throws RDFRDBException { 1814 String res = RDBCodeDelim; 1815 res = ((lang == null) ? "" : Integer.toString(lang.length())) + RDBCodeDelim; 1816 res = res + ((dtype == null) ? "" : Integer.toString(dtype.length())) + RDBCodeDelim; 1817 res = res + (lang == null ? "" : lang) + (dtype == null ? "" : dtype); 1818 return res; 1819 } 1820 1821 1826 protected boolean objectIsLong ( int encodingLen, String objAsString ) { 1827 return ( (encodingLen + objAsString.length()) > LONG_OBJECT_LENGTH); 1828 } 1829 1830 class RDBLongObject { 1831 String head; 1832 long hash; 1833 String tail; 1834 } 1835 1836 protected RDBLongObject literalToLongObject ( Node_Literal node ) { 1837 RDBLongObject res = new RDBLongObject(); 1838 int headLen; 1839 int avail; 1840 LiteralLabel l = node.getLiteral(); 1841 String lang = l.language(); 1842 String dtype = l.getDatatypeURI(); 1843 String val = l.getLexicalForm(); 1844 String langType = litLangTypeToRDBString(lang,dtype); 1845 1846 res.head = RDBCodeLiteral + RDBCodeValue + RDBCodeDelim + langType; 1847 headLen = res.head.length(); 1848 avail = INDEX_KEY_LENGTH - (headLen + EOS_LEN); 1849 if ( val.length() > avail ) { 1850 res.head = res.head + val.substring(0,avail); 1851 res.tail = val.substring(avail); 1852 res.hash = stringToHash(res.tail); 1853 } else { 1854 res.head = res.head + val; 1855 res.tail = ""; 1856 } 1857 res.head = res.head + EOS; 1858 return res; 1859 } 1860 1861 1862 protected long stringToHash ( String str ) { 1863 CRC32 checksum = new CRC32 (); 1864 checksum.update(str.getBytes()); 1865 return checksum.getValue(); 1866 } 1867 1868 1871 public DBIDInt getBlankID(String bstr, boolean add) throws RDFRDBException { 1872 RDBLongObject lobj = URIToLongObject (bstr,RDBCodeBlank); 1873 return getLongObjectID(lobj, LONG_URI_TABLE, add); 1874 } 1875 1876 1879 public DBIDInt getURIID(String qname, boolean add) throws RDFRDBException { 1880 RDBLongObject lobj = URIToLongObject (qname,RDBCodeURI); 1881 return getLongObjectID(lobj, LONG_URI_TABLE, add); 1882 } 1883 1884 protected RDBLongObject URIToLongObject ( String qname, String code ) { 1885 RDBLongObject res = new RDBLongObject(); 1886 int headLen; 1887 int avail; 1888 1889 res.head = code + RDBCodeValue + RDBCodeDelim; 1890 headLen = res.head.length(); 1891 avail = INDEX_KEY_LENGTH - (headLen + EOS_LEN); 1892 if ( qname.length() > avail ) { 1893 res.head = res.head + qname.substring(0,avail); 1894 res.tail = qname.substring(avail); 1895 res.hash = stringToHash(res.tail); 1896 } else { 1897 res.head = res.head + qname; 1898 res.tail = ""; 1899 } 1900 res.head = res.head + EOS; 1901 return res; 1902 } 1903 1904 1905 1908 public DBIDInt getLiteralID(Node_Literal lnode, boolean add) throws RDFRDBException { 1909 RDBLongObject lobj = literalToLongObject (lnode); 1910 return getLongObjectID(lobj, LONG_LIT_TABLE, add); 1911 } 1912 1913 public DBIDInt getLongObjectID(RDBLongObject lobj, String table, boolean add) throws RDFRDBException { 1914 try { 1915 String opName = "getLongObjectID"; 1916 if ( lobj.tail.length() > 0 ) 1917 opName += "withChkSum"; 1918 PreparedStatement ps = m_sql.getPreparedSQLStatement(opName, table); 1919 ps.setString(1,lobj.head); 1920 if ( lobj.tail.length() > 0 ) 1921 ps.setLong(2, lobj.hash); 1922 1923 ResultSet rs = ps.executeQuery(); 1924 DBIDInt result = null; 1925 if (rs.next()) { 1926 result = wrapDBID(rs.getObject(1)); 1927 } else { 1928 if ( add ) 1929 result = addRDBLongObject(lobj, table); 1930 } 1931 rs.close(); 1932 m_sql.returnPreparedSQLStatement(ps); 1933 return result; 1934 } catch (SQLException e1) { 1935 throw new RDFRDBException("Failed to find literal", e1); 1937 } 1938 } 1939 1940 1945 public DBIDInt addRDBLongObject(RDBLongObject lobj, String table) throws RDFRDBException { 1946 try { 1947 int argi = 1; 1948 String opname = "insertLongObject"; 1949 PreparedStatement ps = m_sql.getPreparedSQLStatement(opname, table); 1950 int dbid = 0; if ( PRE_ALLOCATE_ID ) { 1952 dbid = getInsertID(table); 1953 ps.setInt(argi++,dbid); 1954 } 1955 ps.setString(argi++, lobj.head); 1956 if ( lobj.tail.length() > 0 ) { 1957 ps.setLong(argi++, lobj.hash); 1958 ps.setString(argi++, lobj.tail); 1959 } else { 1960 ps.setNull(argi++,java.sql.Types.BIGINT); 1961 ps.setNull(argi++,java.sql.Types.VARCHAR); 1962 } 1963 1986 ps.executeUpdate(); 1987 if ( !PRE_ALLOCATE_ID ) dbid = getInsertID(table); 1989 return wrapDBID(new Integer (dbid)); 1990 } catch (Exception e1) { 1991 System.out.println("Problem on long object (l=" + lobj.head + ") " + e1 ); 1992 throw new RDFRDBException("Failed to add long object ", e1); 1994 } 1995 } 1996 1997 2002 protected String IDtoPrefix ( int prefixID ) { 2003 DBIDInt dbid = new DBIDInt(prefixID); 2005 Object res = prefixCache.get(dbid); 2006 if ( res != null) 2007 return (String ) res; 2008 else 2009 return IDtoString ( prefixID, PREFIX_TABLE, RDBCodePrefix); 2010 } 2011 2012 2017 protected String IDtoBlank(String bnID) { 2018 return IDtoString(bnID, LONG_URI_TABLE, RDBCodeBlank); 2019 } 2020 2025 protected String IDtoURI(String uriID) { 2026 return IDtoString(uriID, LONG_URI_TABLE, RDBCodeURI); 2027 } 2028 2029 2034 protected String IDtoLiteral ( int litID ) { 2035 return IDtoString ( litID, LONG_LIT_TABLE, RDBCodeLiteral); 2036 } 2037 2038 2039 2040 protected String IDtoString ( String dbidAsString, String table, String RDBcode ) { 2041 int dbID; 2042 String res = null; 2043 try { 2044 dbID = Integer.parseInt(dbidAsString); 2045 } catch (NumberFormatException e1) { 2046 throw new RDFRDBException("Invalid Object ID: " + dbidAsString); 2047 } 2048 return IDtoString (dbID, table, RDBcode); 2049 } 2050 2051 protected String IDtoString ( int dbID, String table, String RDBcode ) { 2052 String res = null; 2053 RDBLongObject lobj = IDtoLongObject(dbID, table); 2054 if ( lobj == null ) 2055 throw new RDFRDBException("Invalid Object ID: " + dbID); 2056 if ( !lobj.head.substring(0,3).equals(RDBcode + RDBCodeValue + RDBCodeDelim) ) 2058 throw new RDFRDBException("Malformed URI in Database: " + lobj.head); 2059 res = lobj.head.substring(3,lobj.head.length() - EOS_LEN); 2060 if ( lobj.tail != null ) 2061 res = res + lobj.tail; 2062 return res; 2063 } 2064 2065 2066 protected RDBLongObject IDtoLongObject ( int dbid, String table ) { 2067 RDBLongObject res = null; 2068 try { 2069 String opName = "getLongObject"; 2070 PreparedStatement ps = m_sql.getPreparedSQLStatement(opName, table); 2071 ps.setInt(1,dbid); 2072 ResultSet rs = ps.executeQuery(); 2073 if (rs.next()) { 2074 res = new RDBLongObject(); 2075 res.head = rs.getString(1); 2076 res.tail = rs.getString(2); 2077 } 2078 rs.close(); 2079 m_sql.returnPreparedSQLStatement(ps); 2080 } catch (SQLException e1) { 2081 throw new RDFRDBException("Failed to find literal", e1); 2083 } 2084 return res; 2085 } 2086 2087 protected RDBLongObject IDtoLongObject ( String idAsString, String table ) { 2088 RDBLongObject res = null; 2089 int dbid; 2090 try { 2091 dbid = Integer.parseInt(idAsString); 2092 } catch (NumberFormatException e1) { 2093 throw new RDFRDBException("Invalid Object ID: " + idAsString); 2094 } 2095 return IDtoLongObject(dbid,table); 2096 } 2097 2098 2099 2103 public DBIDInt wrapDBID(Object id) throws RDFRDBException { 2104 if (id instanceof Number ) { 2105 return new DBIDInt(((Number )id).intValue()); 2106 } else if (id == null) { 2107 return null; 2108 } else { 2109 throw new RDFRDBException("Unexpected DB identifier type: " + id); 2110 } 2112 } 2113 2114 public String genSQLReifQualStmt () { 2115 return "stmt = ?"; 2116 } 2117 2118 public String genSQLReifQualAnyObj( boolean objIsStmt) { 2119 return "( subj = ? OR prop = ? OR obj = ?" + (objIsStmt ? " OR hasType = " + 2120 QUOTE_CHAR + "T" + QUOTE_CHAR + " )" : " )"); 2121 } 2122 2123 public String genSQLReifQualObj ( char reifProp, boolean hasObj ) { 2124 String qual = ""; 2125 if ( reifProp == 'T' ) { 2126 qual = "hasType = " + QUOTE_CHAR + "T" + QUOTE_CHAR; 2127 } else { 2128 String cmp = (hasObj ? " = ?" : " is not null"); 2129 String col = null; 2130 if ( reifProp == 'S' ) col = "subj"; 2131 else if ( reifProp == 'P' ) col = "prop"; 2132 else if ( reifProp == 'O' ) col = "obj"; 2133 else throw new JenaException("Undefined reification property"); 2134 2135 qual = col + cmp; 2136 } 2137 return qual; 2138 } 2139 2140 protected String colidToColname ( char colid ) { 2141 if ( colid == 'G' ) return "GraphID"; 2142 if ( colid == 'P' ) return "Prop"; 2143 if ( colid == 'S' ) return "Subj"; 2144 if ( colid == 'O' ) return "Obj"; 2145 if ( colid == 'N' ) return "Stmt"; 2146 if ( colid == 'T' ) return "HasType"; 2147 throw new JenaException("Invalid column identifer: '" + colid + "\'"); 2148 } 2149 2150 protected String aliasToString ( int alias ) { 2151 return "A" + alias; 2152 } 2153 2154 protected String colAliasToString ( int alias, char colid ) { 2155 return aliasToString(alias) + "." + colidToColname(colid); 2156 } 2157 2158 2166 2167 public String genSQLQualConst ( int alias, char pred, Node lit ) { 2168 String val = nodeToRDBString(lit, false); 2169 if ( val == "" ) 2170 val = RDBCodeInvalid; 2174 return colAliasToString(alias,pred) + "=" + QUOTE_CHAR + val + QUOTE_CHAR; 2175 } 2176 2177 public String genSQLReifQualConst ( int alias, char pred, Node lit ) { 2178 String val = ""; 2179 if ( (pred == 'T') && (lit.equals(RDF.Nodes.Statement)) ) 2180 val = "T"; 2181 else 2182 val = nodeToRDBString(lit, false); 2183 return colAliasToString(alias,pred) + "=" + QUOTE_CHAR + val + QUOTE_CHAR; 2184 } 2185 2186 public String genSQLQualParam( int alias, char pred ) { 2187 return colAliasToString(alias,pred) + "=?"; 2188 } 2189 2190 public String genSQLQualGraphId( int alias, int graphId ) { 2191 return colAliasToString(alias,'G') + "=" + graphId; 2192 } 2193 2194 public String genSQLJoin( int lhsAlias, char lhsCol, 2195 int rhsAlias, char rhsCol ) { 2196 return colAliasToString(lhsAlias,lhsCol) + "=" + 2197 colAliasToString(rhsAlias,rhsCol); 2198 } 2199 2200 public String genSQLStringMatch( int alias, char col, 2201 String fun, String stringToMatch ) { 2202 boolean ignCase = 2203 fun.equals(ExpressionFunctionURIs.J_startsWithInsensitive) || 2204 fun.equals(ExpressionFunctionURIs.J_endsWithInsensitive); 2205 boolean pfxMatch = 2206 fun.equals(ExpressionFunctionURIs.J_startsWith) || 2207 fun.equals(ExpressionFunctionURIs.J_startsWithInsensitive); 2208 String var = colAliasToString(alias,col); 2209 String qual = " ( " + genSQLStringMatchLHS(ignCase,var); 2211 qual += " " + genSQLStringMatchOp(ignCase,fun); 2212 qual += " " + genSQLStringMatchRHS(ignCase,pfxMatch,stringToMatch); 2213 qual += " " + genSQLOrKW() + genSQLStringMatchLHS(false,var); 2215 qual += " " + genSQLStringMatchOp(false,fun); 2216 qual += " " + genSQLStringMatchLong() + " )"; 2217 2218 return qual; 2219 } 2220 2221 public String genSQLStringMatchLHS( boolean ignCase, String var ) { 2222 return ignCase ? genSQLStringMatchLHS_IC(var): var; 2223 } 2224 2225 public String genSQLStringMatchLong( ) { 2226 return QUOTE_CHAR + stringMatchAnyChar() + stringMatchLongObj() + 2227 stringMatchAllChar() + QUOTE_CHAR; 2228 } 2229 2230 public String genSQLStringMatchOp( boolean ignCase, String fun ) { 2231 return ignCase ? genSQLStringMatchOp_IC(fun): 2232 genSQLStringMatchOp(fun); 2233 } 2234 2235 public String stringMatchAllChar() { return "%"; } 2236 public String stringMatchAnyChar() { return "_"; } 2237 public String stringMatchEscapeChar() { return "\\\\"; } 2238 public String stringMatchLongObj() { return "r"; } 2239 public String stringMatchShortObj() { return "v"; } 2240 2241 public String genSQLStringMatchRHS( boolean ignCase, boolean pfxMatch, 2242 String strToMatch ) { 2243 boolean isEscaped = stringMatchNeedsEscape(strToMatch); 2244 if ( isEscaped ) strToMatch = addEscape(strToMatch); 2245 2254 strToMatch = stringMatchAnyChar() + stringMatchShortObj() + 2255 stringMatchAllChar() + strToMatch + stringMatchAllChar(); 2256 strToMatch = QUOTE_CHAR + strToMatch + QUOTE_CHAR; 2257 String qual = ignCase ? genSQLStringMatchRHS_IC(strToMatch): strToMatch; 2258 if ( isEscaped ) qual += genSQLStringMatchEscape(); 2259 2260 return qual; 2261 } 2262 2263 public String genSQLStringMatchLHS_IC(String var) { 2264 return var; 2265 } 2266 2267 public String genSQLStringMatchRHS_IC(String strToMatch) { 2268 return strToMatch; 2269 } 2270 2271 public String genSQLStringMatchOp( String fun ) { 2272 return genSQLLikeKW(); 2273 } 2274 2275 public String genSQLStringMatchOp_IC( String fun ) { 2276 return genSQLLikeKW(); 2277 } 2278 2279 public boolean stringMatchNeedsEscape ( String strToMatch ) { 2280 return strToMatch.indexOf('_') >= 0; 2281 } 2282 2283 public String addEscape ( String strToMatch ) { 2284 int i = strToMatch.indexOf('_'); 2285 return strToMatch.substring(0,i) + stringMatchEscapeChar() + 2286 strToMatch.substring(i); 2287 } 2288 2289 public String genSQLStringMatchEscape() { 2290 return ""; 2291 } 2292 2293 public String genSQLResList( int resIndex[], VarDesc[] binding ) { 2294 String resList = ""; 2295 int i,j; 2296 for(i=0,j=0;i<binding.length;i++) { 2297 VarDesc b = binding[i]; 2298 if ( !b.isArgVar() ) { 2299 resList += (j>0?", ":"") + colAliasToString(b.alias,b.column); 2301 if ( j >= resIndex.length ) 2302 throw new JenaException("Too many result columns"); 2303 resIndex[j++] = b.mapIx; 2304 } 2305 } 2306 return resList; 2307 } 2308 2309 public String genSQLFromList( int aliasCnt, String table ) { 2310 int i; 2311 String resList = ""; 2312 for(i=0;i<aliasCnt;i++) { 2313 resList += (i>0?", ":"") + table + " " + aliasToString(i); 2314 } 2315 return resList; 2316 2317 } 2318 2319 public String genSQLLikeKW() { 2320 return "Like "; 2321 } 2322 2323 public String genSQLEscapeKW() { 2324 return "Escape "; 2325 } 2326 2327 public String genSQLSelectKW() { 2328 return "Select "; 2329 } 2330 2331 public String genSQLFromKW() { 2332 return "From "; 2333 } 2334 2335 public String genSQLWhereKW() { 2336 return "Where "; 2337 } 2338 2339 public String genSQLOrKW() { 2340 return "Or "; 2341 } 2342 2343 2344 2345 public String genSQLSelectStmt( String res, String from, String qual ) { 2346 return genSQLSelectKW() + res + " " + 2347 genSQLFromKW() + from + " " + 2348 (qual.length() == 0 ? qual :genSQLWhereKW()) + qual; 2349 } 2350 2351 2352 protected int getTableCount(int graphId) { 2353 try { 2354 DatabaseMetaData dbmd = m_dbcon.getConnection().getMetaData(); 2355 String [] tableTypes = { "TABLE" }; 2356 int res = 0; 2357 String tblPattern = 2358 TABLE_NAME_PREFIX + "g" + Integer.toString(graphId) + "%"; 2359 tblPattern = stringToDBname(tblPattern); 2360 ResultSet alltables = 2361 dbmd.getTables(null, null, tblPattern, tableTypes); 2362 while (alltables.next()) { 2363 res += 1; 2364 } 2365 alltables.close(); 2366 return res; 2367 } catch (SQLException e1) { 2368 throw new RDFRDBException("Internal SQL error in driver - " + e1); 2369 } 2370 } 2371 2372 2375 2376 public int getLongObjectLength () { 2377 return LONG_OBJECT_LENGTH; 2378 } 2379 2380 public void setLongObjectLength ( int len ) { 2381 checkDbUninitialized(); 2382 if ( len > LONG_OBJECT_LENGTH_MAX ) 2383 throw new JenaException("IndexKeyLength exceeds maximum value for database"); 2384 LONG_OBJECT_LENGTH = len; 2385 } 2386 2387 public int getIndexKeyLength () { 2388 return INDEX_KEY_LENGTH; 2389 } 2390 2391 public void setIndexKeyLength ( int len ) { 2392 checkDbUninitialized(); 2393 if ( len > INDEX_KEY_LENGTH_MAX ) 2394 throw new JenaException("IndexKeyLength exceeds maximum value for database"); 2395 INDEX_KEY_LENGTH = len; 2396 } 2397 2398 public boolean getIsTransactionDb () { 2399 return IS_XACT_DB; 2400 } 2401 2402 public void setIsTransactionDb ( boolean bool ) { 2403 checkDbUninitialized(); 2404 if ( bool == false ) 2405 throw new JenaException("setIsTransactionDb unsupported for this database engine"); 2406 } 2407 2408 public boolean getDoCompressURI () { 2409 return URI_COMPRESS; 2410 } 2411 2412 public void setDoCompressURI ( boolean bool ) { 2413 checkDbUninitialized(); 2414 URI_COMPRESS = bool; 2415 } 2416 2417 public int getCompressURILength() { 2418 return URI_COMPRESS_LENGTH; 2419 } 2420 2421 public void setCompressURILength ( int len ) { 2422 checkDbUninitialized(); 2423 URI_COMPRESS_LENGTH = len; 2424 } 2425 2426 public boolean getDoDuplicateCheck() { 2427 return !SKIP_DUPLICATE_CHECK; 2428 } 2429 2430 public void setDoDuplicateCheck(boolean bool) { 2431 SKIP_DUPLICATE_CHECK = !bool; 2432 } 2433 2434 protected boolean dbIsOpen() { 2435 return (m_sysProperties != null); 2436 } 2437 2438 protected void checkDbIsOpen() { 2439 if ( !dbIsOpen() ) 2440 throw new JenaException("Database not open"); 2441 } 2442 2443 protected void checkDbUninitialized() { 2444 if ( dbIsOpen() || isDBFormatOK() ) 2445 throw new JenaException("Database configuration option cannot be set after database is formatted"); 2446 } 2447 2448 public String getTableNamePrefix() { 2449 return TABLE_NAME_PREFIX; 2450 } 2451 2452 public void setTableNamePrefix ( String prefix ) { 2453 if ( dbIsOpen() ) 2454 throw new JenaException("Table name prefix must be set before opening or connecting to a model."); 2455 2460 String sav = TABLE_NAME_PREFIX; 2461 String testpfx = prefix; 2462 int i; 2463 for ( i=0;i<MAXIMUM_INDEX_COLUMNS;i++) testpfx += "X"; 2464 setTableNames(testpfx); 2465 try { 2467 String s = genTableName(10,10,true); 2468 s = genTableName(10,10,false); 2469 } catch ( RDFRDBException e ) { 2470 setTableNames(sav); 2471 throw new JenaException("New prefix (\"" + prefix + 2472 "\") is too long and will cause table names \n" + 2473 "to exceed maximum length for database (" + TABLE_NAME_LENGTH_MAX + ")."); 2474 } 2475 setTableNames(prefix); 2477 } 2478 2479 2480 2483 2484 protected String genTableName( int graphId, int tblId, boolean isReif ) 2485 { 2486 String res = stringToDBname(TABLE_NAME_PREFIX + 2487 "g" + Integer.toString(graphId) + 2488 "t" + Integer.toString(tblId) + 2489 (isReif ? REIF_TABLE_NAME_SUFFIX : STMT_TABLE_NAME_SUFFIX)); 2490 if ( res.length() > TABLE_NAME_LENGTH_MAX ) 2491 throw new RDFRDBException("New table name (\"" + res + 2492 "\") exceeds maximum length for database (" + TABLE_NAME_LENGTH_MAX + ")."); 2493 return res; 2494 } 2495 2496 2497 2499 2500 protected void setTableNames ( String prefix ) { 2501 TABLE_NAME_PREFIX = stringToDBname(prefix); 2502 int i = 0; 2503 SYSTEM_TABLE_NAME = new String [6]; 2504 SYSTEM_TABLE_NAME[i++] = SYSTEM_STMT_TABLE = stringToDBname(TABLE_NAME_PREFIX + "sys_stmt"); 2505 SYSTEM_TABLE_NAME[i++] = LONG_LIT_TABLE = stringToDBname(TABLE_NAME_PREFIX + "long_lit"); 2506 SYSTEM_TABLE_NAME[i++] = LONG_URI_TABLE = stringToDBname(TABLE_NAME_PREFIX + "long_uri"); 2507 SYSTEM_TABLE_NAME[i++] = PREFIX_TABLE = stringToDBname(TABLE_NAME_PREFIX + "prefix"); 2508 SYSTEM_TABLE_NAME[i++] = GRAPH_TABLE = stringToDBname(TABLE_NAME_PREFIX + "graph"); 2509 SYSTEM_TABLE_NAME[i++] = MUTEX_TABLE = stringToDBname(TABLE_NAME_PREFIX + "mutex"); 2510 SYSTEM_TABLE_CNT = i; 2511 } 2512 2513 2516 2517 public int getSystemTableCount() { 2518 return SYSTEM_TABLE_CNT; 2519 } 2520 2521 2524 2525 public String getSystemTableName ( int i ) { 2526 return ((i < 0) || (i >= SYSTEM_TABLE_CNT)) ? 2527 null : SYSTEM_TABLE_NAME[i]; 2528 } 2529 2530 2531 public String getStoreWithModel() { 2532 return STORE_WITH_MODEL; 2533 } 2534 2535 public void setStoreWithModel(String modelName) { 2536 String name = null; 2537 if ((modelName != null) && !modelName.equals("")) 2538 name = modelName; 2539 STORE_WITH_MODEL = name; 2540 } 2541 2542 public int getCompressCacheSize() { 2543 checkDbIsOpen(); 2544 return prefixCache.getLimit(); 2545 } 2546 2547 public void setCompressCacheSize(int count) { 2548 checkDbIsOpen(); 2549 prefixCache.setLimit(count); 2550 } 2551 2552} 2553 2554 2555 2556 2582 | Popular Tags |