Community
Participate
Working Groups
>Temporary table identifier "#" is converted to parameter "?" in user defined native SQL >Test client (modified from Peter's example) private void nativeQuery() { Query aQuery = null; int version = 3; StringBuffer aBuffer = new StringBuffer(); aBuffer.append("UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = "); aBuffer.append(version + 1); aBuffer.append(" WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = "); aBuffer.append(version); aBuffer.append(") AND (PROCUNIT_ID IN "); aBuffer.append("(SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))"); try { aQuery = getEntityManager().createNativeQuery(aBuffer.toString()); // Convert to delegate when on EE container - otherwise just return same EE EM setEntityManager(JpaHelper.getEntityManager(getEntityManager())); JpaHelper.getDatabaseQuery(aQuery).setIsUserDefined(false); // If container managed TX - do not begin/end as SE if(JpaHelper.isEclipseLink(entityManagerFactory)) { getEntityManager().getTransaction().begin(); } aQuery.executeUpdate(); if(JpaHelper.isEclipseLink(entityManagerFactory)) { getEntityManager().getTransaction().commit(); } } catch (Exception e) { e.printStackTrace(); } } [EL Finer]: 2010-09-13 16:47:49.4--ServerSession(3449340)--Thread(Thread[main,5,main])--client acquired [EL Finest]: 2010-09-13 16:47:49.41--UnitOfWork(32801378)--Thread(Thread[main,5,main])--Execute query DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))") [EL Finer]: 2010-09-13 16:47:49.41--ClientSession(25706868)--Connection(27296482)--Thread(Thread[main,5,main])--begin transaction [EL Warning]: 2010-09-13 16:47:49.41--ClientSession(25706868)--Thread(Thread[main,5,main])--named_argument_not_found_in_query_parameters (There is no English translation for this message.) [EL Fine]: 2010-09-13 16:47:49.41--ClientSession(25706868)--Connection(27296482)--Thread(Thread[main,5,main])--UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?))) bind => [null] [EL Fine]: 2010-09-13 16:47:49.46--ClientSession(25706868)--Thread(Thread[main,5,main])--VALUES(1) [EL Warning]: 2010-09-13 16:47:49.48--UnitOfWork(32801378)--Thread(Thread[main,5,main])--Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "?" at line 1, column 166. >SQLServer 2008 Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Must declare the table variable "@P0". Error Code: 1087 Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?))) bind => [null] Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?)))") at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:797) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:863) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:583) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526) at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:990) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:206) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:192) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:235) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:215) at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:768) at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:675) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2914) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1301) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1283) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1257) at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:534) at org.eclipse.persistence.example.dataparallel.GridClient.nativeQuery(GridClient.java:97) at org.eclipse.persistence.example.dataparallel.GridClient.main(GridClient.java:318) Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Must declare the table variable "@P0". >MySQL 5 [EL Config]: 2010-09-13 16:46:48.837--ServerSession(24561483)--Connection(28399250)--Thread(Thread[main,5,main])--disconnect Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null)))' at line 1 Error Code: 1064 Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?))) bind => [null] Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?)))") at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:797) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:863) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:583) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526) at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:990) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:206) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:192) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:235) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:215) at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:768) at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:675) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2914) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1301) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1283) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1257) at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:534) at org.eclipse.persistence.example.dataparallel.GridClient.nativeQuery(GridClient.java:102) at org.eclipse.persistence.example.dataparallel.GridClient.main(GridClient.java:322) Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null)))' at line 1 >Derby 10.5.3.0 [EL Config]: 2010-09-13 16:47:49.48--ServerSession(3449340)--Connection(27296482)--Thread(Thread[main,5,main])--disconnect Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "?" at line 1, column 166. Error Code: -1 Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?))) bind => [null] Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?)))") at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:683) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526) at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:990) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:206) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:192) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:235) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:215) at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:768) at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:675) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2914) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1301) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1283) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1257) at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:534) at org.eclipse.persistence.example.dataparallel.GridClient.nativeQuery(GridClient.java:102) at org.eclipse.persistence.example.dataparallel.GridClient.main(GridClient.java:322) Caused by: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "?" at line 1, column 166. >Workaround: The suggested workaround below stops the # to ? conversion - this bug will incorporate this change into foundation code JpaHelper.getDatabaseQuery(aQuery).setIsUserDefined(false); >SQLServer (supported) [EL Finest]: 2010-09-13 16:54:41.405--UnitOfWork(7566193)--Thread(Thread[main,5,main])--Execute query DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))") [EL Finer]: 2010-09-13 16:54:41.405--ClientSession(31664352)--Connection(5699121)--Thread(Thread[main,5,main])--begin transaction [EL Fine]: 2010-09-13 16:54:41.405--ClientSession(31664352)--Connection(5699121)--Thread(Thread[main,5,main])--UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT))) [EL Fine]: 2010-09-13 16:54:41.425--ClientSession(31664352)--Thread(Thread[main,5,main])--SELECT 1 [EL Warning]: 2010-09-13 16:54:41.425--UnitOfWork(7566193)--Thread(Thread[main,5,main])--Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name '#DPAR_SPROCUNIT'. Error Code: 208 Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT))) Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))") at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324) >Derby (not supported) [EL Finest]: 2010-09-13 16:53:04.513--UnitOfWork(26596606)--Thread(Thread[main,5,main])--Execute query DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))") [EL Finer]: 2010-09-13 16:53:04.513--ClientSession(19397138)--Connection(11299397)--Thread(Thread[main,5,main])--begin transaction [EL Fine]: 2010-09-13 16:53:04.513--ClientSession(19397138)--Connection(11299397)--Thread(Thread[main,5,main])--UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT))) [EL Fine]: 2010-09-13 16:53:04.543--ClientSession(19397138)--Thread(Thread[main,5,main])--VALUES(1) [EL Warning]: 2010-09-13 16:53:04.553--UnitOfWork(26596606)--Thread(Thread[main,5,main])--Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: Lexical error at line 1, column 166. Encountered: "#" (35), after : "". Error Code: -1 Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT))) Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))")
>debugged in SE and reproduced the issue >We should not be adding the #temporary table as a parameter on the query at org.eclipse.persistence.example.dataparallel.GridClient at localhost:56800 Thread [main] (Suspended) SQLCall(DatasourceCall).appendIn(Writer, DatabaseField) line: 568 SQLCall(DatasourceCall).translateCustomQuery() line: 422 SQLCall.translateCustomQuery() line: 283 SQLCall.prepareInternal(AbstractSession) line: 149 SQLCall(DatabaseCall).prepare(AbstractSession) line: 546 CallQueryMechanism.prepareCall() line: 132 CallQueryMechanism(DatasourceCallQueryMechanism).prepareExecuteNoSelect() line: 490 DataModifyQuery.prepare() line: 103 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord, boolean) line: 541 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord) line: 502 DataModifyQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 703 DataModifyQuery(DatabaseQuery).executeInUnitOfWork(UnitOfWorkImpl, AbstractRecord) line: 675 RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2914 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, List) line: 1257 EJBQueryImpl<X>.executeUpdate() line: 534 GridClient.nativeQuery() line: 107 GridClient.main(String[]) line: 329 >DatasourceCall.java:422 public void translateCustomQuery() { ... try { // ** This method is heavily optimized do not touch anything unless you "know" what your doing. while (lastIndex != -1) { int poundIndex = queryString.indexOf('#', lastIndex); ... if (poundIndex != -1) { ... // Check for ## which means field from modify row. if (queryString.charAt(poundIndex + 1) == '#') { ... } else { String fieldName = queryString.substring(poundIndex + 1, wordEndIndex); DatabaseField field = createField(fieldName); > appendIn(writer, field); this SQLCall (id=73) parameters NonSynchronizedVector (id=97) elementData Object[10] (id=120) > [0] DatabaseField (id=92) qualifiedName "DPAR_SPROCUNIT" (id=91) sqlString "UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))" (id=78) DatabaseQuery.java:535 public void checkPrepare(AbstractSession session, AbstractRecord translationRow, boolean force) { try { // This query is first prepared for global common state, this must be synced. if (!this.isPrepared) {// Avoid the monitor is already prepare, must ... synchronized (this) { if (!isPrepared()) { if ((isReadQuery() || isDataModifyQuery()) && isCallQuery() && (getQueryMechanism() instanceof CallQueryMechanism) && ((translationRow == null) || translationRow.isEmpty())) { if (isReadObjectQuery() || isUserDefined()) { > ((CallQueryMechanism) getQueryMechanism()).setCallHasCustomSQLArguments(); >We then write a "?" in place of this parameter into the CharArrayWriter("UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?") GridClient [Java Application] org.eclipse.persistence.example.dataparallel.GridClient at localhost:56800 Thread [main] (Suspended (breakpoint at line 393 in DatasourceCall)) SQLCall(DatasourceCall).translateCustomQuery() line: 393 SQLCall.translateCustomQuery() line: 283 >And set the queryString queryString "UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?)))" (id=143)
>The preliminary fix is to not do processing for custom SQL arguments in this case >SQLCall.java:138 protected void prepareInternal(AbstractSession session) { if (hasCustomSQLArguments()) { ... translateCustomQuery(); >needs to be false so we do not run translateCustomQuery() this SQLCall (id=74) > hasCustomSQLArguments true (should be false) sqlString "UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))" (id=79) >The flag is set by ((CallQueryMechanism) getQueryMechanism()).setCallHasCustomSQLArguments() in checkPrepare if it is a readObjectQuery or is user defined ? if (isReadObjectQuery() || isUserDefined()) { >GridClient [Java Application] org.eclipse.persistence.example.dataparallel.GridClient at localhost:57176 Thread [main] (Suspended (breakpoint at line 164 in SQLCall)) SQLCall.setHasCustomSQLArguments(boolean) line: 164 CallQueryMechanism.setCallHasCustomSQLArguments() line: 346 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord, boolean) line: 535 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord) line: 502 DataModifyQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 703 >Therefore the fix is not to set the userDefined field to [True] in this case >Setting the isSQLCall to false would not make sense for setCallHasCustomSQLArguments() >The preliminary fix is to not do parameter processing for custom SQL arguments in this case >SQLCall.java:138 protected void prepareInternal(AbstractSession session) { if (hasCustomSQLArguments()) { ... translateCustomQuery(); >needs to be false so we do not run translateCustomQuery() this SQLCall (id=74) > hasCustomSQLArguments true (should be false) sqlString "UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))" (id=79) >The flag is set by ((CallQueryMechanism) getQueryMechanism()).setCallHasCustomSQLArguments() in checkPrepare if it is a readObjectQuery or is user defined ? if (isReadObjectQuery() || isUserDefined()) { >GridClient [Java Application] org.eclipse.persistence.example.dataparallel.GridClient at localhost:57176 Thread [main] (Suspended (breakpoint at line 164 in SQLCall)) SQLCall.setHasCustomSQLArguments(boolean) line: 164 CallQueryMechanism.setCallHasCustomSQLArguments() line: 346 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord, boolean) line: 535 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord) line: 502 DataModifyQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 703 >Therefore the fix is not to set the userDefined field to [True] in this case >Setting the isSQLCall to false would not make sense for setCallHasCustomSQLArguments() There are 28 references to DatabaseQuery.setIsUserDefined() We need a way to figure out the difference between an #F_NAME parameter and a #EMPLOYEE temporary table and not set the flag in the temporary table case update EMPLOYEE set F_NAME to #F_NAME from update EMPLOYEE set F_NAME to 'test' where ((EMP_ID = 1) and (EMP_ID in (select EMP_ID from #EMPLOYEE)) >What about a mixed query that has both parameters and custom tables? update EMPLOYEE set F_NAME to #F_NAME where ((EMP_ID = 1) and (EMP_ID in (select EMP_ID from #EMPLOYEE))
>Issue: SQLCall needs a possible subclass or a release from being classified as a "Call" in the temporary table case Since the call on the CallQueryMechanism is an SQLCall - by definition "A call is an SQL string with parameters." it has parameters in the SQL string - but this one does not. Therefore we need an SQLCall without parameters - as the translation code assumes that # is only for stored procedures [EL Warning]: 2010-09-14 14:51:03.222--ClientSession(20337504)--Thread(Thread[main,5,main])--named_argument_not_found_in_query_parameters (There is no English translation for this message.) <fixed message for bug# 325170 below> [EL Warning]: 2010-09-14 15:16:02.052--ClientSession(20796783)--Thread(Thread[main,5,main])--Missing Query parameter for named argument: DPAR_SPROCUNIT null will be substituted. SQLCall(DatasourceCall).getValueForInParameter(Object, AbstractRecord, AbstractRecord, AbstractSession, boolean) line: 791 >or the translation code needs to work with a navigable tree and not just character based indexes so we will know if the # is in the context of a "from" subquery update +-- in +-- select from # >Here is where the ? is written Thread [main] (Suspended) SQLCall(DatasourceCall).appendIn(Writer, DatabaseField) line: 567 SQLCall(DatasourceCall).translateCustomQuery() line: 422 SQLCall.translateCustomQuery() line: 283 SQLCall.prepareInternal(AbstractSession) line: 149 SQLCall(DatabaseCall).prepare(AbstractSession) line: 546 CallQueryMechanism.prepareCall() line: 132 CallQueryMechanism(DatasourceCallQueryMechanism).prepareExecuteNoSelect() line: 490 DataModifyQuery.prepare() line: 103 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord, boolean) line: 541 DataModifyQuery(DatabaseQuery).checkPrepare(AbstractSession, AbstractRecord) line: 502 DataModifyQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 703 DataModifyQuery(DatabaseQuery).executeInUnitOfWork(UnitOfWorkImpl, AbstractRecord) line: 675 RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2914 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283 RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, List) line: 1257 EJBQueryImpl<X>.executeUpdate() line: 534 GridClient.nativeQuery() line: 107 GridClient.main(String[]) line: 329 >Experimental fix result >before Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM ?)))") >after Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 47) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SPROCUNIT)))") >using new // 325167: experimental code to be discarded/refactored public boolean isTemporaryTableQuery() { boolean result = false; // explicit if (isCallQuery() && (getQueryMechanism() instanceof CallQueryMechanism)) { String queryString = ((CallQueryMechanism)getQueryMechanism()).getCall().getQueryString(); if(null != queryString) { Pattern pattern = Pattern.compile("[^ (]*[ ]*[(]*[fF][rR][oO][mM][ ]+#[^ ]*"); Matcher matcher = pattern.matcher(queryString); result = matcher.find(); } } return result; } >and modified checkPrepare if ((isReadQuery() || isDataModifyQuery()) && isCallQuery() && (getQueryMechanism() instanceof CallQueryMechanism) && ((translationRow == null) || translationRow.isEmpty()) && !isTemporaryTableQuery()) { // Must check for read object queries as the row will be // empty until the prepare. if (isReadObjectQuery() || isUserDefined()) { ((CallQueryMechanism) getQueryMechanism()).setCallHasCustomSQLArguments(); } } else if (isCallQuery() && (getQueryMechanism() instanceof CallQueryMechanism) && !isTemporaryTableQuery()) { ((CallQueryMechanism) getQueryMechanism()).setCallHasCustomSQLArguments(); }
Created attachment 178884 [details] experimental non-call pattern-matching only for "from #" case so far, to preempt userDefined being set to true
See also square bracket [] fix for bug # 260265 (a child of bug # 299418) for stored procedure parameters - which is related See additional forum post on this temporary table issue http://www.dotnetspark.com/links/15292-error-when-using-sql-server-temporary-tables.aspx
>directly related MSDN post to be answered when this is fixed http://social.msdn.microsoft.com/Forums/en/transactsql/thread/40bb4a45-af38-4aba-92e2-00da9616d35b >Alternate fix is to delimit with [] brackets - just as in one of the fixes for bug# 260263 where we ended up using @ >see comment 6 https://bugs.eclipse.org/bugs/show_bug.cgi?id=260263#c6 this is Alt # 5 http://wiki.eclipse.org/EclipseLink/Bugs/325167#Alternative_5:_Delimit_temporary_table_with_Square_brackets_like_260263
>Alt 5: [] delimiters does not currently work like it did for stored procedures >native query fragment aBuffer.append("(SELECT PROCUNIT_ID FROM [#DPAR_SCPROCUNIT])))") >still gets converted to ? parameters by CalQueryMechanism with a hanging [ (SELECT PROCUNIT_ID FROM [?)))
>5962622: This issue should have been in 2.1
>See non-blocking bug# 328717 that may affect or be affected by a change here
Created attachment 182121 [details] 325167 Alternative #7 use query hint to override default hash bind parameter char - pre code_review
>Alternative #7 test results http://wiki.eclipse.org/EclipseLink/Bugs/325167#Alternative_7:_Use_a_query_hint_to_change_the_default_bind_parameter_hash_char >The following results show % binding and # pass-through on the Natvie SQL query Query: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = %anid) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SCPROCUNIT))) >with the following client change aQuery.setParameter("anid", 32); aQuery.setHint(QueryHints.PARAMETER_DELIMITER, "%"); Call: UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = 32) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SCPROCUNIT))) Query: DataModifyQuery(sql="UPDATE DPAR_SCPROCUNIT SET STATE = 1, PENDINGSTATE = 1, ALU_VERSION = 4 WHERE ((PROCUNIT_ID = ?) AND (ALU_VERSION = 3) AND (PROCUNIT_ID IN (SELECT PROCUNIT_ID FROM #DPAR_SCPROCUNIT)))")
Essentially, this change involves making the currently hardcoded # delimiter - user definable into something like % for example
Created attachment 182181 [details] 325167 Alternative #7 use query hint to override default hash bind parameter char - pre code_review
Created attachment 182475 [details] 325167 Alternative #7 use query hint to override default hash bind parameter char
Created attachment 182619 [details] 325167 Alternative #7 use query hint to override default hash bind parameter char (SQLCall removed - comments only) >Updated patch (SQLCall had no mofifications) - will merge with 2.1.2/2.1.3 when the stream opens shortly
>core regression results [junit] Tests run: 7813, Failures: 0, Errors: 0, Time elapsed: 1,807.902 sec
Created attachment 182814 [details] 2.1 stream : 325167 Alternative #7 use query hint to override default hash bind parameter char (comment change)
Created attachment 182815 [details] 2.2 stream : 325167 Alternative #7 use query hint to override default hash bind parameter char (comment change)
>Checked into trunk (2.2) under SVN rev# 8493 before checking into (2.1) in a future approved TXN https://fisheye2.atlassian.com/changelog/eclipselink/?cs=8493 >Note: we do not run nightly HSQL testing but regression testing on other DB will be done on the trunk code as part of automated nightly testing. >2.1 core LRG results [junit] Tests run: 7757, Failures: 0, Errors: 0, Time elapsed: 1,859.864 sec [junit] Tests run: 7757, Failures: 0, Errors: 0, Time elapsed: 1,899.747 sec >2.1 clean view results <testsuite errors="101" failures="7" hostname="xps435" name="org.eclipse.persistence.testing.tests.jpa.AllCMP3TestRunModel" tests="2461" time="1410.291" timestamp="2010-11-10T16:17:03"> >2.1 modified view results <testsuite errors="104" failures="8" hostname="xps435" name="org.eclipse.persistence.testing.tests.jpa.AllCMP3TestRunModel" tests="2461" time="1576.638" timestamp="2010-11-11T14:23:35"> >2.2 trunk core LRG results [junit] Tests run: 7813, Failures: 0, Errors: 0, Time elapsed: 1,892.677 sec >2.2 trunk JPA results <testsuite errors="0" failures="0" hostname="xps435" name="org.eclipse.persistence.testing.tests.jpa.AllCMP3TestRunModel" tests="2172" time="1480.224" timestamp="2010-11-10T14:49:39">
>closing until the 2.1 transaction is approved for 2.1.3 or later. A 2.1 view is merged and ready for commit if this bug is reopened in the future. >Currently "trunk" has all the changes since rev 8493.
>This patch does not address the following issues - we in the past are marking both dynamic and static queries with setIsUserDefined(true) - we should only be doing this for static queries >The patch allows parameter pass through but does not fix the other issue above with dynamic queries having the userdefined flag set
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink