001: /* =============================================================
002: * SmallSQL : a free Java DBMS library for the Java(tm) platform
003: * =============================================================
004: *
005: * (C) Copyright 2004-2007, by Volker Berlin.
006: *
007: * Project Info: http://www.smallsql.de/
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * ---------------
028: * CommandInsert.java
029: * ---------------
030: * Author: Volker Berlin
031: *
032: */
033: package smallsql.database;
034:
035: import java.sql.SQLException;
036: import java.util.ArrayList;
037: import smallsql.database.language.Language;
038:
039: public class CommandInsert extends Command {
040:
041: boolean noColumns; // after the table name was no columnExpressions; all columnExpressions in default order
042: private CommandSelect cmdSel;
043:
044: private Table table;
045: private long tableTimestamp;
046: private int[] matrix; // mapping of the columns from INSERT to the columns in the Table; -1 default Value
047:
048: CommandInsert(Logger log, String name) {
049: super (log);
050: this .name = name;
051: }
052:
053: void addColumnExpression(Expression column) throws SQLException {
054: if (columnExpressions.indexOf(column) >= 0) {
055: throw SmallSQLException.create(Language.COL_DUPLICATE,
056: column);
057: }
058: super .addColumnExpression(column);
059: }
060:
061: void addValues(Expressions values) {
062: // this.values = values;
063: this .cmdSel = new CommandSelect(log, values);
064: }
065:
066: void addValues(CommandSelect cmdSel) {
067: this .cmdSel = cmdSel;
068: }
069:
070: /**
071: * The method compile set all needed reference links after the Parsing
072: */
073: private void compile(SSConnection con) throws Exception {
074: TableView tableView = con.getDatabase(false).getTableView(con,
075: name);
076: if (!(tableView instanceof Table))
077: throw SmallSQLException.create(Language.VIEW_INSERT);
078: table = (Table) tableView;
079: tableTimestamp = table.getTimestamp();
080: cmdSel.compile(con);
081: int count = table.columns.size();
082: matrix = new int[count];
083: if (noColumns) {
084: // noColumns means a table without Columns like INSERT INTO mytable VALUES(1,2)
085: // in this case all columnExpressions of the table need to use
086: columnExpressions.clear();
087: for (int i = 0; i < count; i++) {
088: matrix[i] = i;
089: }
090: if (count != cmdSel.columnExpressions.size())
091: throw SmallSQLException
092: .create(Language.COL_VAL_UNMATCH);
093: } else {
094: for (int i = 0; i < count; i++)
095: matrix[i] = -1;
096: for (int c = 0; c < columnExpressions.size(); c++) {
097: // listing of the column names in the INSERT SQL expression
098: Expression sqlCol = columnExpressions.get(c);
099: String sqlColName = sqlCol.getName();
100: int idx = table.findColumnIdx(sqlColName);
101: if (idx >= 0) {
102: matrix[idx] = c;
103: } else {
104: throw SmallSQLException.create(
105: Language.COL_MISSING, sqlColName);
106: }
107: }
108: if (columnExpressions.size() != cmdSel.columnExpressions
109: .size())
110: throw SmallSQLException
111: .create(Language.COL_VAL_UNMATCH);
112: }
113: }
114:
115: void executeImpl(SSConnection con, SSStatement st) throws Exception {
116: // on first time and on change of the table we need to recompile
117: if (table == null || tableTimestamp != table.getTimestamp())
118: compile(con);
119:
120: final IndexDescriptions indexes = table.indexes;
121:
122: updateCount = 0;
123: cmdSel.from.execute();
124: cmdSel.beforeFirst();
125:
126: //Variables for GeneratedKeys
127: Strings keyColumnNames = null;
128: ArrayList keys = null;
129: boolean needGeneratedKeys = st.needGeneratedKeys();
130: int generatedKeysType = 0;
131:
132: while (cmdSel.next()) {
133: if (needGeneratedKeys) {
134: keyColumnNames = new Strings();
135: keys = new ArrayList();
136: if (st.getGeneratedKeyNames() != null)
137: generatedKeysType = 1;
138: if (st.getGeneratedKeyIndexes() != null)
139: generatedKeysType = 2;
140: }
141: StoreImpl store = table.getStoreInsert(con);
142: for (int c = 0; c < matrix.length; c++) {
143: Column column = table.columns.get(c);
144: int idx = matrix[c];
145: Expression valueExpress;
146: if (idx >= 0) {
147: valueExpress = cmdSel.columnExpressions.get(idx);
148: } else {
149: valueExpress = column.getDefaultValue(con);
150: if (needGeneratedKeys && generatedKeysType == 0
151: && valueExpress != Expression.NULL) {
152: keyColumnNames.add(column.getName());
153: keys.add(valueExpress.getObject());
154: }
155: }
156: if (needGeneratedKeys && generatedKeysType == 1) {
157: String[] keyNames = st.getGeneratedKeyNames();
158: for (int i = 0; i < keyNames.length; i++) {
159: if (column.getName().equalsIgnoreCase(
160: keyNames[i])) {
161: keyColumnNames.add(column.getName());
162: keys.add(valueExpress.getObject());
163: break;
164: }
165: }
166: }
167: if (needGeneratedKeys && generatedKeysType == 2) {
168: int[] keyIndexes = st.getGeneratedKeyIndexes();
169: for (int i = 0; i < keyIndexes.length; i++) {
170: if (c + 1 == keyIndexes[i]) {
171: keyColumnNames.add(column.getName());
172: keys.add(valueExpress.getObject());
173: break;
174: }
175: }
176: }
177: store.writeExpression(valueExpress, column);
178: for (int i = 0; i < indexes.size(); i++) {
179: indexes.get(i).writeExpression(c, valueExpress);
180: }
181: }
182: store.writeFinsh(con);
183: for (int i = 0; i < indexes.size(); i++) {
184: indexes.get(i).writeFinish(con);
185: }
186: updateCount++;
187: if (needGeneratedKeys) {
188: Object[][] data = new Object[1][keys.size()];
189: keys.toArray(data[0]);
190: st.setGeneratedKeys(new SSResultSet(st, Utils
191: .createMemoryCommandSelect(con, keyColumnNames
192: .toArray(), data)));
193: }
194: }
195: }
196:
197: }
|