| /* |
| * Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| package org.eclipse.persistence.testing.tests.feature; |
| |
| import org.eclipse.persistence.descriptors.*; |
| import org.eclipse.persistence.exceptions.DatabaseException; |
| import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; |
| import org.eclipse.persistence.platform.database.DatabasePlatform; |
| import org.eclipse.persistence.sequencing.*; |
| import org.eclipse.persistence.sessions.*; |
| |
| import org.eclipse.persistence.testing.framework.*; |
| import org.eclipse.persistence.testing.models.sequencing.*; |
| |
| /** |
| * The purpose of this test is to test that when Sequencing shouldAcquireValueAfterInsert is set, |
| * the SQL which is generated for an insert query does not include column name and values for the |
| * sequence number column defined for the object being inserted. |
| */ |
| public class SequenceFieldRemovalForAcquireValueAfterInsertTest extends TestCase { |
| |
| protected ClassDescriptor descriptor; |
| protected SQLStringListener sqlListener; |
| protected ModifyRowModifier modifyRowModifier; |
| protected Sequence oldSequence; |
| protected String sqlString; |
| |
| public SequenceFieldRemovalForAcquireValueAfterInsertTest() { |
| super(); |
| setDescription("Tests removing the sequence field from an SQL insert statement, when Sequencing shouldAcquireValueAfterInsert is true"); |
| } |
| |
| @Override |
| public void setup() { |
| this.descriptor = getSession().getDescriptor(SeqTestClass1.class); |
| |
| String sequenceNumberName = descriptor.getSequenceNumberName(); |
| Sequence sequence = getSession().getLogin().getSequence(sequenceNumberName); |
| DatabasePlatform platform = getDatabaseSession().getPlatform(); |
| |
| if (!platform.supportsNativeSequenceNumbers() || !platform.supportsIdentity()) { |
| throw new TestWarningException("Test only supported on platforms supporting sequencing and identity"); |
| } |
| |
| // if the sequence is not native, change it to be native and cache the old sequence |
| if (!sequence.isNative()) { |
| this.oldSequence = sequence; |
| NativeSequence newSequence = new NativeSequence(sequenceNumberName, 1); |
| newSequence.setShouldAcquireValueAfterInsert(true); |
| getDatabaseSession().getLogin().removeSequence(sequenceNumberName); |
| getDatabaseSession().getLogin().addSequence(newSequence); |
| getDatabaseSession().getSequencingControl().resetSequencing(); |
| } |
| |
| this.sqlListener = new SQLStringListener(); |
| this.descriptor.getEventManager().addListener(sqlListener); |
| // need to modify the size of the row to force reprepare |
| this.modifyRowModifier = new ModifyRowModifier(); |
| this.descriptor.getEventManager().addListener(modifyRowModifier); |
| |
| beginTransaction(); |
| } |
| |
| @Override |
| public void test() { |
| UnitOfWork uow = getDatabaseSession().acquireUnitOfWork(); |
| |
| SeqTestClass1 object = new SeqTestClass1(); |
| object.setTest1("aTestValue"); |
| object.setTest2(ModifyRowModifier.OMISSION_MARKER); // marker to have modify row altered |
| |
| uow.registerObject(object); |
| try { |
| uow.commit(); |
| sqlString = this.sqlListener.getSQLString(); |
| } catch (DatabaseException d) { |
| // catch exception, don't rethrow - only need SQL generated |
| sqlString = ((DatabaseCall)d.getCall()).getSQLString(); |
| } |
| |
| if (sqlString == null) { |
| throw new TestErrorException("Generated SQL string is null"); |
| } |
| } |
| |
| @Override |
| public void reset() { |
| rollbackTransaction(); |
| if (sqlListener != null) { |
| this.descriptor.getEventManager().removeListener(sqlListener); |
| } |
| if (modifyRowModifier != null) { |
| this.descriptor.getEventManager().removeListener(modifyRowModifier); |
| } |
| |
| // if sequencing was changed, reset to the previous sequence |
| if (oldSequence != null) { |
| getDatabaseSession().getLogin().removeSequence(descriptor.getSequenceNumberName()); |
| getDatabaseSession().getLogin().addSequence(oldSequence); |
| this.oldSequence = null; |
| getDatabaseSession().getSequencingControl().resetSequencing(); |
| } |
| } |
| |
| @Override |
| public void verify() { |
| String fieldName = descriptor.getSequenceNumberField().getName(); |
| String qualifiedFieldName = descriptor.getSequenceNumberField().getQualifiedName(); |
| |
| if (sqlString.indexOf(qualifiedFieldName) != -1 || sqlString.indexOf(fieldName) != -1) { |
| throw new TestErrorException("Invalid SQL String - sequence field " + fieldName + " was included in SQL: (" + sqlString + ")" |
| + "- incorrect for shouldAcquireValueAfterInsert = true"); |
| } |
| } |
| |
| class SQLStringListener extends DescriptorEventAdapter { |
| |
| protected String sqlString; |
| |
| @Override |
| public void postInsert(DescriptorEvent event) { |
| sqlString = event.getQuery().getSQLString(); |
| } |
| |
| public String getSQLString() { |
| return this.sqlString; |
| } |
| |
| } |
| |
| class ModifyRowModifier extends DescriptorEventAdapter { |
| |
| public static final String OMISSION_MARKER = "omit_this_field"; |
| |
| @Override |
| public void aboutToInsert(DescriptorEvent event) { |
| org.eclipse.persistence.sessions.Record modifyRow = event.getRecord(); |
| Object[] keys = modifyRow.keySet().toArray(); |
| for (int i = 0; i < keys.length; i++) { |
| Object key = keys[i]; |
| Object value = modifyRow.get(key); |
| if (value != null && value.equals(OMISSION_MARKER)) { |
| modifyRow.remove(key); |
| } |
| } |
| } |
| |
| } |
| |
| } |