/** * Gives a possibility to patch the Castor-generated SQL statement for INSERT (makes sense for * DURING_INSERT key generators) */ public String patchSQL(String insert, String primKeyName) throws MappingException { StringTokenizer st; String tableName; String seqName; String nextval; StringBuffer sb; int lp1; // the first left parenthesis, which starts fields list int lp2; // the second left parenthesis, which starts values list if (_style == BEFORE_INSERT) { return insert; } // First find the table name st = new StringTokenizer(insert); if (!st.hasMoreTokens() || !st.nextToken().equalsIgnoreCase("INSERT")) { throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert)); } if (!st.hasMoreTokens() || !st.nextToken().equalsIgnoreCase("INTO")) { throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert)); } if (!st.hasMoreTokens()) { throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert)); } tableName = st.nextToken(); // remove every double quote in the tablename int idxQuote = tableName.indexOf('"'); if (idxQuote >= 0) { StringBuffer buffer2 = new StringBuffer(); int pos = 0; do { buffer2.append(tableName.substring(pos, idxQuote)); pos = idxQuote + 1; } while ((idxQuote = tableName.indexOf('"', pos)) != -1); buffer2.append(tableName.substring(pos)); tableName = buffer2.toString(); } seqName = MessageFormat.format( _seqName, new String[] {tableName, primKeyName}); // due to varargs in 1.5, see CASTOR-1097 nextval = _factory.quoteName(seqName + ".nextval"); lp1 = insert.indexOf('('); lp2 = insert.indexOf('(', lp1 + 1); if (lp1 < 0) { throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert)); } sb = new StringBuffer(insert); if (!_triggerPresent) { // if no onInsert triggers in the DB, we have to supply the Key values // manually if (lp2 < 0) { // Only one pk field in the table, the INSERT statement would be // INSERT INTO table VALUES () lp2 = lp1; lp1 = insert.indexOf(" VALUES "); // don't change the order of lines below, // otherwise index becomes invalid sb.insert(lp2 + 1, nextval); sb.insert(lp1 + 1, "(" + _factory.quoteName(primKeyName) + ") "); } else { // don't change the order of lines below, // otherwise index becomes invalid sb.insert(lp2 + 1, nextval + ","); sb.insert(lp1 + 1, _factory.quoteName(primKeyName) + ","); } } if (_style == DURING_INSERT) { // append 'RETURNING primKeyName INTO ?' sb.append(" RETURNING "); sb.append(_factory.quoteName(primKeyName)); sb.append(" INTO ?"); } return sb.toString(); }
/** * @param conn An open connection within the given transaction * @param tableName The table name * @param primKeyName The primary key name * @param props A temporary replacement for Principal object * @return A new key * @throws PersistenceException An error occured talking to persistent storage */ public Object generateKey(Connection conn, String tableName, String primKeyName, Properties props) throws PersistenceException { PreparedStatement stmt = null; ResultSet rs; String seqName; String table; seqName = MessageFormat.format( _seqName, new String[] {tableName, primKeyName}); // due to varargs in 1.5, see CASTOR-1097 table = _factory.quoteName(tableName); try { if (_factory.getFactoryName().equals(InterbaseFactory.FACTORY_NAME)) { // interbase only does before_insert, and does it its own way stmt = conn.prepareStatement( "SELECT gen_id(" + seqName + "," + _increment + ") FROM rdb$database"); rs = stmt.executeQuery(); } else if (_factory.getFactoryName().equals(DB2Factory.FACTORY_NAME)) { stmt = conn.prepareStatement("SELECT nextval FOR " + seqName + " FROM SYSIBM.SYSDUMMY1"); rs = stmt.executeQuery(); } else { if (_style == BEFORE_INSERT) { stmt = conn.prepareStatement("SELECT nextval('" + seqName + "')"); rs = stmt.executeQuery(); } else if (_triggerPresent && _factoryName.equals(PostgreSQLFactory.FACTORY_NAME)) { Object insStmt = props.get("insertStatement"); Class psqlStmtClass = Class.forName("org.postgresql.Statement"); Method getInsertedOID = psqlStmtClass.getMethod("getInsertedOID", (Class[]) null); int insertedOID = ((Integer) getInsertedOID.invoke(insStmt, (Object[]) null)).intValue(); stmt = conn.prepareStatement( "SELECT " + _factory.quoteName(primKeyName) + " FROM " + table + " WHERE OID=?"); stmt.setInt(1, insertedOID); rs = stmt.executeQuery(); } else { stmt = conn.prepareStatement( "SELECT " + _factory.quoteName(seqName + ".currval") + " FROM " + table); rs = stmt.executeQuery(); } } if (!rs.next()) { throw new PersistenceException( Messages.format("persist.keyGenFailed", getClass().getName())); } Object resultKey = null; int resultValue = rs.getInt(1); String resultColName = rs.getMetaData().getColumnName(1); int resultColType = rs.getMetaData().getColumnType(1); if (LOG.isDebugEnabled()) { LOG.debug( "JDBC query returned value " + resultValue + " from column " + resultColName + "/" + resultColType); } if (_sqlType == Types.INTEGER) { resultKey = new Integer(resultValue); } else if (_sqlType == Types.BIGINT) { resultKey = new Long(resultValue); } else if (_sqlType == Types.CHAR || _sqlType == Types.VARCHAR) { resultKey = String.valueOf(resultValue); } else { resultKey = new BigDecimal(resultValue); } if (LOG.isDebugEnabled()) { if (resultKey != null) { LOG.debug( "Returning value " + resultKey + " of type " + resultKey.getClass().getName() + " as key."); } } return resultKey; } catch (Exception ex) { throw new PersistenceException( Messages.format("persist.keyGenSQL", getClass().getName(), ex.toString())); } finally { JDOUtils.closeStatement(stmt); } }