Bug 339277 - INSERT call in ExpressionQueryMechanism instead of UPDATE call
Summary: INSERT call in ExpressionQueryMechanism instead of UPDATE call
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-08 15:00 EST by Markus Bukowski CLA
Modified: 2022-06-09 10:07 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Bukowski CLA 2011-03-08 15:00:35 EST
Build Identifier: EclipseLink, version: Eclipse Persistence Services - 2.1.1.v20100817-r8050

Hi,

I am trying to collect all insert, update and delete queries within a transaction. I have extended the DescriptorEventAdapter
and try to capute the queries through overriding the postInsert, postUpdate and postDelete method. I am interested in the SQL + the parameters.
My goal is some kind of transaction capture. So I am able to replay the transaction on another machine with writes exactly the same data into another 
database (schema is going to be the same).

After a few tests I could see the following behaviour:

First Call is: SQLCall(INSERT INTO HASHNODE (LEAF, VERSIONSNUMMER, HASH_DOKUMENT, HASH_TREENODE, HASH_ZEITSTEMPELKETTE, ZAEHLER, UUID, PARENT_UUID, DOKINFO_UUID, BAUM_UUID, ZEITSTEMPEL_UUID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))
which seems ok. 
Second call is according to
	event->query->queryMechanism->call:
		SQLCall(INSERT INTO HASHBAUM (ERSTELLT, HASHVERFAHREN, FINALISIERT, KARDINALITAET, VERSIONSNUMMER, UUID, RETIMESTAMP_UUID, ROOT_UUID, STAMTGRUPPE_UUID, REHASH_UUID, HASHBAUM_TYP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))
		with a event->query->modifyRow of
			DatabaseRecord(
			HASHBAUM.KARDINALITAET 		=> 	100
			HASHBAUM.FINALISIERT 		=> 	2011-03-08 20:27:10.814
			HASHBAUM.ERSTELLT 			=> 	2011-03-08 20:27:09.539
			HASHBAUM.ROOT_UUID 			=> 	100f55a0-49ba-11e0-8234-00247e1610fe
			HASHBAUM.VERSIONSNUMMER 	=> 	1
			HASHBAUM.HASHVERFAHREN 		=> 	2.16.840.1.101.3.4.2.1
			HASHBAUM.STAMTGRUPPE_UUID 	=> 	3c2ed210-4969-11e0-a827-00247e1610fe)
	whereas the issued query on the database is
		EL Fine]: ClientSession(21702188)--Connection(12003823)--UPDATE HASHBAUM SET KARDINALITAET = ?, FINALISIERT = ?, ERSTELLT = ?, ROOT_UUID = ?, VERSIONSNUMMER = ?, HASHVERFAHREN = ?, STAMTGRUPPE_UUID = ? WHERE (UUID = ?)
	bind => [100, 2011-03-08 20:27:10.814, 2011-03-08 20:27:09.539, 100f55a0-49ba-11e0-8234-00247e1610fe, 1, 2.16.840.1.101.3.4.2.1, 3c2ed210-4969-11e0-a827-00247e1610fe, 0f96a330-49ba-11e0-8234-00247e1610fe]

	In effect this means that the executed call is another than the carried on in the queryMechanism object. But what I am not able to understand is why are the parameters right (the given parameters are not working with the INSERT query)
	
	Is this the right behaviour? Shouldn't event->query->queryMechanism->call be 
		"UPDATE HASHBAUM SET KARDINALITAET = ?, FINALISIERT = ?, ERSTELLT = ?, ROOT_UUID = ?, VERSIONSNUMMER = ?, HASHVERFAHREN = ?, STAMTGRUPPE_UUID = ? WHERE (UUID = ?)"?
		
		
I am using EclipseLink 2.1.1 (JPA) with Oracle WebLogic 10.3.3		


Reproducible: Always
Comment 1 Doug Clarke CLA 2011-03-09 15:02:09 EST
The following session-event-listener can capture all SQL without the parameter binding. Using some additional conditions on the query type the INSERT/UPDATE/DELETE within a TXN could be captured.

public class SQLCaptureListener extends SessionEventAdapter {

    @Override
    public void postExecuteQuery(SessionEvent event) {
        DatabaseQuery query = (DatabaseQuery) event.getQuery();
        String sql = query.getTranslatedSQLString(event.getSession(), query.getTranslationRow());
        System.out.println("SQL: " + sql);
    }
}
Comment 2 Doug Clarke CLA 2011-03-09 15:19:50 EST
Here is a transactional example that captures all modify SQL in a UnitOfWork and logs it at the end.

/**
 * Capture the modify SQL statements within a transaction and log them at the
 * end.
 * 
 * @author dclarke
 * @since EclipseLink 2.2
 */
public class CaptureTransactionSQL extends SessionEventAdapter {

    private static final String PROPERTY = CaptureTransactionSQL.class.getName();

    @Override
    public void postExecuteQuery(SessionEvent event) {
        DatabaseQuery query = (DatabaseQuery) event.getQuery();

        if (query.isModifyQuery() && event.getSession().isUnitOfWork()) {
            String sql = query.getTranslatedSQLString(event.getSession(), query.getTranslationRow());
            getSQLStrings(event.getSession()).add(sql);
        }
    }

    @SuppressWarnings("unchecked")
    private List<String> getSQLStrings(Session session) {
        if (!session.getProperties().containsKey(PROPERTY)) {
            session.setProperty(PROPERTY, new ArrayList<String>());
        }
        return (List<String>) session.getProperty(PROPERTY);
    }

    /**
     * Log the SQL statements. This could alternatively store them.
     */
    @Override
    public void postCommitUnitOfWork(SessionEvent event) {
        System.out.println("POST COMMIT - LOG SQL:");
        for (String sql : getSQLStrings(event.getSession())) {
            System.out.println("\t> " + sql);
        }
    }

}
Comment 3 Doug Clarke CLA 2011-03-09 15:32:09 EST
This fails when the query has arguments. I believe another fix is required for that but may be fine for what you described.
Comment 4 Markus Bukowski CLA 2011-03-09 15:47:54 EST
Thanks a lot for the quick response!

I think that I have identified another problem. 
In the method ExpressionQueryMechanism(DatabaseQueryMechanism).insertObjectForWrite() the method
updateForeignKeyFieldAfterInsert(WriteObjectQuery) is called. In which 
a new SQLUpdateStatement is created. After the creation of the statement the modifyRow of the previous InsertObjectQuery 
is set to the new SQLUpdateStatement-ModifyRow whereas the SQLCall is not replaced (See below). I think that the SQLCall should also be replaced. I think this is the reason for the previously described bug (The same code seems to be in the trunk version of EL).

Current code in updateForeignKeyFieldAfterInsert(WriteObjectQuery):
...
StatementQueryMechanism updateMechanism = new StatementQueryMechanism(writeQuery, updateStatement);
writeQuery.setModifyRow(updateStatement.getModifyRow());
updateMechanism.updateObject();
...

Possible fix for updateForeignKeyFieldAfterInsert(WriteObjectQuery):
...
StatementQueryMechanism updateMechanism = new StatementQueryMechanism(writeQuery, updateStatement);
writeQuery.setModifyRow(updateStatement.getModifyRow());
// possible fix?? the new DatabaseSessionImpl() is also used in the toString() 
// of the class SQLStatement. Perhaps annother Session can be used
writeQuery.setCall(updateStatement
	.buildCall(
		new DatabaseSessionImpl(
			new org.eclipse.persistence.sessions.DatabaseLogin()
		)
	);
updateMechanism.updateObject();
...
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:07:37 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink