ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/schema/Sequence.java

Path
ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/schema/Sequence.java
Status
scanned
Type
file
Name
Sequence.java
Extension
.java
Programming language
Java
Mime type
text/x-java
File type
Java source, ASCII text
Tag

      
    
Rootfs path

      
    
Size
19367 (18.9 KB)
MD5
d47ecd46f113a10132627ea96fb8fd8b
SHA1
bde55857600281988c42d46e277f08a545a2dfe1
SHA256
4f4eca37368b7148220bb87f138a3b03d612c25882fbdbd27cf2771717c6d3d2
SHA512

      
    
SHA1_git
f56ecf1160363ca207265365000e3f06abf3af35
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
Sequence.java | 18.9 KB |

/* * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (https://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.schema; import org.h2.api.ErrorCode; import org.h2.command.ddl.SequenceOptions; import org.h2.engine.DbObject; import org.h2.engine.SessionLocal; import org.h2.message.DbException; import org.h2.message.Trace; import org.h2.value.TypeInfo; import org.h2.value.Value; import org.h2.value.ValueBigint; /** * A sequence is created using the statement * CREATE SEQUENCE */ public final class Sequence extends SchemaObject { /** * CYCLE clause and sequence state. */ public enum Cycle { /** * Sequence is cycled. */ CYCLE, /** * Sequence is not cycled and isn't exhausted yet. */ NO_CYCLE, /** * Sequence is not cycled and was already exhausted. */ EXHAUSTED; /** * Return whether sequence is cycled. * * @return {@code true} if sequence is cycled, {@code false} if sequence * is not cycled */ public boolean isCycle() { return this == CYCLE; } } /** * The default cache size for sequences. */ public static final int DEFAULT_CACHE_SIZE = 32; private long baseValue; private long margin; private TypeInfo dataType; private long increment; private long cacheSize; private long startValue; private long minValue; private long maxValue; private Cycle cycle; private boolean belongsToTable; private boolean writeWithMargin; /** * Creates a new sequence. * * @param session * the session * @param schema * the schema * @param id * the object id * @param name * the sequence name * @param options * the sequence options * @param belongsToTable * whether this sequence belongs to a table (for generated * columns) */ public Sequence(SessionLocal session, Schema schema, int id, String name, SequenceOptions options, boolean belongsToTable) { super(schema, id, name, Trace.SEQUENCE); dataType = options.getDataType(); if (dataType == null) { options.setDataType(dataType = session.getMode().decimalSequences ? TypeInfo.TYPE_NUMERIC_BIGINT : TypeInfo.TYPE_BIGINT); } long bounds[] = options.getBounds(); Long t = options.getIncrement(session); long increment = t != null ? t : 1; Long start = options.getStartValue(session); Long min = options.getMinValue(null, session); Long max = options.getMaxValue(null, session); long minValue = min != null ? min : getDefaultMinValue(start, increment, bounds); long maxValue = max != null ? max : getDefaultMaxValue(start, increment, bounds); long startValue = start != null ? start : increment >= 0 ? minValue : maxValue; Long restart = options.getRestartValue(session, startValue); long baseValue = restart != null ? restart : startValue; t = options.getCacheSize(session); long cacheSize; boolean mayAdjustCacheSize; if (t != null) { cacheSize = t; mayAdjustCacheSize = false; } else { cacheSize = DEFAULT_CACHE_SIZE; mayAdjustCacheSize = true; } cacheSize = checkOptions(baseValue, startValue, minValue, maxValue, increment, cacheSize, mayAdjustCacheSize); Cycle cycle = options.getCycle(); if (cycle == null) { cycle = Cycle.NO_CYCLE; } else if (cycle == Cycle.EXHAUSTED) { baseValue = startValue; } this.margin = this.baseValue = baseValue; this.increment = increment; this.cacheSize = cacheSize; this.startValue = startValue; this.minValue = minValue; this.maxValue = maxValue; this.cycle = cycle; this.belongsToTable = belongsToTable; } /** * Allows the base value, start value, min value, max value, increment and * cache size to be updated atomically, including atomic validation. Useful * because setting these attributes one after the other could otherwise * result in an invalid sequence state (e.g. min value &gt; max value, start * value &lt; min value, etc). * @param baseValue * the base value ({@code null} if restart is not requested) * @param startValue * the new start value ({@code null} if no change) * @param minValue * the new min value ({@code null} if no change) * @param maxValue * the new max value ({@code null} if no change) * @param increment * the new increment ({@code null} if no change) * @param cycle * the new cycle value, or {@code null} if no change * @param cacheSize * the new cache size ({@code null} if no change) */ public synchronized void modify(Long baseValue, Long startValue, Long minValue, Long maxValue, Long increment, Cycle cycle, Long cacheSize) { long baseValueAsLong = baseValue != null ? baseValue : this.baseValue; long startValueAsLong = startValue != null ? startValue : this.startValue; long minValueAsLong = minValue != null ? minValue : this.minValue; long maxValueAsLong = maxValue != null ? maxValue : this.maxValue; long incrementAsLong = increment != null ? increment : this.increment; long cacheSizeAsLong; boolean mayAdjustCacheSize; if (cacheSize != null) { cacheSizeAsLong = cacheSize; mayAdjustCacheSize = false; } else { cacheSizeAsLong = this.cacheSize; mayAdjustCacheSize = true; } cacheSizeAsLong = checkOptions(baseValueAsLong, startValueAsLong, minValueAsLong, maxValueAsLong, incrementAsLong, cacheSizeAsLong, mayAdjustCacheSize); if (cycle == null) { cycle = this.cycle; if (cycle == Cycle.EXHAUSTED && baseValue != null) { cycle = Cycle.NO_CYCLE; } } else if (cycle == Cycle.EXHAUSTED) { baseValueAsLong = startValueAsLong; } this.margin = this.baseValue = baseValueAsLong; this.startValue = startValueAsLong; this.minValue = minValueAsLong; this.maxValue = maxValueAsLong; this.increment = incrementAsLong; this.cacheSize = cacheSizeAsLong; this.cycle = cycle; } /** * Validates the specified prospective base value, start value, min value, * max value, increment, and cache size relative to each other, since each * of their respective validities are contingent on the values of the other * parameters. * * @param baseValue * the prospective base value * @param startValue * the prospective start value * @param minValue * the prospective min value * @param maxValue * the prospective max value * @param increment * the prospective increment * @param cacheSize * the prospective cache size * @param mayAdjustCacheSize * whether cache size may be adjusted, cache size 0 is adjusted * unconditionally to 1 * @return the prospective or adjusted cache size */ private long checkOptions(long baseValue, long startValue, long minValue, long maxValue, long increment, long cacheSize, boolean mayAdjustCacheSize) { if (minValue <= baseValue && baseValue <= maxValue // && minValue <= startValue && startValue <= maxValue // && minValue < maxValue && increment != 0L) { long range = maxValue - minValue; if (Long.compareUnsigned(Math.abs(increment), range) <= 0 && cacheSize >= 0L) { if (cacheSize <= 1L) { return 1L; } long maxCacheSize = getMaxCacheSize(range, increment); if (cacheSize <= maxCacheSize) { return cacheSize; } if (mayAdjustCacheSize) { return maxCacheSize; } } } throw DbException.get(ErrorCode.SEQUENCE_ATTRIBUTES_INVALID_7, getName(), Long.toString(baseValue), Long.toString(startValue), Long.toString(minValue), Long.toString(maxValue), Long.toString(increment), Long.toString(cacheSize)); } private static long getMaxCacheSize(long range, long increment) { if (increment > 0L) { if (range < 0) { range = Long.MAX_VALUE; } else { range += increment; if (range < 0) { range = Long.MAX_VALUE; } } } else { range = -range; if (range > 0) { range = Long.MIN_VALUE; } else { range += increment; if (range >= 0) { range = Long.MIN_VALUE; } } } return range / increment; } /** * Calculates default min value. * * @param startValue the start value of the sequence. * @param increment the increment of the sequence value. * @param bounds min and max bounds of data type of the sequence * @return min value. */ public static long getDefaultMinValue(Long startValue, long increment, long[] bounds) { long v = increment >= 0 ? 1 : bounds[0]; if (startValue != null && increment >= 0 && startValue < v) { v = startValue; } return v; } /** * Calculates default max value. * * @param startValue the start value of the sequence. * @param increment the increment of the sequence value. * @param bounds min and max bounds of data type of the sequence * @return min value. */ public static long getDefaultMaxValue(Long startValue, long increment, long[] bounds) { long v = increment >= 0 ? bounds[1] : -1; if (startValue != null && increment < 0 && startValue > v) { v = startValue; } return v; } public boolean getBelongsToTable() { return belongsToTable; } public TypeInfo getDataType() { return dataType; } public int getEffectivePrecision() { TypeInfo dataType = this.dataType; switch (dataType.getValueType()) { case Value.NUMERIC: { int p = (int) dataType.getPrecision(); int s = dataType.getScale(); if (p - s > ValueBigint.DECIMAL_PRECISION) { return ValueBigint.DECIMAL_PRECISION + s; } return p; } case Value.DECFLOAT: return Math.min((int) dataType.getPrecision(), ValueBigint.DECIMAL_PRECISION); default: return (int) dataType.getPrecision(); } } public long getIncrement() { return increment; } public long getStartValue() { return startValue; } public long getMinValue() { return minValue; } public long getMaxValue() { return maxValue; } public Cycle getCycle() { return cycle; } @Override public String getDropSQL() { if (getBelongsToTable()) { return null; } StringBuilder builder = new StringBuilder("DROP SEQUENCE IF EXISTS "); return getSQL(builder, DEFAULT_SQL_FLAGS).toString(); } @Override public String getCreateSQL() { StringBuilder builder = getSQL(new StringBuilder("CREATE SEQUENCE "), DEFAULT_SQL_FLAGS); if (dataType.getValueType() != Value.BIGINT) { dataType.getSQL(builder.append(" AS "), DEFAULT_SQL_FLAGS); } builder.append(' '); synchronized (this) { getSequenceOptionsSQL(builder, writeWithMargin ? margin : baseValue); } if (belongsToTable) { builder.append(" BELONGS_TO_TABLE"); } return builder.toString(); } /** * Append the options part of the SQL statement to create the sequence. * * @param builder the builder * @return the builder */ public synchronized StringBuilder getSequenceOptionsSQL(StringBuilder builder) { return getSequenceOptionsSQL(builder, baseValue); } private StringBuilder getSequenceOptionsSQL(StringBuilder builder, long value) { builder.append("START WITH ").append(startValue); if (value != startValue && cycle != Cycle.EXHAUSTED) { builder.append(" RESTART WITH ").append(value); } if (increment != 1) { builder.append(" INCREMENT BY ").append(increment); } long[] bounds = SequenceOptions.getBounds(dataType); if (minValue != getDefaultMinValue(value, increment, bounds)) { builder.append(" MINVALUE ").append(minValue); } if (maxValue != getDefaultMaxValue(value, increment, bounds)) { builder.append(" MAXVALUE ").append(maxValue); } if (cycle == Cycle.CYCLE) { builder.append(" CYCLE"); } else if (cycle == Cycle.EXHAUSTED) { builder.append(" EXHAUSTED"); } if (cacheSize != DEFAULT_CACHE_SIZE) { if (cacheSize == 1) { builder.append(" NO CACHE"); } else if (cacheSize > DEFAULT_CACHE_SIZE // || cacheSize != getMaxCacheSize(maxValue - minValue, increment)) { builder.append(" CACHE ").append(cacheSize); } } return builder; } /** * Get the next value for this sequence. Should not be called directly, use * {@link SessionLocal#getNextValueFor(Sequence, org.h2.command.Prepared)} instead. * * @param session the session * @return the next value */ public Value getNext(SessionLocal session) { long result; boolean needsFlush; synchronized (this) { if (cycle == Cycle.EXHAUSTED) { throw DbException.get(ErrorCode.SEQUENCE_EXHAUSTED, getName()); } result = baseValue; long newBase = result + increment; needsFlush = increment > 0 ? increment(result, newBase) : decrement(result, newBase); } if (needsFlush) { flush(session); } return ValueBigint.get(result).castTo(dataType, session); } private boolean increment(long oldBase, long newBase) { boolean needsFlush = false; /* * If old base is not negative and new base is negative there is an * overflow. */ if (newBase > maxValue || (~oldBase & newBase) < 0) { newBase = minValue; needsFlush = true; if (cycle == Cycle.CYCLE) { margin = newBase + increment * (cacheSize - 1); } else { margin = newBase; cycle = Cycle.EXHAUSTED; } } else if (newBase > margin) { long newMargin = newBase + increment * (cacheSize - 1); if (newMargin > maxValue || (~newBase & newMargin) < 0) { /* * Don't cache values near the end of the sequence for * simplicity. */ newMargin = newBase; } margin = newMargin; needsFlush = true; } baseValue = newBase; return needsFlush; } private boolean decrement(long oldBase, long newBase) { boolean needsFlush = false; /* * If old base is negative and new base is not negative there is an * overflow. */ if (newBase < minValue || (oldBase & ~newBase) < 0) { newBase = maxValue; needsFlush = true; if (cycle == Cycle.CYCLE) { margin = newBase + increment * (cacheSize - 1); } else { margin = newBase; cycle = Cycle.EXHAUSTED; } } else if (newBase < margin) { long newMargin = newBase + increment * (cacheSize - 1); if (newMargin < minValue || (newBase & ~newMargin) < 0) { /* * Don't cache values near the end of the sequence for * simplicity. */ newMargin = newBase; } margin = newMargin; needsFlush = true; } baseValue = newBase; return needsFlush; } /** * Flush the current value to disk. */ public void flushWithoutMargin() { if (margin != baseValue) { margin = baseValue; flush(null); } } /** * Flush the current value, including the margin, to disk. * * @param session the session */ public void flush(SessionLocal session) { if (isTemporary()) { return; } if (session == null || !database.isSysTableLockedBy(session)) { // This session may not lock the sys table (except if it has already // locked it) because it must be committed immediately, otherwise // other threads can not access the sys table. SessionLocal sysSession = database.getSystemSession(); synchronized (sysSession) { flushInternal(sysSession); sysSession.commit(false); } } else { synchronized (session) { flushInternal(session); } } } private void flushInternal(SessionLocal session) { final boolean metaWasLocked = database.lockMeta(session); // just for this case, use the value with the margin try { writeWithMargin = true; database.updateMeta(session, this); } finally { writeWithMargin = false; if (!metaWasLocked) { database.unlockMeta(session); } } } /** * Flush the current value to disk and close this object. */ public void close() { flushWithoutMargin(); } @Override public int getType() { return DbObject.SEQUENCE; } @Override public void removeChildrenAndResources(SessionLocal session) { database.removeMeta(session, getId()); invalidate(); } public synchronized long getBaseValue() { // Use synchronized because baseValue is not volatile return baseValue; } public synchronized long getCurrentValue() { return baseValue - increment; } public void setBelongsToTable(boolean b) { this.belongsToTable = b; } public long getCacheSize() { return cacheSize; } }
Detected license expression

      
    
Detected license expression (SPDX)

      
    
Percentage of license text
0.63
Copyrights
- end_line: 2
  copyright: Copyright 2004-2023 H2 Group. Multiple-Licensed
  start_line: 2
Holders
- holder: H2 Group. Multiple-Licensed
  end_line: 2
  start_line: 2
Authors

      
    
License expression License clue details
(mpl-2.0 OR epl-1.0) AND proprietary-license {'score': 20.37, 'matcher': '3-seq', 'end_line': 3, 'rule_url': 'https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'from_file': None, 'start_line': 2, 'matched_text': ' * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,\n * and the EPL 1.0 (https://h2database.com/html/license.html).', 'match_coverage': 20.37, 'matched_length': 11, 'rule_relevance': 100, 'rule_identifier': 'mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'license_expression': '(mpl-2.0 OR epl-1.0) AND proprietary-license', 'license_expression_spdx': '(MPL-2.0 OR EPL-1.0) AND LicenseRef-scancode-proprietary-license'}
URL Start line End line
https://h2database.com/html/license.html 3 3
Package URL License Primary language
pkg:osgi/com.h2database.source@2.2.220