Quadcap Embeddable Database

com/quadcap/sql/AutoNumberConstraint.java

Go to the documentation of this file.
00001 package com.quadcap.sql; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.Externalizable; 00042 import java.io.IOException; 00043 import java.io.ObjectInput; 00044 import java.io.ObjectOutput; 00045 00046 import java.sql.SQLException; 00047 00048 import com.quadcap.sql.types.TypeBigInt; 00049 import com.quadcap.sql.types.Value; 00050 import com.quadcap.sql.types.ValueLong; 00051 00052 import com.quadcap.util.Debug; 00053 00054 /** 00055 * Constraint class for SQL <b>AUTO_NUMBER</b> constraints. 00056 * 00057 * @author Stan Bailes 00058 */ 00059 public class AutoNumberConstraint 00060 extends Constraint implements Externalizable 00061 { 00062 transient AutoNumberStep step; 00063 00064 long current = -1; 00065 00066 /** 00067 * Default constructor 00068 */ 00069 public AutoNumberConstraint() {} 00070 00071 /** 00072 * Explicit name constructor 00073 */ 00074 public AutoNumberConstraint(String name) { 00075 super(name); 00076 } 00077 00078 /** 00079 * When added, I need to number all rows which already exist in the 00080 * table 00081 */ 00082 public void add(Session session) throws SQLException { 00083 if (!table.isUnderConstruction()) { 00084 try { 00085 Column col = getColumn(); 00086 col.isAutoIncr = true; 00087 session.getDatabase().updateRelation(table); 00088 } catch (IOException e) { 00089 throw DbException.wrapThrowable(e); 00090 } 00091 } 00092 } 00093 00094 /** 00095 * My column is no longer an auto-incrementer 00096 */ 00097 public void delete(Session session) throws SQLException, IOException { 00098 Column col = getColumn(); 00099 col.isAutoIncr = false; 00100 session.getDatabase().updateRelation(table); 00101 } 00102 00103 /** 00104 * Our work is already done. (We gave out the number in checkInsert()) 00105 */ 00106 public void applyInsert(Session session, Row row, long rowId, 00107 Constraint activeIndex) 00108 throws SQLException, IOException 00109 { 00110 } 00111 00112 /** 00113 * We don't care about deletes. 00114 */ 00115 public void checkDelete(Session session, Row row, long rowId) 00116 throws SQLException, IOException 00117 { 00118 } 00119 00120 /** 00121 * We don't care about deletes. 00122 */ 00123 public void applyDelete(Session session, Row row, long rowId, 00124 Constraint activeIndex) 00125 throws SQLException, IOException 00126 { 00127 } 00128 00129 static Object stepLock = new Object(); 00130 00131 /** 00132 * If the 'with identity' field is null or not an integer 00133 * we assign the number before the insert operation and increment 00134 * our little counter. 00135 */ 00136 public void checkInsert(Session session, Row row) 00137 throws SQLException, IOException 00138 { 00139 Column c = getColumn(); 00140 int col = c.getColumn(); 00141 boolean incr = false; 00142 Value v = row.item(col); 00143 Database db = session.getDatabase(); 00144 00145 if (Value.isNull(v)) { 00146 incr = true; 00147 } else { 00148 Value t = v.convert(TypeBigInt.typeBigInt); 00149 if (!(t instanceof ValueLong)) { 00150 incr = true; 00151 } else { 00152 ValueLong l = (ValueLong)t; 00153 current = db.getTableIdentity(table.getName()); 00154 if (l.longValue() >= current) { 00155 current = l.longValue() + 1; 00156 synchronized (stepLock) { 00157 if (step == null) { 00158 step = new AutoNumberStep(session, table, current); 00159 } else { 00160 step.setCurrentId(current); 00161 } 00162 session.doStep(step); // go ahead and do it... 00163 } 00164 } 00165 } 00166 } 00167 00168 if (incr) { 00169 if (true || current < 0) { 00170 // XXX We can't optimize this away in all cases, because 00171 // XXX the value of 'current' that's stored locally may 00172 // XXX be wrong. This can happen if the table containing 00173 // XXX this constraint isn't updated properly. 00174 current = db.getTableIdentity(table.getName()); 00175 } 00176 session.setLastInsertId(current); 00177 row.set(col, new ValueLong(current++)); 00178 // we avoid an allocation per step by doing a static allocation, 00179 // but then we need to protect the shared resource from contention 00180 synchronized (stepLock) { 00181 if (step == null) { 00182 step = new AutoNumberStep(session, table, current); 00183 } else { 00184 step.setCurrentId(current); 00185 } 00186 session.doStep(step); // go ahead and do it... 00187 } 00188 } 00189 } 00190 00191 /** 00192 * We only operate during INSERT, basically. 00193 */ 00194 public void checkUpdate(Session session, byte[] oldKey, Row row, 00195 Row oldRow, long rowId, Constraint activeIndex) 00196 throws SQLException, IOException 00197 { 00198 } 00199 00200 /** 00201 * 's cool. 00202 */ 00203 public void applyUpdate(Session session, byte[] oldKey, Row row, 00204 Row oldRow, long rowId, Constraint activeIndex) 00205 throws SQLException, IOException 00206 { 00207 } 00208 00209 /** 00210 * Where did I leave off? 00211 */ 00212 public void readExternal(ObjectInput in) 00213 throws IOException, ClassNotFoundException 00214 { 00215 super.readExternal(in); 00216 current = in.readLong(); 00217 } 00218 00219 /** 00220 * Remember where we were. 00221 */ 00222 public void writeExternal(ObjectOutput out) throws IOException { 00223 super.writeExternal(out); 00224 out.writeLong(current); 00225 } 00226 00227 /** 00228 * Do me first. 00229 */ 00230 public int getPriority() { return 0; } 00231 }