diff options
Diffstat (limited to 'src/main/java/com/amazon/carbonado/repo/jdbc')
6 files changed, 790 insertions, 0 deletions
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlExceptionTransformer.java new file mode 100644 index 0000000..6b86757 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlExceptionTransformer.java @@ -0,0 +1,40 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.sql.SQLException;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class MysqlExceptionTransformer extends JDBCExceptionTransformer {
+ public static int DUPLICATE_ENTRY = 1062;
+
+ public boolean isUniqueConstraintError(SQLException e) {
+ if (isConstraintError(e)) {
+ String sqlstate = e.getSQLState();
+ int errorCode = e.getErrorCode();
+ return DUPLICATE_ENTRY == errorCode
+ || SQLSTATE_UNIQUE_CONSTRAINT_VIOLATION.equals(sqlstate);
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java new file mode 100644 index 0000000..e06f1f8 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/MysqlSupportStrategy.java @@ -0,0 +1,45 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+
+import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.PersistException;
+import com.amazon.carbonado.Transaction;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class MysqlSupportStrategy extends JDBCSupportStrategy {
+ protected MysqlSupportStrategy(JDBCRepository repo) {
+ super(repo);
+ }
+
+ JDBCExceptionTransformer createExceptionTransformer() {
+ return new MysqlExceptionTransformer();
+ }
+}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleBlob.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleBlob.java new file mode 100644 index 0000000..f60ade9 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleBlob.java @@ -0,0 +1,137 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+
+import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.PersistException;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class OracleBlob extends JDBCBlob {
+ OracleBlob(JDBCRepository repo, Blob blob, JDBCBlobLoader loader) {
+ super(repo, blob, loader);
+ }
+
+ @Override
+ public InputStream openInputStream() throws FetchException {
+ return openInputStream(0);
+ }
+
+ @Override
+ public InputStream openInputStream(long pos) throws FetchException {
+ Method m = support().mBLOB_getBinaryStream;
+
+ if (m == null) {
+ return super.openInputStream(pos);
+ }
+
+ try {
+ return (InputStream) m.invoke(getInternalBlobForFetch(), pos);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toFetchException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toFetchException(e);
+ }
+ }
+
+ @Override
+ public InputStream openInputStream(long pos, int bufferSize) throws FetchException {
+ return openInputStream(pos);
+ }
+
+ @Override
+ public long getLength() throws FetchException {
+ Method m = support().mBLOB_length;
+
+ if (m == null) {
+ return super.getLength();
+ }
+
+ try {
+ return (Long) m.invoke(getInternalBlobForFetch());
+ } catch (InvocationTargetException e) {
+ throw mRepo.toFetchException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toFetchException(e);
+ }
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws PersistException {
+ return openOutputStream(0);
+ }
+
+ @Override
+ public OutputStream openOutputStream(long pos) throws PersistException {
+ Method m = support().mBLOB_getBinaryOutputStream;
+
+ if (m == null) {
+ return super.openOutputStream(pos);
+ }
+
+ try {
+ return (OutputStream) m.invoke(getInternalBlobForPersist(), pos);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ @Override
+ public OutputStream openOutputStream(long pos, int bufferSize) throws PersistException {
+ return openOutputStream(pos);
+ }
+
+ @Override
+ public void setLength(long length) throws PersistException {
+ // FIXME: Add special code to support increasing length
+
+ Method m = support().mBLOB_trim;
+
+ if (m == null) {
+ super.setLength(length);
+ return;
+ }
+
+ try {
+ m.invoke(getInternalBlobForPersist(), length);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ private OracleSupportStrategy support() {
+ return (OracleSupportStrategy) mRepo.getSupportStrategy();
+ }
+}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleClob.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleClob.java new file mode 100644 index 0000000..573a3ed --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleClob.java @@ -0,0 +1,137 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.io.Reader;
+import java.io.Writer;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.sql.Clob;
+import java.sql.SQLException;
+
+import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.PersistException;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class OracleClob extends JDBCClob {
+ OracleClob(JDBCRepository repo, Clob clob, JDBCClobLoader loader) {
+ super(repo, clob, loader);
+ }
+
+ @Override
+ public Reader openReader() throws FetchException {
+ return openReader(0);
+ }
+
+ @Override
+ public Reader openReader(long pos) throws FetchException {
+ Method m = support().mCLOB_getCharacterStream;
+
+ if (m == null) {
+ return super.openReader(pos);
+ }
+
+ try {
+ return (Reader) m.invoke(getInternalClobForFetch(), pos);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toFetchException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toFetchException(e);
+ }
+ }
+
+ @Override
+ public Reader openReader(long pos, int bufferSize) throws FetchException {
+ return openReader(pos);
+ }
+
+ @Override
+ public long getLength() throws FetchException {
+ Method m = support().mCLOB_length;
+
+ if (m == null) {
+ return super.getLength();
+ }
+
+ try {
+ return (Long) m.invoke(getInternalClobForFetch());
+ } catch (InvocationTargetException e) {
+ throw mRepo.toFetchException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toFetchException(e);
+ }
+ }
+
+ @Override
+ public Writer openWriter() throws PersistException {
+ return openWriter(0);
+ }
+
+ @Override
+ public Writer openWriter(long pos) throws PersistException {
+ Method m = support().mCLOB_getCharacterOutputStream;
+
+ if (m == null) {
+ return super.openWriter(pos);
+ }
+
+ try {
+ return (Writer) m.invoke(getInternalClobForPersist(), pos);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ @Override
+ public Writer openWriter(long pos, int bufferSize) throws PersistException {
+ return openWriter(pos);
+ }
+
+ @Override
+ public void setLength(long length) throws PersistException {
+ // FIXME: Add special code to support increasing length
+
+ Method m = support().mCLOB_trim;
+
+ if (m == null) {
+ super.setLength(length);
+ return;
+ }
+
+ try {
+ m.invoke(getInternalClobForPersist(), length);
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ private OracleSupportStrategy support() {
+ return (OracleSupportStrategy) mRepo.getSupportStrategy();
+ }
+}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java new file mode 100644 index 0000000..6f3ff4a --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java @@ -0,0 +1,50 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.sql.SQLException;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class OracleExceptionTransformer extends JDBCExceptionTransformer {
+ public static int UNIQUE_CONSTRAINT_VIOLATION = 1;
+
+ public static int INSUFFICIENT_PRIVILEGES = 1031;
+
+ public boolean isUniqueConstraintError(SQLException e) {
+ if (isConstraintError(e)) {
+ String sqlstate = e.getSQLState();
+ int errorCode = e.getErrorCode();
+ return UNIQUE_CONSTRAINT_VIOLATION == errorCode
+ || SQLSTATE_UNIQUE_CONSTRAINT_VIOLATION.equals(sqlstate);
+ }
+ return false;
+ }
+
+ public boolean isInsufficientPrivilegesError(SQLException e) {
+ if (e != null) {
+ int errorCode = e.getErrorCode();
+ return INSUFFICIENT_PRIVILEGES == errorCode;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java new file mode 100644 index 0000000..cb7fe51 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleSupportStrategy.java @@ -0,0 +1,381 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.io.IOException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+
+import org.apache.commons.logging.LogFactory;
+
+import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.PersistException;
+import com.amazon.carbonado.Transaction;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+class OracleSupportStrategy extends JDBCSupportStrategy {
+ private static final int LOB_CHUNK_LIMIT = 4000;
+
+ private static final String PLAN_TABLE_NAME = "TEMP_CARBONADO_PLAN_TABLE";
+
+ final Method mBLOB_empty_lob;
+ final Method mBLOB_getBinaryStream;
+ final Method mBLOB_length;
+ final Method mBLOB_getBinaryOutputStream;
+ final Method mBLOB_trim;
+
+ final Method mCLOB_empty_lob;
+ final Method mCLOB_getCharacterStream;
+ final Method mCLOB_length;
+ final Method mCLOB_getCharacterOutputStream;
+ final Method mCLOB_trim;
+
+ protected OracleSupportStrategy(JDBCRepository repo) {
+ super(repo);
+
+ // Access all the custom oracle.sql.BLOB methods via reflection.
+ {
+ Method blob_empty_lob = null;
+ Method blob_getBinaryStream = null;
+ Method blob_length = null;
+ Method blob_getBinaryOutputStream = null;
+ Method blob_trim = null;
+
+ try {
+ Class blobClass = Class.forName("oracle.sql.BLOB");
+
+ blob_empty_lob = blobClass.getMethod("empty_lob");
+ blob_getBinaryStream = blobClass.getMethod("getBinaryStream", long.class);
+ blob_length = blobClass.getMethod("length");
+ blob_getBinaryOutputStream =
+ blobClass.getMethod("getBinaryOutputStream", long.class);
+ blob_trim = blobClass.getMethod("trim", long.class);
+ } catch (ClassNotFoundException e) {
+ LogFactory.getLog(getClass()).warn("Unable to find Oracle BLOB class", e);
+ } catch (NoSuchMethodException e) {
+ LogFactory.getLog(getClass()).warn("Unable to find Oracle BLOB method", e);
+ }
+
+ mBLOB_empty_lob = blob_empty_lob;
+ mBLOB_getBinaryStream = blob_getBinaryStream;
+ mBLOB_length = blob_length;
+ mBLOB_getBinaryOutputStream = blob_getBinaryOutputStream;
+ mBLOB_trim = blob_trim;
+ }
+
+ // Access all the custom oracle.sql.CLOB methods via reflection.
+ {
+ Method clob_empty_lob = null;
+ Method clob_getCharacterStream = null;
+ Method clob_length = null;
+ Method clob_getCharacterOutputStream = null;
+ Method clob_trim = null;
+
+ try {
+ Class clobClass = Class.forName("oracle.sql.CLOB");
+
+ clob_empty_lob = clobClass.getMethod("empty_lob");
+ clob_getCharacterStream = clobClass.getMethod("getCharacterStream", long.class);
+ clob_length = clobClass.getMethod("length");
+ clob_getCharacterOutputStream =
+ clobClass.getMethod("getCharacterOutputStream", long.class);
+ clob_trim = clobClass.getMethod("trim", long.class);
+ } catch (ClassNotFoundException e) {
+ LogFactory.getLog(getClass()).warn("Unable to find Oracle CLOB class", e);
+ } catch (NoSuchMethodException e) {
+ LogFactory.getLog(getClass()).warn("Unable to find Oracle CLOB method", e);
+ }
+
+ mCLOB_empty_lob = clob_empty_lob;
+ mCLOB_getCharacterStream = clob_getCharacterStream;
+ mCLOB_length = clob_length;
+ mCLOB_getCharacterOutputStream = clob_getCharacterOutputStream;
+ mCLOB_trim = clob_trim;
+ }
+ }
+
+ @Override
+ JDBCExceptionTransformer createExceptionTransformer() {
+ return new OracleExceptionTransformer();
+ }
+
+ @Override
+ String createSequenceQuery(String sequenceName) {
+ return new StringBuilder(25 + sequenceName.length())
+ .append("SELECT ").append(sequenceName).append(".NEXTVAL FROM DUAL")
+ .toString();
+ }
+
+ @Override
+ JDBCBlob convertBlob(java.sql.Blob blob, JDBCBlobLoader loader) {
+ return new OracleBlob(mRepo, blob, loader);
+ }
+
+ @Override
+ JDBCClob convertClob(java.sql.Clob clob, JDBCClobLoader loader) {
+ return new OracleClob(mRepo, clob, loader);
+ }
+
+ /**
+ * @return original blob if too large and post-insert update is required, null otherwise
+ * @throws PersistException instead of FetchException since this code is
+ * called during an insert operation
+ */
+ @Override
+ com.amazon.carbonado.lob.Blob setBlobValue(PreparedStatement ps, int column,
+ com.amazon.carbonado.lob.Blob blob)
+ throws PersistException
+ {
+ try {
+ long length = blob.getLength();
+ if (length > LOB_CHUNK_LIMIT || ((long) ((int) length)) != length) {
+ if (mBLOB_empty_lob == null) {
+ return super.setBlobValue(ps, column, blob);
+ }
+
+ try {
+ ps.setBlob(column, (java.sql.Blob) mBLOB_empty_lob.invoke(null));
+ return blob;
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ if (blob instanceof OracleBlob) {
+ ps.setBlob(column, ((OracleBlob) blob).getInternalBlobForPersist());
+ return null;
+ }
+
+ ps.setBinaryStream(column, blob.openInputStream(), (int) length);
+ return null;
+ } catch (SQLException e) {
+ throw mRepo.toPersistException(e);
+ } catch (FetchException e) {
+ throw e.toPersistException();
+ }
+ }
+
+ /**
+ * @return original clob if too large and post-insert update is required, null otherwise
+ */
+ @Override
+ com.amazon.carbonado.lob.Clob setClobValue(PreparedStatement ps, int column,
+ com.amazon.carbonado.lob.Clob clob)
+ throws PersistException
+ {
+ try {
+ long length = clob.getLength();
+ if (length > LOB_CHUNK_LIMIT || ((long) ((int) length)) != length) {
+ if (mCLOB_empty_lob == null) {
+ return super.setClobValue(ps, column, clob);
+ }
+
+ try {
+ ps.setClob(column, (java.sql.Clob) mCLOB_empty_lob.invoke(null));
+ return clob;
+ } catch (InvocationTargetException e) {
+ throw mRepo.toPersistException(e.getCause());
+ } catch (Exception e) {
+ throw mRepo.toPersistException(e);
+ }
+ }
+
+ if (clob instanceof OracleClob) {
+ ps.setClob(column, ((OracleClob) clob).getInternalClobForPersist());
+ return null;
+ }
+
+ ps.setCharacterStream(column, clob.openReader(), (int) length);
+ return null;
+ } catch (SQLException e) {
+ throw mRepo.toPersistException(e);
+ } catch (FetchException e) {
+ throw e.toPersistException();
+ }
+ }
+
+ /* FIXME
+ @Override
+ boolean printPlan(Appendable app, int indentLevel, String statement)
+ throws FetchException, IOException
+ {
+ Transaction txn = mRepo.enterTransaction();
+ try {
+ Connection con = mRepo.getConnection();
+ try {
+ try {
+ return printPlan(app, indentLevel, statement, con);
+ } catch (SQLException e) {
+ throw mRepo.toFetchException(e);
+ }
+ } finally {
+ mRepo.yieldConnection(con);
+ }
+ } finally {
+ try {
+ txn.exit();
+ } catch (PersistException e) {
+ // I don't care.
+ }
+ }
+ }
+
+ private boolean printPlan(Appendable app, int indentLevel, String statement, Connection con)
+ throws SQLException, IOException
+ {
+ preparePlanTable(con);
+
+ String explainPlanStatement =
+ "EXPLAIN PLAN INTO " + PLAN_TABLE_NAME + " FOR " +
+ statement;
+
+ Statement st = con.createStatement();
+ try {
+ st.execute(explainPlanStatement);
+ } finally {
+ st.close();
+ }
+
+ st = con.createStatement();
+ try {
+ String planStatement =
+ "SELECT LEVEL, OPERATION, OPTIONS, OBJECT_NAME, CARDINALITY, BYTES, COST " +
+ "FROM " + PLAN_TABLE_NAME + " " +
+ "START WITH ID=0 " +
+ "CONNECT BY PRIOR ID = PARENT_ID " +
+ "AND PRIOR NVL(STATEMENT_ID, ' ') = NVL(STATEMENT_ID, ' ') " +
+ "AND PRIOR TIMESTAMP <= TIMESTAMP " +
+ "ORDER BY ID, POSITION";
+
+ ResultSet rs = st.executeQuery(planStatement);
+ try {
+ while (rs.next()) {
+ BaseQuery.indent(app, indentLevel + (rs.getInt(1) - 1) * 2);
+
+ app.append(rs.getString(2));
+ String options = rs.getString(3);
+ if (options != null && options.length() > 0) {
+ app.append(" (");
+ app.append(options);
+ app.append(')');
+ }
+
+ String name = rs.getString(4);
+ if (name != null && name.length() > 0) {
+ app.append(' ');
+ app.append(name);
+ }
+
+ app.append(" {");
+
+ String[] extraNames = {
+ "rows", "CARDINALITY",
+ "bytes", "BYTES",
+ "cost", "COST",
+ };
+
+ boolean comma = false;
+ for (int i=0; i<extraNames.length; i+=2) {
+ String str = rs.getString(extraNames[i + 1]);
+ if (str != null && str.length() > 0) {
+ if (comma) {
+ app.append(", ");
+ }
+ app.append(extraNames[i]);
+ app.append('=');
+ app.append(str);
+ comma = true;
+ }
+ }
+
+ app.append('}');
+ app.append('\n');
+ }
+ } finally {
+ rs.close();
+ }
+ } finally {
+ st.close();
+ }
+
+ return true;
+ }
+
+ private void preparePlanTable(Connection con) throws SQLException {
+ Statement st = con.createStatement();
+ try {
+ // TODO: Is there a better way to check if a table exists?
+ st.execute("SELECT COUNT(*) FROM " + PLAN_TABLE_NAME);
+ return;
+ } catch (SQLException e) {
+ // Assume table doesn't exist, so create it.
+ } finally {
+ st.close();
+ }
+
+ String statement =
+ "CREATE GLOBAL TEMPORARY TABLE " + PLAN_TABLE_NAME + " (" +
+ "STATEMENT_ID VARCHAR2(30)," +
+ "TIMESTAMP DATE," +
+ "REMARKS VARCHAR2(80)," +
+ "OPERATION VARCHAR2(30)," +
+ "OPTIONS VARCHAR2(30)," +
+ "OBJECT_NODE VARCHAR2(128)," +
+ "OBJECT_OWNER VARCHAR2(30)," +
+ "OBJECT_NAME VARCHAR2(30)," +
+ "OBJECT_INSTANCE NUMBER(38)," +
+ "OBJECT_TYPE VARCHAR2(30)," +
+ "OPTIMIZER VARCHAR2(255)," +
+ "SEARCH_COLUMNS NUMBER," +
+ "ID NUMBER(38)," +
+ "PARENT_ID NUMBER(38)," +
+ "POSITION NUMBER(38)," +
+ "COST NUMBER(38)," +
+ "CARDINALITY NUMBER(38)," +
+ "BYTES NUMBER(38)," +
+ "OTHER_TAG VARCHAR2(255)," +
+ "PARTITION_START VARCHAR2(255)," +
+ "PARTITION_STOP VARCHAR2(255)," +
+ "PARTITION_ID NUMBER(38),"+
+ "OTHER LONG," +
+ "DISTRIBUTION VARCHAR2(30)" +
+ ")";
+
+ st = con.createStatement();
+ try {
+ st.execute(statement);
+ } finally {
+ st.close();
+ }
+ }
+ */
+}
|