1 | /* ============================================================= |
2 | * SmallSQL : a free Java DBMS library for the Java(tm) platform |
3 | * ============================================================= |
4 | * |
5 | * (C) Copyright 2004-2006, by Volker Berlin. |
6 | * |
7 | * Project Info: http://www.smallsql.de/ |
8 | * |
9 | * This library is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU Lesser General Public License as published by |
11 | * the Free Software Foundation; either version 2.1 of the License, or |
12 | * (at your option) any later version. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
17 | * License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with this library; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
22 | * USA. |
23 | * |
24 | * [Java is a trademark or registered trademark of Sun Microsystems, Inc. |
25 | * in the United States and other countries.] |
26 | * |
27 | * --------------- |
28 | * CommandInsert.java |
29 | * --------------- |
30 | * Author: Volker Berlin |
31 | * |
32 | */ |
33 | package smallsql.database; |
34 | |
35 | import java.util.ArrayList; |
36 | |
37 | |
38 | |
39 | public class CommandInsert extends Command { |
40 | |
41 | boolean noColumns; // after the table name was no columnExpressions; all columnExpressions in default order |
42 | private CommandSelect cmdSel; |
43 | |
44 | private Table table; |
45 | private long tableTimestamp; |
46 | private int[] matrix; // mapping der Spalten vom INSERT zu den Spalten in der Tabelle; -1 default Value |
47 | |
48 | CommandInsert( Logger log, String name ){ |
49 | super(log); |
50 | this.name = name; |
51 | } |
52 | |
53 | void addValues( Expressions values ){ |
54 | //this.values = values; |
55 | this.cmdSel = new CommandSelect(log, values ); |
56 | } |
57 | |
58 | |
59 | void addValues( CommandSelect cmdSel ){ |
60 | this.cmdSel = cmdSel; |
61 | } |
62 | |
63 | /** |
64 | * The method compile set all needed referenz links after the Parsing |
65 | */ |
66 | private void compile(SSConnection con) throws Exception{ |
67 | TableView tableView = con.getDatabase(false).getTableView( con, name); |
68 | if(!(tableView instanceof Table)) |
69 | throw Utils.createSQLException("INSERT is not supported for a VIEW."); |
70 | table = (Table)tableView; |
71 | tableTimestamp = table.getTimestamp(); |
72 | cmdSel.compile(con); |
73 | int count = table.columns.size(); |
74 | matrix = new int[count]; |
75 | if(noColumns){ |
76 | // noColumns means a table without Columns like INSERT INTO mytable VALUES(1,2) |
77 | // in this case all columnExpressions of the table need to use |
78 | columnExpressions.clear(); |
79 | for(int i=0; i<count; i++){ |
80 | matrix[i] = i; |
81 | } |
82 | if(count != cmdSel.columnExpressions.size()) |
83 | throw Utils.createSQLException("Columns and Values count is not identical."); |
84 | }else{ |
85 | for(int i=0; i<count; i++) matrix[i] = -1; |
86 | for(int c=0; c<columnExpressions.size(); c++){ |
87 | // Auflistung der Spaltennamen in INSERT SQL expression |
88 | Expression sqlCol = columnExpressions.get(c); |
89 | String sqlColName = sqlCol.getName(); |
90 | int idx = table.findColumnIdx( sqlColName ); |
91 | if(idx >= 0){ |
92 | matrix[idx] = c; |
93 | }else{ |
94 | throw Utils.createSQLException("Column name '" + sqlColName + "' not found."); |
95 | } |
96 | } |
97 | if(columnExpressions.size() != cmdSel.columnExpressions.size()) |
98 | throw Utils.createSQLException("Columns and Values count is not identical."); |
99 | } |
100 | } |
101 | |
102 | |
103 | |
104 | void executeImpl(SSConnection con, SSStatement st) throws Exception { |
105 | // beim Erstenmal und bei änderung der Tabelle neu kompilieren |
106 | if(table == null || tableTimestamp != table.getTimestamp()) compile( con ); |
107 | |
108 | final IndexDescriptions indexes = table.indexes; |
109 | |
110 | updateCount = 0; |
111 | cmdSel.join.execute(); |
112 | cmdSel.beforeFirst(); |
113 | |
114 | //Variables for GeneratedKeys |
115 | Strings keyColumnNames = null; |
116 | ArrayList keys = null; |
117 | boolean needGeneratedKeys = st.needGeneratedKeys(); |
118 | int generatedKeysType = 0; |
119 | |
120 | while(cmdSel.next()){ |
121 | if(needGeneratedKeys){ |
122 | keyColumnNames = new Strings(); |
123 | keys = new ArrayList(); |
124 | if(st.getGeneratedKeyNames() != null) |
125 | generatedKeysType = 1; |
126 | if(st.getGeneratedKeyIndexes() != null) |
127 | generatedKeysType = 2; |
128 | } |
129 | StoreImpl store = table.getStoreInsert( con ); |
130 | for(int c=0; c<matrix.length; c++){ |
131 | Column column = table.columns.get(c); |
132 | int idx = matrix[c]; |
133 | Expression valueExpress; |
134 | if(idx >= 0){ |
135 | valueExpress = cmdSel.columnExpressions.get(idx); |
136 | }else{ |
137 | valueExpress = column.getDefaultValue(con); |
138 | if(needGeneratedKeys && generatedKeysType == 0 && valueExpress != Expression.NULL){ |
139 | keyColumnNames.add(column.getName()); |
140 | keys.add(valueExpress.getObject()); |
141 | } |
142 | } |
143 | if(needGeneratedKeys && generatedKeysType == 1){ |
144 | String[] keyNames = st.getGeneratedKeyNames(); |
145 | for(int i=0; i<keyNames.length; i++){ |
146 | if(column.getName().equalsIgnoreCase(keyNames[i])){ |
147 | keyColumnNames.add(column.getName()); |
148 | keys.add(valueExpress.getObject()); |
149 | break; |
150 | } |
151 | } |
152 | } |
153 | if(needGeneratedKeys && generatedKeysType == 2){ |
154 | int[] keyIndexes = st.getGeneratedKeyIndexes(); |
155 | for(int i=0; i<keyIndexes.length; i++){ |
156 | if(c+1 == keyIndexes[i]){ |
157 | keyColumnNames.add(column.getName()); |
158 | keys.add(valueExpress.getObject()); |
159 | break; |
160 | } |
161 | } |
162 | } |
163 | store.writeExpression( valueExpress, column ); |
164 | for(int i=0; i<indexes.size(); i++){ |
165 | indexes.get(i).writeExpression( c, valueExpress ); |
166 | } |
167 | } |
168 | store.writeFinsh( con ); |
169 | StorePageLink link = store.getLink(); |
170 | for(int i=0; i<indexes.size(); i++){ |
171 | indexes.get(i).writeFinsh( con ); |
172 | } |
173 | updateCount++; |
174 | if(needGeneratedKeys){ |
175 | Object[][] data = new Object[1][keys.size()]; |
176 | keys.toArray(data[0]); |
177 | st.setGeneratedKeys(new SSResultSet( st, Utils.createMemoryCommandSelect( con, keyColumnNames.toArray(), data))); |
178 | } |
179 | } |
180 | } |
181 | |
182 | } |