You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-dev@db.apache.org by tf...@apache.org on 2013/12/27 23:40:45 UTC
svn commit: r1553756 - in /db/torque/torque4/trunk:
torque-runtime/src/main/java/org/apache/torque/oid/
torque-runtime/src/main/java/org/apache/torque/util/
torque-test/src/test/java/org/apache/torque/generated/peer/
Author: tfischer
Date: Fri Dec 27 22:40:44 2013
New Revision: 1553756
URL: http://svn.apache.org/r1553756
Log:
TORQUE-305 fix insert into ... select statements when primary key is not given and sequences are used to generate primary keys
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
db/torque/torque4/trunk/torque-test/src/test/java/org/apache/torque/generated/peer/DoInsertTest.java
Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java?rev=1553756&r1=1553755&r2=1553756&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java Fri Dec 27 22:40:44 2013
@@ -73,7 +73,7 @@ public abstract class AbstractIdGenerato
*
* @throws TorqueException if a database error occurs.
*/
- public int getIdAsInt(Connection connection, Object keyInfo)
+ public int getIdAsInt(final Connection connection, final Object keyInfo)
throws TorqueException
{
return getId(connection, keyInfo, new IntegerMapper());
@@ -89,7 +89,7 @@ public abstract class AbstractIdGenerato
*
* @throws TorqueException if a database error occurs.
*/
- public long getIdAsLong(Connection connection, Object keyInfo)
+ public long getIdAsLong(final Connection connection, final Object keyInfo)
throws TorqueException
{
return getId(connection, keyInfo, new LongMapper());
@@ -105,7 +105,7 @@ public abstract class AbstractIdGenerato
*
* @throws TorqueException if a database error occurs.
*/
- public BigDecimal getIdAsBigDecimal(Connection connection, Object keyInfo)
+ public BigDecimal getIdAsBigDecimal(final Connection connection, final Object keyInfo)
throws TorqueException
{
return getId(connection, keyInfo, new BigDecimalMapper());
@@ -122,7 +122,7 @@ public abstract class AbstractIdGenerato
*
* @throws TorqueException if a database error occurs.
*/
- public String getIdAsString(Connection connection, Object keyInfo)
+ public String getIdAsString(final Connection connection, final Object keyInfo)
throws TorqueException
{
return getId(connection, keyInfo, new StringMapper());
@@ -159,21 +159,36 @@ public abstract class AbstractIdGenerato
* appropriate java object.
*
* @return The generated id.
- * @exception TorqueException if a database error occurs.
+ * @throws TorqueException if a database error occurs.
*/
protected <T> T getId(
- Connection connection,
- Object keyInfo,
- RecordMapper<T> mapper)
+ final Connection connection,
+ final Object keyInfo,
+ final RecordMapper<T> mapper)
throws TorqueException
{
- String tableName = SqlBuilder.getFullTableName(
- String.valueOf(keyInfo),
- databaseName);
- String idSql = adapter.getIDMethodSQL(tableName);
+ String idSql = getIdSql(keyInfo);
BasePeerImpl<T> peer = new BasePeerImpl<T>(mapper, null, databaseName);
List<T> result = peer.doSelect(idSql, connection);
return result.get(0);
}
+
+ /**
+ * Returns the SQL to retrieve the next id.
+ *
+ * @param keyInfo an Object that contains additional info.
+ *
+ * @return the SQL to retrieve the next id.
+ *
+ * @throws TorqueException
+ */
+ public String getIdSql(final Object keyInfo) throws TorqueException
+ {
+ String tableName = SqlBuilder.getFullTableName(
+ String.valueOf(keyInfo),
+ databaseName);
+ String idSql = adapter.getIDMethodSQL(tableName);
+ return idSql;
+ }
}
Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java?rev=1553756&r1=1553755&r2=1553756&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java Fri Dec 27 22:40:44 2013
@@ -35,6 +35,7 @@ import org.apache.commons.lang.StringUti
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.torque.Column;
+import org.apache.torque.ColumnImpl;
import org.apache.torque.Database;
import org.apache.torque.TooManyRowsException;
import org.apache.torque.Torque;
@@ -48,6 +49,7 @@ import org.apache.torque.map.ColumnMap;
import org.apache.torque.map.MapHelper;
import org.apache.torque.map.TableMap;
import org.apache.torque.oid.IdGenerator;
+import org.apache.torque.oid.SequenceIdGenerator;
import org.apache.torque.om.NumberKey;
import org.apache.torque.om.ObjectKey;
import org.apache.torque.om.SimpleKey;
@@ -636,7 +638,8 @@ public class BasePeerImpl<T> implements
/**
* Executes a insert into...select statement.
*
- * @param toInsertInto the columns in which to insert, not null.
+ * @param toInsertInto the columns in which to insert, not null,
+ * must not contain null.
* @param criteria the criteria which selects the values to insert,
* not null.
* @param dbName the database name, or null to take the database name
@@ -654,15 +657,74 @@ public class BasePeerImpl<T> implements
final Connection connection)
throws TorqueException
{
- if (dbName == null)
+ if (dbName == null)
{
dbName = getDatabaseName();
}
+ ColumnMap pk = getTableMap().getPrimaryKey();
+ boolean pkExistsInColumnMap = false;
+
List<String> columnNames = new ArrayList<String>();
for (Column column : toInsertInto)
{
columnNames.add(column.getColumnName());
+ if (pk != null
+ && column.getSqlExpression().equals(pk.getSqlExpression()))
+ {
+ pkExistsInColumnMap = true;
+ }
+ }
+ if (!pkExistsInColumnMap)
+ {
+ IDMethod idMethod = getTableMap().getPrimaryKeyMethod();
+ Adapter adapter = Torque.getAdapter(dbName);
+ if (idMethod == IDMethod.ID_BROKER)
+ {
+ log.debug("pk does not exist in column map and id method is "
+ + idMethod
+ + ", SQL will fail if column has no default value");
+ // try SQL, maybe database has a default value set
+ }
+ else if (idMethod == IDMethod.SEQUENCE
+ || (idMethod == IDMethod.NATIVE
+ && adapter.getIDMethodType() == IDMethod.SEQUENCE))
+ {
+ IdGenerator keyGen = Torque.getDatabase(dbName).getIdGenerator(
+ getTableMap().getPrimaryKeyMethod());
+ if (keyGen instanceof SequenceIdGenerator)
+ {
+ SequenceIdGenerator sequenceIdGenerator
+ = (SequenceIdGenerator) keyGen;
+ String idSql = sequenceIdGenerator.getIdSql(
+ getIdMethodInfo());
+ // This is a bit of a hack.
+ // The idSql is usually a stand-alone statement, but we
+ // need the part to be inserted as a column.
+ // Therefore we extract the complete word containing
+ // the term nextval
+ int nextvalPos = idSql.toLowerCase().indexOf("nextval");
+ int spacePos = idSql.lastIndexOf(" ", nextvalPos);
+ if (spacePos != -1)
+ {
+ idSql = idSql.substring(spacePos + 1);
+ }
+ spacePos = idSql.indexOf(" ");
+ if (spacePos != -1)
+ {
+ idSql = idSql.substring(0, idSql.indexOf(" "));
+ }
+ columnNames.add(pk.getColumnName());
+ criteria.addSelectColumn(
+ new ColumnImpl(null, null, null, idSql));
+ }
+ else
+ {
+ log.warn("id method is sequence "
+ + "but keyGen is no Sequence id generator, "
+ + "cannot add sequence generation info");
+ }
+ }
}
String fullTableName = SqlBuilder.getFullTableName(
Modified: db/torque/torque4/trunk/torque-test/src/test/java/org/apache/torque/generated/peer/DoInsertTest.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-test/src/test/java/org/apache/torque/generated/peer/DoInsertTest.java?rev=1553756&r1=1553755&r2=1553756&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-test/src/test/java/org/apache/torque/generated/peer/DoInsertTest.java (original)
+++ db/torque/torque4/trunk/torque-test/src/test/java/org/apache/torque/generated/peer/DoInsertTest.java Fri Dec 27 22:40:44 2013
@@ -23,13 +23,19 @@ import java.math.BigDecimal;
import java.sql.Types;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.torque.BaseDatabaseTestCase;
+import org.apache.torque.Column;
import org.apache.torque.ColumnImpl;
+import org.apache.torque.adapter.IDMethod;
import org.apache.torque.criteria.Criteria;
import org.apache.torque.om.ObjectKey;
import org.apache.torque.test.dbobject.Author;
+import org.apache.torque.test.dbobject.Book;
import org.apache.torque.test.dbobject.IntegerType;
import org.apache.torque.test.peer.AuthorPeer;
+import org.apache.torque.test.peer.BookPeer;
import org.apache.torque.test.peer.IntegerTypePeer;
import org.apache.torque.util.ColumnValues;
import org.apache.torque.util.JdbcTypedValue;
@@ -43,6 +49,8 @@ public class DoInsertTest extends BaseDa
{
private List<Author> authorList;
+ private static Log log =LogFactory.getLog(DoInsertTest.class);
+
@Override
public void setUp() throws Exception
{
@@ -131,4 +139,120 @@ public class DoInsertTest extends BaseDa
((BigDecimal) objectKey.getValue()).intValue(),
allIntegerTypes.get(0).getId());
}
+
+ /**
+ * Tests the doInsert method where the inserted values are selected
+ * from the table.
+ *
+ * @throws Exception if a database error occurs.
+ */
+ public void testDoInsertWithSelectSingleRecordIdSet()
+ throws Exception
+ {
+ Criteria selectCriteria = new Criteria()
+ .where(AuthorPeer.AUTHOR_ID, authorList.get(0).getAuthorId())
+ .addSelectColumn(new ColumnImpl(
+ AuthorPeer.AUTHOR_ID.getSchemaName(),
+ AuthorPeer.AUTHOR_ID.getTableName(),
+ AuthorPeer.AUTHOR_ID.getColumnName(),
+ AuthorPeer.AUTHOR_ID.getSqlExpression() + " + 100"))
+ .addSelectColumn(AuthorPeer.NAME);
+
+ // execute
+ int numberOfInsertedRows = AuthorPeer.doInsert(
+ new Column[] {AuthorPeer.AUTHOR_ID, AuthorPeer.NAME},
+ selectCriteria);
+
+ // verify
+ assertEquals(1, numberOfInsertedRows);
+ Author author = new Author();
+ author.setAuthorId(authorList.get(0).getAuthorId() + 100);
+ author.setName(authorList.get(0).getName());
+ authorList.add(author);
+ verifyBookstore(authorList);
+ }
+
+ /**
+ * Tests the doInsert method where the inserted values are selected
+ * from the table.
+ *
+ * @throws Exception if a database error occurs.
+ */
+ public void testDoInsertWithSelectSingleRecord()
+ throws Exception
+ {
+ if ( IDMethod.ID_BROKER == AuthorPeer.getTableMap().getPrimaryKeyMethod())
+ {
+ log.warn("Cannot test insert.. select statement with autoincrement"
+ + " id method");
+ return;
+ }
+ Criteria selectCriteria = new Criteria()
+ .where(AuthorPeer.AUTHOR_ID, authorList.get(0).getAuthorId())
+ .addSelectColumn(AuthorPeer.NAME);
+
+ // execute
+ int numberOfInsertedRows = AuthorPeer.doInsert(
+ new Column[] {AuthorPeer.NAME},
+ selectCriteria);
+
+ // verify
+ assertEquals(1, numberOfInsertedRows);
+ Author author = new Author();
+ author.setAuthorId(authorList.get(9).getAuthorId() + 1);
+ author.setName(authorList.get(0).getName());
+ authorList.add(author);
+ verifyBookstore(authorList);
+ }
+
+ /**
+ * Tests the doInsert method where the inserted values are selected
+ * from the table.
+ *
+ * @throws Exception if a database error occurs.
+ */
+ public void testDoInsertWithSelectMultipleRecords()
+ throws Exception
+ {
+ if ( IDMethod.ID_BROKER == AuthorPeer.getTableMap().getPrimaryKeyMethod())
+ {
+ log.warn("Cannot test insert.. select statement with autoincrement"
+ + " id method");
+ return;
+ }
+ Criteria selectCriteria = new Criteria()
+ .where(BookPeer.AUTHOR_ID, authorList.get(0).getAuthorId())
+ .addSelectColumn(BookPeer.TITLE);
+
+ // execute
+ int numberOfInsertedRows = AuthorPeer.doInsert(
+ new Column[] {AuthorPeer.NAME},
+ selectCriteria);
+
+ // verify
+ assertEquals(10, numberOfInsertedRows);
+ List<Author> selectedAuthorList = AuthorPeer.doSelect(new Criteria());
+ // check size of List
+ assertEquals(20, selectedAuthorList.size());
+ for (Author author : selectedAuthorList)
+ {
+ if (author.getAuthorId() > authorList.get(9).getAuthorId())
+ {
+ boolean found = false;
+ for (Book book : authorList.get(0).getBooks())
+ {
+ if (author.getName().equals(book.getTitle()))
+ {
+ found = true;
+ authorList.get(0).getBooks().remove(book);
+ break;
+ }
+ }
+ if (!found)
+ {
+ fail("unexpected author with name " + author.getName());
+ }
+ }
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org