001: /*
002: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: * All rights reserved.
004: *
005: *
006: */
007:
008: package com.hp.hpl.jena.db.impl;
009:
010: import java.sql.DatabaseMetaData;
011: import java.sql.PreparedStatement;
012: import java.sql.ResultSet;
013: import java.sql.SQLException;
014: import java.util.ArrayList;
015: import java.util.Iterator;
016: import java.util.List;
017:
018: import com.hp.hpl.jena.db.IDBConnection;
019: import com.hp.hpl.jena.db.RDFRDBException;
020:
021: /**
022: * @author hkuno based on code by Dave Reynolds.
023: * Modified for later, more standard, Oracle drivers by Andy Seaborne (Dec 2006)
024: *
025: * See alo Driver_Oracle_LOB for code that uses native
026: * Oracle blobs more directly. That needs uncommenting
027: * some code sections and recompiling against Oracle
028: * Java libraries.
029: */
030:
031: public class Driver_Oracle extends DriverRDB {
032:
033: public Driver_Oracle() {
034: super ();
035:
036: String myPackageName = this .getClass().getPackage().getName();
037:
038: DATABASE_TYPE = "Oracle";
039: // Must aline to driver. But the EngineType is set from the driver.
040: // See also PSet_TripleStore_RDB.storeTripleAR which tests specifically for "Oracle".
041:
042: DRIVER_NAME = "oracle.jdbc.driver.OracleDriver";
043:
044: ID_SQL_TYPE = "INTEGER";
045: URI_COMPRESS = false;
046: // LONG_OBJECT_LENGTH_MAX = INDEX_KEY_LENGTH_MAX = INDEX_KEY_LENGTH = 2000;
047: // LONG_OBJECT_LENGTH = 250;
048:
049: LONG_OBJECT_LENGTH_MAX = INDEX_KEY_LENGTH_MAX = INDEX_KEY_LENGTH = 250;
050: LONG_OBJECT_LENGTH = 250;
051:
052: TABLE_NAME_LENGTH_MAX = 30;
053: /* 30 is a guesstimate. setConnection should be called
054: * immediately to get the correct value. */
055: IS_XACT_DB = true;
056: PRE_ALLOCATE_ID = true;
057: SKIP_DUPLICATE_CHECK = false;
058: SQL_FILE = "etc/oracle.sql";
059:
060: m_psetClassName = myPackageName + ".PSet_TripleStore_RDB";
061: m_psetReifierClassName = myPackageName + ".PSet_ReifStore_RDB";
062:
063: m_lsetClassName = myPackageName
064: + ".SpecializedGraph_TripleStore_RDB";
065: m_lsetReifierClassName = myPackageName
066: + ".SpecializedGraphReifier_RDB";
067:
068: QUOTE_CHAR = '\'';
069:
070: DB_NAMES_TO_UPPER = true;
071: setTableNames(TABLE_NAME_PREFIX);
072: }
073:
074: /**
075: * Set the database connection
076: */
077: public void setConnection(IDBConnection dbcon) {
078: m_dbcon = dbcon;
079:
080: try {
081: DatabaseMetaData dmd = dbcon.getConnection().getMetaData();
082: if (dmd == null)
083: throw new RDFRDBException(
084: "Oracle database metadata not available.");
085: TABLE_NAME_LENGTH_MAX = dmd.getMaxTableNameLength();
086: setTableNames(TABLE_NAME_PREFIX); // need to recheck that table names are not too long
087: } catch (SQLException e) {
088: throw new RDFRDBException(
089: "Problem accessing Oracle database metadata.");
090: }
091:
092: try {
093: m_sql = new SQLCache(SQL_FILE, null, dbcon, ID_SQL_TYPE);
094: } catch (Exception e) {
095: e.printStackTrace(System.err);
096: logger.error("Unable to set connection for Driver:", e);
097: }
098: }
099:
100: /**
101: * Allocate an identifier for a new graph.
102: *
103: */
104: public int graphIdAlloc(String graphName) {
105: DBIDInt result = null;
106: int dbid = 0;
107: try {
108: String op = "insertGraph";
109: dbid = getInsertID(GRAPH_TABLE);
110: PreparedStatement ps = m_sql.getPreparedSQLStatement(op,
111: GRAPH_TABLE);
112: ps.setInt(1, dbid);
113: ps.setString(2, graphName);
114: ps.executeUpdate();
115: m_sql.returnPreparedSQLStatement(ps);
116: } catch (SQLException e) {
117: throw new RDFRDBException(
118: "Failed to get last inserted ID: " + e);
119: }
120: return dbid;
121: }
122:
123: /**
124: * Dellocate an identifier for a graph.
125: *
126: */
127: public void graphIdDealloc(int graphId) {
128: DBIDInt result = null;
129: try {
130: String op = "deleteGraph";
131: PreparedStatement ps = m_sql.getPreparedSQLStatement(op,
132: GRAPH_TABLE);
133: ps.setInt(1, graphId);
134: ps.executeUpdate();
135: m_sql.returnPreparedSQLStatement(ps);
136: } catch (SQLException e) {
137: throw new RDFRDBException("Failed to delete graph ID: " + e);
138: }
139: return;
140: }
141:
142: // Now common code moved to DriverRDB - delete this anytime after Jena 2.5.2
143: // public int getInsertID ( String tableName ) {
144: // DBIDInt result = null;
145: // try {
146: // String op = "getInsertID";
147: // PreparedStatement ps = m_sql.getPreparedSQLStatement(op,tableName);
148: // ResultSet rs = ps.executeQuery();
149: // if (rs.next()) {
150: // result = wrapDBID(rs.getObject(1));
151: // } else
152: // throw new RDFRDBException("No insert ID");
153: // m_sql.returnPreparedSQLStatement(ps);
154: // } catch (SQLException e) {
155: // throw new RDFRDBException("Failed to insert ID: " + e);
156: // }
157: // return result.getIntID();
158: // }
159:
160: /**
161: * Return the parameters for table creation.
162: * 1) column type for subj, prop, obj.
163: * 2) column type for head.
164: * 3) table and index name prefix.
165: * @param param array to hold table creation parameters.
166: */
167: protected void getTblParams(String[] param) {
168: String objColType;
169:
170: // length of varchar columns in statement tables
171: if (LONG_OBJECT_LENGTH > 4000)
172: throw new RDFRDBException("Long object length specified ("
173: + LONG_OBJECT_LENGTH
174: + ") exceeds maximum sane length of 4000.");
175: if (INDEX_KEY_LENGTH > 4000)
176: throw new RDFRDBException("Index key length specified ("
177: + INDEX_KEY_LENGTH
178: + ") exceeds maximum sane length of 4000.");
179:
180: objColType = "NVARCHAR2(" + LONG_OBJECT_LENGTH + ")";
181: STRINGS_TRIMMED = false;
182: param[0] = objColType;
183:
184: // length of head column in literal tables
185: String headColType = "NVARCHAR2(" + INDEX_KEY_LENGTH + ")";
186: param[1] = headColType;
187: param[2] = TABLE_NAME_PREFIX;
188: }
189:
190: /**
191: *
192: * Return the parameters for table creation.
193: * Generate the table name by counting the number of existing
194: * tables for the graph. This is not reliable if another client
195: * is concurrently trying to create a table so, if failure, we
196: * make several attempts to create the table.
197: */
198:
199: protected String[] getCreateTableParams(int graphId, boolean isReif) {
200: String[] parms = new String[3];
201: String[] res = new String[2];
202:
203: getTblParams(parms);
204: int tblCnt = getTableCount(graphId);
205: res[0] = genTableName(graphId, tblCnt, isReif);
206: res[1] = parms[0];
207: return res;
208: }
209:
210: /**
211: * Return the parameters for database initialization.
212: */
213: protected String[] getDbInitTablesParams() {
214: String[] res = new String[3];
215:
216: getTblParams(res);
217: EOS_LEN = EOS.length();
218:
219: return res;
220: }
221:
222: // /**
223: // * Insert a long object into the database.
224: // * This assumes the object is not already in the database.
225: // * @return the db index of the added literal
226: // */
227:
228: // // Try to use standard blob handling
229: //
230: // public DBIDInt addRDBLongObject(RDBLongObject lobj, String table) throws RDFRDBException {
231: // // Assumes tail is in the prepared statement
232: // return super.addRDBLongObject(lobj, table) ;
233: // }
234:
235: // /**
236: // * Retrieve LongObject from database.
237: // */
238: // protected RDBLongObject IDtoLongObject ( int dbid, String table ) {
239: // return super.IDtoLongObject(dbid, table) ;
240: // }
241:
242: protected void setLongObjectHashAndTail(PreparedStatement ps,
243: int argi, RDBLongObject lobj) throws SQLException {
244: int paramCount = ps.getParameterMetaData().getParameterCount();
245: // In Jena 2.4 and before, using Oracle specific BLOB code, this is 3.
246: // In Jena 2.5 it is 4 because of a change to the SQL statement in etc/oracle.sql
247: // Check this here.
248: if (paramCount != 4) {
249: logger
250: .warn("Warning: Driver_Oracle: Mismatch in prepared statement paramter count: Expected "
251: + 4 + " : Got: " + paramCount);
252: logger
253: .warn("Maybe running with an old (pre Jena2.5) etc/oracle.sql file?");
254: }
255:
256: super .setLongObjectHashAndTail_Binary(ps, argi, lobj);
257: }
258:
259: /**
260: * Drop all Jena-related sequences from database, if necessary.
261: * Override in subclass if sequences must be explicitly deleted.
262: */
263: public void clearSequences() {
264: Iterator seqIt = getSequences().iterator();
265: while (seqIt.hasNext()) {
266: removeSequence((String) seqIt.next());
267: }
268: }
269:
270: /** Oracle implementation of getConnection().getMetaData() can see all tables if run sufficiently priviledge.
271: *
272: */
273: protected List getAllTables() {
274: try {
275: // DatabaseMetaData dbmd = m_dbcon.getConnection().getMetaData();
276: // String[] tableTypes = { "TABLE" };
277: // String prefixMatch = stringToDBname(TABLE_NAME_PREFIX + "%");
278: // ResultSet rs = dbmd.getTables(null, dbmd.getUserName(), prefixMatch, tableTypes);
279:
280: // This way (Oracle specific) see only the tables we own and access.
281: String sql = "SELECT TNAME AS TABLE_NAME FROM tab WHERE TNAME LIKE '"
282: + TABLE_NAME_PREFIX + "%'";
283: ResultSet rs = m_dbcon.getConnection().createStatement()
284: .executeQuery(sql);
285:
286: List tables = new ArrayList();
287: while (rs.next())
288: tables.add(rs.getString("TABLE_NAME"));
289: rs.close();
290: return tables;
291: } catch (SQLException e1) {
292: throw new RDFRDBException("Internal SQL error in driver - "
293: + e1);
294: }
295: }
296:
297: public String genSQLStringMatchLHS_IC(String var) {
298: return "UPPER(" + var + ")";
299: }
300:
301: public String genSQLStringMatchRHS_IC(String strToMatch) {
302: return "UPPER(" + strToMatch + ")";
303: }
304:
305: public String stringMatchEscapeChar() {
306: return "\\";
307: }
308:
309: public String genSQLStringMatchEscape() {
310: return " " + genSQLEscapeKW() + " '" + stringMatchEscapeChar()
311: + "'";
312: }
313: }
314:
315: /*
316: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
317: * All rights reserved.
318: *
319: * Redistribution and use in source and binary forms, with or without
320: * modification, are permitted provided that the following conditions
321: * are met:
322: * 1. Redistributions of source code must retain the above copyright
323: * notice, this list of conditions and the following disclaimer.
324: * 2. Redistributions in binary form must reproduce the above copyright
325: * notice, this list of conditions and the following disclaimer in the
326: * documentation and/or other materials provided with the distribution.
327: * 3. The name of the author may not be used to endorse or promote products
328: * derived from this software without specific prior written permission.
329:
330: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
331: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
332: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
333: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
334: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
335: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
336: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
338: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
339: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
340: */
|