001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.schema;
007:
008: import java.sql.SQLException;
009:
010: import org.h2.constant.ErrorCode;
011: import org.h2.engine.DbObject;
012: import org.h2.engine.Session;
013: import org.h2.message.Message;
014: import org.h2.message.Trace;
015: import org.h2.table.Table;
016:
017: /**
018: *A sequence is created using the statement
019: * CREATE SEQUENCE
020: */
021: public class Sequence extends SchemaObjectBase {
022: public static final int DEFAULT_CACHE_SIZE = 32;
023: private long value = 1;
024: private long valueWithMargin;
025: private long increment = 1;
026: private long cacheSize = DEFAULT_CACHE_SIZE;
027: private boolean belongsToTable;
028:
029: public Sequence(Schema schema, int id, String name,
030: boolean belongsToTable) {
031: super (schema, id, name, Trace.SEQUENCE);
032: this .belongsToTable = belongsToTable;
033: }
034:
035: public synchronized void setStartValue(long value) {
036: this .value = value;
037: this .valueWithMargin = value;
038: }
039:
040: public boolean getBelongsToTable() {
041: return belongsToTable;
042: }
043:
044: public long getIncrement() {
045: return increment;
046: }
047:
048: public void setIncrement(long inc) throws SQLException {
049: if (inc == 0) {
050: throw Message.getSQLException(ErrorCode.INVALID_VALUE_2,
051: new String[] { "0", "INCREMENT" }, null);
052: }
053: this .increment = inc;
054: }
055:
056: public String getDropSQL() {
057: if (getBelongsToTable()) {
058: return null;
059: }
060: return "DROP SEQUENCE IF EXISTS " + getSQL();
061: }
062:
063: public String getCreateSQLForCopy(Table table, String quotedName) {
064: throw Message.getInternalError();
065: }
066:
067: public synchronized String getCreateSQL() {
068: StringBuffer buff = new StringBuffer();
069: buff.append("CREATE SEQUENCE ");
070: buff.append(getSQL());
071: buff.append(" START WITH ");
072: buff.append(value);
073: if (increment != 1) {
074: buff.append(" INCREMENT BY ");
075: buff.append(increment);
076: }
077: if (cacheSize != DEFAULT_CACHE_SIZE) {
078: buff.append(" CACHE ");
079: buff.append(cacheSize);
080: }
081: if (belongsToTable) {
082: buff.append(" BELONGS_TO_TABLE");
083: }
084: return buff.toString();
085: }
086:
087: public synchronized long getNext() throws SQLException {
088: if ((increment > 0 && value >= valueWithMargin)
089: || (increment < 0 && value <= valueWithMargin)) {
090: valueWithMargin += increment * cacheSize;
091: flush();
092: }
093: long v = value;
094: value += increment;
095: return v;
096: }
097:
098: public void flush() throws SQLException {
099: // can not use the session, because it must be committed immediately
100: // otherwise other threads can not access the sys table.
101: Session s = database.getSystemSession();
102: synchronized (this ) {
103: // just for this case, use the value with the margin for the script
104: long realValue = value;
105: try {
106: value = valueWithMargin;
107: database.update(s, this );
108: } finally {
109: value = realValue;
110: }
111: }
112: s.commit(false);
113: }
114:
115: public void close() throws SQLException {
116: valueWithMargin = value;
117: flush();
118: }
119:
120: public int getType() {
121: return DbObject.SEQUENCE;
122: }
123:
124: public void removeChildrenAndResources(Session session)
125: throws SQLException {
126: database.removeMeta(session, getId());
127: invalidate();
128: }
129:
130: public void checkRename() {
131: // nothing to do
132: }
133:
134: public synchronized long getCurrentValue() {
135: return value - increment;
136: }
137:
138: public void setBelongsToTable(boolean b) {
139: this .belongsToTable = b;
140: }
141:
142: public void setCacheSize(long cacheSize) {
143: this .cacheSize = cacheSize;
144: }
145:
146: public long getCacheSize() {
147: return cacheSize;
148: }
149:
150: }
|