Quadcap Embeddable Database

com/quadcap/sql/StmtInsert.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.util.Vector; 00042 00043 import java.io.IOException; 00044 00045 import java.sql.SQLException; 00046 00047 import com.quadcap.sql.types.Value; 00048 import com.quadcap.sql.types.ValueDefault; 00049 import com.quadcap.sql.types.ValueNull; 00050 00051 00052 /** 00053 * Implementation of the SQL <b>INSERT</b> statement. 00054 * 00055 * @author Stan Bailes 00056 */ 00057 00058 public class StmtInsert implements Stmt { 00059 String tableName; 00060 Vector columns; 00061 Expression values; 00062 00063 boolean defaultValues = false; 00064 VectorExpression ve = null; 00065 Row tempRow = null; 00066 00067 Relation table = null; 00068 00069 public StmtInsert() {} 00070 00071 public StmtInsert(String tableName) { 00072 this.tableName = tableName; 00073 } 00074 00075 public void setDefaultValue() { 00076 this.defaultValues = true; 00077 } 00078 00079 public void setColumns(Vector v) { 00080 this.columns = v; 00081 } 00082 00083 public void setValues(Expression e) { 00084 this.values = e; 00085 } 00086 00087 final Value getDefault(Session session, Cursor cursor, Column c) 00088 throws SQLException 00089 { 00090 Value dflt = ValueNull.valueNull; 00091 Expression e = c.getDefault(); 00092 if (e != null) { 00093 dflt = e.getValue(session, cursor); 00094 } 00095 return dflt; 00096 } 00097 00098 public void setVrow(Session session, VectorExpression ve) 00099 throws IOException, SQLException 00100 { 00101 if (ve.size() != tempRow.size()) { 00102 throw new SQLException("Incorrect number of columns: " + 00103 ve.size() + 00104 "; expecting " + 00105 tempRow.size()); 00106 } 00107 for (int col = 1; col <= tempRow.size(); col++) { 00108 Value v = ve.get(col-1).getValue(session, null); 00109 if (v instanceof ValueDefault) { 00110 Column c = table.getColumn(col); 00111 v = getDefault(session, null, c); 00112 } 00113 tempRow.set(col, v); 00114 } 00115 table.insertRow(session, tempRow); 00116 } 00117 00118 public void execute(Session session) throws IOException, SQLException { 00119 Database db = session.getDatabase(); 00120 if (table == null) { 00121 table = db.getRelation(tableName); 00122 if (table == null) { 00123 throw new SQLException("No table: " + tableName, "42000"); 00124 } 00125 } 00126 if (columns == null) { 00127 if (ve != null || values instanceof VectorExpression) { 00128 // we can do something optimal here.... 00129 if (ve == null) ve = (VectorExpression)values; 00130 if (tempRow == null) tempRow = new Row(table.getColumnCount()); 00131 if (ve.rank() == 1) { 00132 setVrow(session, ve); 00133 return; 00134 } else if (ve.rank() == 2) { 00135 for (int row = 0; row < ve.size(); row++) { 00136 VectorExpression vr = (VectorExpression)ve.get(row); 00137 setVrow(session, vr); 00138 } 00139 return; 00140 } 00141 } 00142 } 00143 00144 // less-than-optimal but full-featured insert implementation 00145 Cursor cursor = null; 00146 if (values != null) { 00147 cursor = values.getCursor(session, null); 00148 } 00149 00150 if (isSelfInsert()) { 00151 DistinctCursor dc = new DistinctCursor(session, cursor); 00152 dc.setDistinct(false); 00153 cursor = dc; 00154 } 00155 try { 00156 if (defaultValues) { 00157 if (tempRow == null) tempRow = new Row(table.getColumnCount()); 00158 for (int col = 1; col <= tempRow.size(); col++) { 00159 Column c = table.getColumn(col); 00160 Value dflt = getDefault(session, cursor, c); 00161 tempRow.set(col, dflt); 00162 } 00163 table.insertRow(session, tempRow); 00164 } else if (columns == null) { 00165 if (cursor.getColumnCount() != table.getColumnCount()) { 00166 throw new SQLException("Incorrect number of columns: " + 00167 cursor.getColumnCount() + 00168 "; expecting " + 00169 table.getColumnCount()); 00170 } 00171 if (cursor instanceof StaticCursor) { 00172 // XXX is this right? Can defaults show up in other 00173 // XXX cursor types? 00174 while (cursor.next()) { 00175 Row r = cursor.getRow(); 00176 for (int i = 1; i <= r.size(); i++) { 00177 Value v = r.item(i); 00178 if (v instanceof ValueDefault) { 00179 Column c = table.getColumn(i); 00180 v = getDefault(session, cursor, c); 00181 r.set(i, v); 00182 } 00183 } 00184 table.insertRow(session, r); 00185 } 00186 } else if (table.hasBlobs()) { 00187 // We may have to passivate the blobs, but it's possible 00188 // that the rows that we get back aren't updateable 00189 // (e.g., insert into TAB select from TAB2, TAB3) 00190 if (tempRow == null) { 00191 tempRow = new Row(table.getColumnCount()); 00192 } 00193 while (cursor.next()) { 00194 Row r = cursor.getRow(); 00195 for (int i = 1; i <= table.getColumnCount(); i++) { 00196 tempRow.set(i, r.item(i)); 00197 } 00198 table.insertRow(session, tempRow); 00199 } 00200 } else { 00201 while (cursor.next()) { 00202 Row r = cursor.getRow(); 00203 table.insertRow(session, r); 00204 } 00205 } 00206 } else { 00207 if (tempRow == null) { 00208 tempRow = new Row(table.getColumnCount()); 00209 } 00210 int[] map = table.mapColumns(columns); 00211 int[] nmap = null; 00212 // make a map to quickly find columns that need defaults 00213 if (map.length < table.getColumnCount()) { 00214 int[] cmap = new int[table.getColumnCount()]; 00215 for (int i = 0; i < map.length; i++) { 00216 cmap[map[i]-1] = 1; 00217 } 00218 nmap = new int[cmap.length - map.length]; 00219 int ncnt = 0; 00220 for (int i = 0; i < cmap.length; i++) { 00221 if (cmap[i] == 0) { 00222 nmap[ncnt++] = i+1; 00223 } 00224 } 00225 } 00226 while (cursor.next()) { 00227 Row row = cursor.getRow(); 00228 for (int i = 0; i < map.length; i++) { 00229 Value v = row.item(i+1); 00230 if (v instanceof ValueDefault) { 00231 Column c = table.getColumn(map[i]); 00232 v = getDefault(session, cursor, c); 00233 } 00234 tempRow.set(map[i], v); 00235 } 00236 if (nmap != null) { 00237 // fill in null/default values 00238 for (int i = 0; i < nmap.length; i++) { 00239 int col = nmap[i]; 00240 Column c = table.getColumn(col); 00241 Value dflt = getDefault(session, cursor, c); 00242 tempRow.set(col, dflt); 00243 } 00244 } 00245 table.insertRow(session, tempRow); 00246 } 00247 } 00248 } finally { 00249 if (cursor != null) cursor.close(); 00250 } 00251 } 00252 00253 class IsSelfInsert implements ExpressionVisitor { 00254 boolean isit = false; 00255 00256 public void visit(Expression sub) { 00257 if (!isit) { 00258 if (sub instanceof SelectExpression) { 00259 Vector v = new Vector(); 00260 SelectExpression se = (SelectExpression)sub; 00261 se.getBaseTables(v); 00262 for (int i = 0; !isit && i < v.size(); i++) { 00263 String name = v.get(i).toString(); 00264 isit = name.equalsIgnoreCase(tableName); 00265 } 00266 } else { 00267 sub.visitSubExpressions(this); 00268 } 00269 } 00270 } 00271 } 00272 00273 boolean isSelfInsert() { 00274 boolean ret = false; 00275 if (values != null) { 00276 IsSelfInsert is = new IsSelfInsert(); 00277 is.visit(values); 00278 ret = is.isit; 00279 } 00280 return ret; 00281 } 00282 } 00283