1.1 --- a/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcMultivaluedIndex.java Sat Nov 27 22:16:17 2004 +0000
1.2 +++ b/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcMultivaluedIndex.java Sun Nov 28 06:38:58 2004 +0000
1.3 @@ -30,9 +30,12 @@
1.4 class JdbcMultivaluedIndex
1.5 extends JdbcIndex implements MultivaluedIndex
1.6 {
1.7 + protected boolean queryDuplicates;
1.8 +
1.9 protected LazyPreparedStatement sqlDeleteWithValue;
1.10 protected LazyPreparedStatement sqlDeleteWithSurrogate;
1.11 protected LazyPreparedStatement sqlFindCount;
1.12 + protected LazyPreparedStatement sqlFindCountWithValue;
1.13 protected LazyPreparedStatement sqlFindSurrogate;
1.14
1.15 protected void defineSql()
1.16 @@ -53,6 +56,11 @@
1.17 "select count(*) from " + tableName
1.18 + " where " + keyColName + " = ?");
1.19
1.20 + sqlFindCountWithValue = new LazyPreparedStatement(
1.21 + "select count(*) from " + tableName
1.22 + + " where " + keyColName + " = ?"
1.23 + + " and " + valColName + " = ?");
1.24 +
1.25 sqlFindSurrogate = new LazyPreparedStatement(
1.26 "select " + JdbcStorage.SURROGATE_COL_NAME
1.27 + " from " + tableName
1.28 @@ -83,6 +91,20 @@
1.29 return !needSurrogate;
1.30 }
1.31
1.32 + // override JdbcIndex
1.33 + public void add(Object key, Object value) throws StorageException
1.34 + {
1.35 + if (queryDuplicates) {
1.36 + int n = storage.getSingletonInt(
1.37 + sqlFindCountWithValue,
1.38 + new Object [] { key, value } );
1.39 + if (n > 0) {
1.40 + throw new StorageBadRequestException("duplicate detected");
1.41 + }
1.42 + }
1.43 + addImpl(key, value);
1.44 + }
1.45 +
1.46 // implement MultivaluedIndex
1.47 public boolean remove(Object key, Object value) throws StorageException
1.48 {
2.1 --- a/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcStorage.java Sat Nov 27 22:16:17 2004 +0000
2.2 +++ b/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcStorage.java Sun Nov 28 06:38:58 2004 +0000
2.3 @@ -57,6 +57,10 @@
2.4
2.5 private final boolean realSchema;
2.6
2.7 + private final boolean debugPrint;
2.8 +
2.9 + private final boolean queryDuplicates;
2.10 +
2.11 private final Map entryTypeToDataTypeMap;
2.12
2.13 private Statement jdbcStmt;
2.14 @@ -110,6 +114,15 @@
2.15 throw new StorageBadRequestException(ex.toString());
2.16 }
2.17 }
2.18 + debugPrint = getBooleanProperty(
2.19 + properties,
2.20 + JdbcStorageFactory.STORAGE_DEBUG_PRINT,
2.21 + false);
2.22 + queryDuplicates = getBooleanProperty(
2.23 + properties,
2.24 + JdbcStorageFactory.STORAGE_QUERY_DUPLICATES,
2.25 + false);
2.26 +
2.27 boolean success = false;
2.28
2.29 try {
2.30 @@ -124,7 +137,7 @@
2.31 idQuote = dbMetaData.getIdentifierQuoteString();
2.32 success = true;
2.33 } catch (SQLException ex) {
2.34 - throw new JdbcStorageException(ex);
2.35 + throw newJdbcException(ex);
2.36 } finally {
2.37 if (!success) {
2.38 rollbackConnection();
2.39 @@ -133,6 +146,26 @@
2.40 }
2.41 }
2.42
2.43 + private static boolean getBooleanProperty(
2.44 + Properties properties,
2.45 + String propName,
2.46 + boolean defaultValue)
2.47 + {
2.48 + String value = properties.getProperty(propName);
2.49 + if (value == null) {
2.50 + return defaultValue;
2.51 + }
2.52 + return value.equalsIgnoreCase("true");
2.53 + }
2.54 +
2.55 + private JdbcStorageException newJdbcException(SQLException ex)
2.56 + {
2.57 + if (debugPrint) {
2.58 + ex.printStackTrace();
2.59 + }
2.60 + return new JdbcStorageException(ex);
2.61 + }
2.62 +
2.63 private void createTypeMap(Properties properties)
2.64 {
2.65 entryTypeToDataTypeMap.put(
2.66 @@ -356,7 +389,7 @@
2.67 jdbcConnection.commit();
2.68 } catch (SQLException ex) {
2.69 rollbackConnection();
2.70 - throw new JdbcStorageException(ex);
2.71 + throw newJdbcException(ex);
2.72 }
2.73 }
2.74
2.75 @@ -379,7 +412,7 @@
2.76 openImpl();
2.77 loadPrimaryIndex();
2.78 } catch (SQLException ex) {
2.79 - throw new JdbcStorageException(ex);
2.80 + throw newJdbcException(ex);
2.81 }
2.82 }
2.83
2.84 @@ -611,7 +644,7 @@
2.85 // NOTE: could use just (KEY,ORDINAL) as primary key.
2.86 // However, we have to be able to modify ordinals, and even
2.87 // PostgreSQL doesn't get the deferred constraint
2.88 - // enforcement right in that case). So, throw in both the
2.89 + // enforcement right in that case. So, throw in both the
2.90 // ORDINAL and the SURROGATE so that ORDER BY can use the
2.91 // index.
2.92 sb.append(",");
2.93 @@ -625,7 +658,7 @@
2.94 sb.append(")");
2.95 jdbcStmt.execute(sb.toString());
2.96 } catch (SQLException ex) {
2.97 - throw new JdbcStorageException(ex);
2.98 + throw newJdbcException(ex);
2.99 }
2.100 }
2.101
2.102 @@ -687,6 +720,9 @@
2.103 } else {
2.104 index = new JdbcMultivaluedIndex();
2.105 }
2.106 + if (queryDuplicates && !needSurrogate) {
2.107 + ((JdbcMultivaluedIndex) index).queryDuplicates = true;
2.108 + }
2.109 }
2.110 index.init(
2.111 this,
2.112 @@ -696,7 +732,7 @@
2.113 nameToIndexMap.put(name,index);
2.114 return index;
2.115 } catch (SQLException ex) {
2.116 - throw new JdbcStorageException(ex);
2.117 + throw newJdbcException(ex);
2.118 } finally {
2.119 closeResultSet();
2.120 closePreparedStatement(ps);
2.121 @@ -742,7 +778,7 @@
2.122 try {
2.123 jdbcStmt.execute("drop table "+getTableNameForIndex(name));
2.124 } catch (SQLException ex) {
2.125 - throw new JdbcStorageException(ex);
2.126 + throw newJdbcException(ex);
2.127 }
2.128 nameToIndexMap.remove(name);
2.129 }
2.130 @@ -771,7 +807,7 @@
2.131 }
2.132 jdbcConnection.commit();
2.133 } catch (SQLException ex) {
2.134 - throw new JdbcStorageException(ex);
2.135 + throw newJdbcException(ex);
2.136 }
2.137 }
2.138
2.139 @@ -784,7 +820,7 @@
2.140 }
2.141 jdbcConnection.rollback();
2.142 } catch (SQLException ex) {
2.143 - throw new JdbcStorageException(ex);
2.144 + throw newJdbcException(ex);
2.145 }
2.146 if (primaryIndex != null) {
2.147 primaryIndex.shutDown();
2.148 @@ -822,7 +858,7 @@
2.149 lps.ps = ps;
2.150 return ps;
2.151 } catch (SQLException ex) {
2.152 - throw new JdbcStorageException(ex);
2.153 + throw newJdbcException(ex);
2.154 }
2.155 }
2.156
2.157 @@ -905,7 +941,7 @@
2.158 }
2.159 return list.listIterator();
2.160 } catch (SQLException ex) {
2.161 - throw new JdbcStorageException(ex);
2.162 + throw newJdbcException(ex);
2.163 }
2.164 }
2.165
2.166 @@ -927,7 +963,7 @@
2.167 closeResultSet();
2.168 }
2.169 } catch (SQLException ex) {
2.170 - throw new JdbcStorageException(ex);
2.171 + throw newJdbcException(ex);
2.172 }
2.173 }
2.174
2.175 @@ -950,7 +986,7 @@
2.176 closeResultSet();
2.177 }
2.178 } catch (SQLException ex) {
2.179 - throw new JdbcStorageException(ex);
2.180 + throw newJdbcException(ex);
2.181 }
2.182 }
2.183
2.184 @@ -1005,7 +1041,7 @@
2.185 bindArgs(ps,args);
2.186 return ps.executeUpdate();
2.187 } catch (SQLException ex) {
2.188 - throw new JdbcStorageException(ex);
2.189 + throw newJdbcException(ex);
2.190 }
2.191 }
2.192 }
3.1 --- a/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcStorageFactory.java Sat Nov 27 22:16:17 2004 +0000
3.2 +++ b/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/JdbcStorageFactory.java Sun Nov 28 06:38:58 2004 +0000
3.3 @@ -51,6 +51,12 @@
3.4 public static final String STORAGE_FIRST_SERIAL_NUMBER =
3.5 PROPERTY_PREFIX + "firstSerialNumber";
3.6
3.7 + public static final String STORAGE_DEBUG_PRINT =
3.8 + PROPERTY_PREFIX + "debugPrint";
3.9 +
3.10 + public static final String STORAGE_QUERY_DUPLICATES =
3.11 + PROPERTY_PREFIX + "queryDuplicates";
3.12 +
3.13 public static final String STORAGE_DATATYPE_MOFID =
3.14 PROPERTY_PREFIX + "datatype.mofid";
3.15
4.1 --- a/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/package.html Sat Nov 27 22:16:17 2004 +0000
4.2 +++ b/mdr/extras/jdbcstorage/src/org/netbeans/mdr/persistence/jdbcimpl/package.html Sun Nov 28 06:38:58 2004 +0000
4.3 @@ -65,11 +65,37 @@
4.4 <li>MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.password =
4.5 password corresponding to userName
4.6
4.7 +<li>MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.queryDuplicates
4.8 += true to force JdbcStorage to issue pre-updated queries to detect
4.9 +duplicates in unique indexes (instead of letting the DBMS do the job
4.10 +during update). This must be enabled for databases such as PostgreSQL
4.11 +(pre-1.7.5) without proper subtransaction support. It should be left
4.12 +disabled for all others since it adds a performance penalty.
4.13 +
4.14 +<li>MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.firstSerialNumber
4.15 += lowest MOFID serial number to assign. When federating multiple
4.16 +storages, this can be used to prevent conflicts by partitioning the
4.17 +MOFID space into non-overlapping ranges. This parameter only takes
4.18 +effect when the storage is initially created; the value can be either
4.19 +decimal, hexadecimal, or octal as interpreted by {@link
4.20 +java.lang.Long#decode}.
4.21 +
4.22 +<li>MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.debugPrint
4.23 += true to request that whenever an SQLException is caught and
4.24 +rethrown, the error message and its stack trace will be printed to
4.25 +standard error. Sometimes exception messages get swallowed by upper
4.26 +layers of MDR, so this can be useful for debugging configuration
4.27 +problems. However, the output can be misleading, because some valid
4.28 +exceptions thrown from the storage layer (e.g. uniqueness violation)
4.29 +are caught and handled by MDR.
4.30 +
4.31 +</ul>
4.32 +
4.33 +<p>
4.34 +
4.35 The next section defines additional parameters affecting
4.36 DBMS-specific usage of SQL.
4.37
4.38 -</ul>
4.39 -
4.40 <h3>Index to Table Mapping</h3>
4.41
4.42 JdbcStorage creates one table per MDR index. It also creates one
4.43 @@ -220,13 +246,13 @@
4.44 <li>
4.45 The StorageId prefix "j" is used for all MOFID's, and all MOFID's
4.46 stored via JdbcStorage must have this prefix. MOFID's are stored as
4.47 -integer serial numbers with no prefix. This means a JdbcStorage-based
4.48 -repository cannot be used for federation of any kind. For some
4.49 -applications, this may be acceptable, and using integers for keys is
4.50 -generally good for SQL performance. Probably we should allow the user
4.51 -a choice on a per-storage basis: either store MOFID's as integers and
4.52 -disallow federation, or store MOFID's as strings or byte arrays and
4.53 -allow federation (factoring out some commonality from btreeimpl).
4.54 +integer serial numbers with no prefix. This makes JdbcStorage-based
4.55 +federation difficult. For some applications, this may be acceptable,
4.56 +and using integers for keys is generally good for SQL performance.
4.57 +Probably we should allow the user a choice on a per-storage basis:
4.58 +either store MOFID's as integers and disallow federation, or store
4.59 +MOFID's as strings or byte arrays and allow federation (factoring out
4.60 +some commonality from btreeimpl).
4.61
4.62 <li>
4.63 Caching for non-primary indexes is probably required for acceptable