| /* |
| * Copyright (c) 1998, 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 |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.testing.tests.feature; |
| |
| import org.eclipse.persistence.testing.models.employee.domain.Employee; |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.tools.schemaframework.SequenceObjectDefinition; |
| import org.eclipse.persistence.tools.schemaframework.SchemaManager; |
| import org.eclipse.persistence.exceptions.*; |
| import org.eclipse.persistence.testing.framework.*; |
| import org.eclipse.persistence.sequencing.Sequence; |
| import org.eclipse.persistence.sequencing.DefaultSequence; |
| import org.eclipse.persistence.sequencing.NativeSequence; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| |
| public class OracleNativeSeqInitTest extends AutoVerifyTestCase { |
| // the following two modes test OracleSequenceDefinition.createOnDatabase method. |
| |
| // this mode tests creation of a new sequence after |
| // the sequence was dropped: |
| // Next available sequence number will be 1. |
| public static final int DROP_CREATE = 0; |
| |
| // this mode tests creation of a sequence after |
| // the sequence was already created: |
| // in this case SequenceDefinition.createOnDatabase method calls |
| // alterOnDatabase method. |
| // Next available sequence number will be the same as |
| // the next available sequence number before the method was called. |
| public static final int CREATE_CREATE = 1; |
| |
| // the following two modes test alterOnDatabase method. |
| |
| // NEXTVAL_ALTER in the case NEXTVAL has been called before on the sequence |
| // and therefore CURRVAL is defined: in this case the increment on the existing sequence |
| // Next available sequence number will be the same as |
| // the next available sequence number before the method was called. |
| public static final int NEXTVAL_ALTER = 2; |
| |
| // CREATE_ALTER in case NEXTVAL was never called on the sequence |
| // after it was created and therefore CURRVAL is undefined: |
| // in this case a new sequence is created, just like in DROP_CREATE case. |
| // Next available sequence number will be 1. |
| public static final int CREATE_ALTER = 3; |
| |
| protected Boolean usesNativeSequencingOriginal; |
| protected Sequence originalSequence; |
| protected int seqPreallocationSizeOriginal; |
| protected int lastSeqNumberOriginal; |
| protected Boolean usesBatchWritingOriginal; |
| protected Boolean shouldCacheAllStatementsOriginal; |
| |
| protected int mode; |
| protected int seqPreallocationSizeOld = 10; |
| protected int seqPreallocationSize = 50; |
| protected int idExpected; |
| protected int id; |
| protected ValidationException exception; |
| protected String seqName; |
| protected SequenceObjectDefinition sequenceDefinition; |
| protected Sequence sequence; |
| |
| protected boolean shouldUseSchemaManager; |
| protected SchemaManager schemaManager; |
| |
| public OracleNativeSeqInitTest(boolean shouldUseSchemaManager, int mode) { |
| this.mode = mode; |
| this.shouldUseSchemaManager = shouldUseSchemaManager; |
| if (shouldUseSchemaManager) { |
| if (mode == DROP_CREATE) { |
| setName(getName() + " SchemaManager DROP CREATE"); |
| setDescription("Tests SchemaManager.createObject method"); |
| } else if (mode == CREATE_CREATE) { |
| setName(getName() + " SchemaManager CREATE CREATE"); |
| setDescription("Tests SchemaManager.createObject method"); |
| } else if (mode == NEXTVAL_ALTER) { |
| setName(getName() + " SchemaManager NEXTVAL_ALTER"); |
| setDescription("Tests SchemaManager.alterSequenceIncrement method"); |
| } else if (mode == CREATE_ALTER) { |
| setName(getName() + " SchemaManager CREATE_ALTER"); |
| setDescription("Tests SchemaManager.alterSequenceIncrement method"); |
| } |
| } else { |
| if (mode == DROP_CREATE) { |
| setName(getName() + " OracleSequenceDefinition DROP CREATE"); |
| setDescription("Tests OracleSequenceDefinition.createOnDatabase method"); |
| } else if (mode == CREATE_CREATE) { |
| setName(getName() + " OracleSequenceDefinition CREATE CREATE"); |
| setDescription("Tests OracleSequenceDefinition.createOnDatabase method"); |
| } else if (mode == NEXTVAL_ALTER) { |
| setName(getName() + " OracleSequenceDefinition NEXTVAL_ALTER"); |
| setDescription("Tests OracleSequenceDefinition.alterOnDatabase method"); |
| } else if (mode == CREATE_ALTER) { |
| setName(getName() + " OracleSequenceDefinition CREATE_ALTER"); |
| setDescription("Tests OracleSequenceDefinition.alterOnDatabase method"); |
| } |
| } |
| } |
| |
| @Override |
| public void setup() { |
| if (!getSession().getPlatform().supportsSequenceObjects()) { |
| throw new TestWarningException("This test requires a platform that supports sequence objects"); |
| } |
| ClassDescriptor descriptor = getSession().getDescriptor(Employee.class); |
| if (!descriptor.usesSequenceNumbers()) { |
| throw new TestWarningException("Employee doesn't use sequencing"); |
| } |
| originalSequence = getSession().getPlatform().getSequence(descriptor.getSequenceNumberName()); |
| usesNativeSequencingOriginal = (originalSequence instanceof NativeSequence || |
| (originalSequence instanceof DefaultSequence && getSession().getPlatform().getDefaultSequence() instanceof NativeSequence) |
| ) && !originalSequence.shouldAcquireValueAfterInsert(); |
| if (!usesNativeSequencingOriginal) { |
| NativeSequence newSequence = new NativeSequence(originalSequence.getName(), originalSequence.getPreallocationSize()); |
| newSequence.onConnect(originalSequence.getDatasourcePlatform()); |
| getAbstractSession().getPlatform().addSequence(newSequence); |
| sequence = newSequence; |
| } else { |
| sequence = originalSequence; |
| } |
| |
| seqPreallocationSizeOriginal = originalSequence.getPreallocationSize(); |
| |
| lastSeqNumberOriginal = getSession().getNextSequenceNumberValue(Employee.class).intValue() - 1; |
| |
| usesBatchWritingOriginal = getSession().getPlatform().usesBatchWriting(); |
| |
| shouldCacheAllStatementsOriginal = getSession().getPlatform().shouldCacheAllStatements(); |
| |
| getDatabaseSession().getSequencingControl().initializePreallocated(); |
| |
| sequenceDefinition = new SequenceObjectDefinition(sequence); |
| sequenceDefinition.setQualifier(getSession().getLogin().getTableQualifier()); |
| if (shouldUseSchemaManager) { |
| schemaManager = new SchemaManager(getDatabaseSession()); |
| |
| // make sure that upcoming DROP and CREATE haven't been cached |
| // and therefore for sure will go through |
| getSession().getPlatform().setShouldCacheAllStatements(false); |
| |
| // This is the worst case scenario settings - SchemaManager should handle it. |
| getSession().getPlatform().setUsesBatchWriting(true); |
| getSession().getPlatform().setShouldCacheAllStatements(true); |
| } else { |
| getSession().getPlatform().setUsesBatchWriting(false); |
| getSession().getPlatform().setShouldCacheAllStatements(false); |
| } |
| |
| // all three modes start with dropping an existing sequence (if any) |
| try { |
| drop(); |
| } catch (DatabaseException exception) { |
| // Ignore already deleted |
| } |
| |
| if (mode == DROP_CREATE) { |
| // sequence doesn't exist. |
| // create sequence with seqPreallocationSize. |
| // note that both increment and starting value are set to |
| // sequenceDefinition.getIncrement() |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSize); |
| create(); |
| |
| // next available sequence number. |
| idExpected = 1; |
| } else if (mode == CREATE_CREATE) { |
| // sequence doesn't exist, |
| // create sequence with seqPreallocationSizeOld |
| // note that both increment and starting value are set to |
| // sequenceDefinition.getIncrement() |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSizeOld); |
| create(); |
| |
| // now sequence exists, |
| // create sequence with seqPreallocationSize |
| // Note that createOnDatabase will call alterOnDatabase |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSize); |
| create(); |
| |
| // next available sequence number. |
| // note that the second createOnDatabase selects NEXTVAL during existance check, |
| // because it is the first call to NEXTVAL, the starting sequence value is returned, |
| // and this value was set to seqPreallocationSizeOld by the first createOnDatabase |
| idExpected = 1 + seqPreallocationSizeOld; |
| } else if (mode == NEXTVAL_ALTER) { |
| // sequence doesn't exist, |
| // create sequence with seqPreallocationSizeOld |
| // note that both increment and starting value are set to |
| // sequenceDefinition.getIncrement() |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSizeOld); |
| create(); |
| |
| // now sequence exists, |
| // select NEXTVAL |
| // because it is the first call to NEXTVAL, the starting sequence value is returned, |
| // and this value was set to seqPreallocationSizeOld by the first createOnDatabase |
| sequenceDefinition.checkIfExist((AbstractSession)getSession()); |
| |
| // alter increment of sequence with seqPreallocationSize. |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSize); |
| alter(); |
| |
| // next available sequence number. |
| // because there was just one call to NEXTVAL, the starting sequence value is returned, |
| // and this value was set to seqPreallocationSizeOld by createOnDatabase |
| idExpected = 1 + seqPreallocationSizeOld; |
| } else if (mode == CREATE_ALTER) { |
| // sequence doesn't exist, |
| // create sequence with seqPreallocationSizeOld |
| // note that both increment and starting value are set to |
| // sequenceDefinition.getIncrement() |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSizeOld); |
| create(); |
| |
| // alter increment of sequence with seqPreallocationSize. |
| sequence.setInitialValue(1); |
| sequence.setPreallocationSize(seqPreallocationSize); |
| alter(); |
| |
| // next available sequence number. |
| idExpected = 1; |
| } |
| getSession().getPlatform().getSequence(descriptor.getSequenceNumberName()).setPreallocationSize(seqPreallocationSize); |
| } |
| |
| @Override |
| public void test() { |
| try { |
| id = getSession().getNextSequenceNumberValue(Employee.class).intValue(); |
| exception = null; |
| } catch (ValidationException ex) { |
| id = 0; |
| exception = ex; |
| } |
| } |
| |
| @Override |
| public void verify() { |
| if (exception != null) { |
| throw new TestErrorException("Sequence allocation failed", exception); |
| } |
| if (id != idExpected) { |
| throw new TestErrorException("Wrong sequencing number"); |
| } |
| } |
| |
| @Override |
| public void reset() { |
| // make sure reset isn't performed twice |
| if(sequence == null) { |
| return; |
| } |
| |
| // make sure that upcoming DROP and CREATE haven't been cached |
| // and therefore for sure will go through |
| getSession().getPlatform().setShouldCacheAllStatements(false); |
| // Drop the sequence |
| drop(); |
| |
| // Should setup Employee's sequence so that: |
| // 1. seqPreallocationOriginal is used as an increment; |
| sequence.setPreallocationSize(seqPreallocationSizeOriginal); |
| // 2. the next available number is lastSeqNumberOriginal + 1 |
| sequence.setInitialValue(lastSeqNumberOriginal + seqPreallocationSizeOriginal); |
| |
| // Re-create sequence in its original state |
| create(); |
| |
| getDatabaseSession().getSequencingControl().initializePreallocated(); |
| getSession().getPlatform().getSequence(getSession().getDescriptor(Employee.class).getSequenceNumberName()).setPreallocationSize(seqPreallocationSizeOriginal); |
| |
| if (shouldCacheAllStatementsOriginal != null) { |
| getSession().getPlatform().setShouldCacheAllStatements(shouldCacheAllStatementsOriginal); |
| } |
| if (usesBatchWritingOriginal != null) { |
| getSession().getPlatform().setUsesBatchWriting(usesBatchWritingOriginal); |
| } |
| |
| if ((usesNativeSequencingOriginal != null) && !usesNativeSequencingOriginal) { |
| getAbstractSession().getPlatform().addSequence(originalSequence); |
| } |
| |
| sequence = null; |
| } |
| |
| protected void drop() { |
| if (shouldUseSchemaManager) { |
| schemaManager.dropObject(sequenceDefinition); |
| } else { |
| sequenceDefinition.dropFromDatabase(getAbstractSession()); |
| } |
| } |
| |
| protected void create() { |
| if (shouldUseSchemaManager) { |
| schemaManager.createObject(sequenceDefinition); |
| } else { |
| sequenceDefinition.createOnDatabase(getAbstractSession()); |
| } |
| } |
| |
| protected void alter() { |
| if (shouldUseSchemaManager) { |
| schemaManager.alterSequence(sequenceDefinition); |
| } else { |
| sequenceDefinition.alterOnDatabase(getAbstractSession()); |
| } |
| } |
| } |