EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.command.ddl]

COVERAGE SUMMARY FOR SOURCE FILE [CreateTable.java]

nameclass, %method, %block, %line, %
CreateTable.java100% (1/1)95%  (20/21)98%  (654/667)97%  (162/167)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CreateTable100% (1/1)95%  (20/21)98%  (654/667)97%  (162/167)
setSortedInsertMode (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
setPrimaryKeyColumns (IndexColumn []): boolean 100% (1/1)93%  (39/42)90%  (9/10)
generateColumnsFromQuery (): void 100% (1/1)94%  (93/99)89%  (17/19)
CreateTable (Session, Schema): void 100% (1/1)100% (21/21)100% (6/6)
addColumn (Column): void 100% (1/1)100% (7/7)100% (2/2)
addConstraintCommand (DefineCommand): void 100% (1/1)100% (32/32)100% (9/9)
getType (): int 100% (1/1)100% (2/2)100% (1/1)
setComment (String): void 100% (1/1)100% (4/4)100% (2/2)
setGlobalTemporary (boolean): void 100% (1/1)100% (5/5)100% (2/2)
setHidden (boolean): void 100% (1/1)100% (5/5)100% (2/2)
setIfNotExists (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setOnCommitDrop (): void 100% (1/1)100% (4/4)100% (2/2)
setOnCommitTruncate (): void 100% (1/1)100% (4/4)100% (2/2)
setPersistData (boolean): void 100% (1/1)100% (11/11)100% (4/4)
setPersistIndexes (boolean): void 100% (1/1)100% (5/5)100% (2/2)
setQuery (Query): void 100% (1/1)100% (4/4)100% (2/2)
setTableEngine (String): void 100% (1/1)100% (5/5)100% (2/2)
setTableEngineParams (ArrayList): void 100% (1/1)100% (5/5)100% (2/2)
setTableName (String): void 100% (1/1)100% (5/5)100% (2/2)
setTemporary (boolean): void 100% (1/1)100% (5/5)100% (2/2)
update (): int 100% (1/1)100% (394/394)100% (90/90)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.command.ddl;
7 
8import java.util.ArrayList;
9import java.util.HashSet;
10 
11import org.h2.api.ErrorCode;
12import org.h2.command.CommandInterface;
13import org.h2.command.dml.Insert;
14import org.h2.command.dml.Query;
15import org.h2.engine.Database;
16import org.h2.engine.DbObject;
17import org.h2.engine.Session;
18import org.h2.expression.Expression;
19import org.h2.message.DbException;
20import org.h2.schema.Schema;
21import org.h2.schema.Sequence;
22import org.h2.table.Column;
23import org.h2.table.IndexColumn;
24import org.h2.table.Table;
25import org.h2.util.New;
26import org.h2.value.DataType;
27 
28/**
29 * This class represents the statement
30 * CREATE TABLE
31 */
32public class CreateTable extends SchemaCommand {
33 
34    private final CreateTableData data = new CreateTableData();
35    private final ArrayList<DefineCommand> constraintCommands = New.arrayList();
36    private IndexColumn[] pkColumns;
37    private boolean ifNotExists;
38    private boolean onCommitDrop;
39    private boolean onCommitTruncate;
40    private Query asQuery;
41    private String comment;
42    private boolean sortedInsertMode;
43 
44    public CreateTable(Session session, Schema schema) {
45        super(session, schema);
46        data.persistIndexes = true;
47        data.persistData = true;
48    }
49 
50    public void setQuery(Query query) {
51        this.asQuery = query;
52    }
53 
54    public void setTemporary(boolean temporary) {
55        data.temporary = temporary;
56    }
57 
58    public void setTableName(String tableName) {
59        data.tableName = tableName;
60    }
61 
62    /**
63     * Add a column to this table.
64     *
65     * @param column the column to add
66     */
67    public void addColumn(Column column) {
68        data.columns.add(column);
69    }
70 
71    /**
72     * Add a constraint statement to this statement.
73     * The primary key definition is one possible constraint statement.
74     *
75     * @param command the statement to add
76     */
77    public void addConstraintCommand(DefineCommand command) {
78        if (command instanceof CreateIndex) {
79            constraintCommands.add(command);
80        } else {
81            AlterTableAddConstraint con = (AlterTableAddConstraint) command;
82            boolean alreadySet;
83            if (con.getType() == CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) {
84                alreadySet = setPrimaryKeyColumns(con.getIndexColumns());
85            } else {
86                alreadySet = false;
87            }
88            if (!alreadySet) {
89                constraintCommands.add(command);
90            }
91        }
92    }
93 
94    public void setIfNotExists(boolean ifNotExists) {
95        this.ifNotExists = ifNotExists;
96    }
97 
98    @Override
99    public int update() {
100        if (!transactional) {
101            session.commit(true);
102        }
103        Database db = session.getDatabase();
104        if (!db.isPersistent()) {
105            data.persistIndexes = false;
106        }
107        if (getSchema().findTableOrView(session, data.tableName) != null) {
108            if (ifNotExists) {
109                return 0;
110            }
111            throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, data.tableName);
112        }
113        if (asQuery != null) {
114            asQuery.prepare();
115            if (data.columns.size() == 0) {
116                generateColumnsFromQuery();
117            } else if (data.columns.size() != asQuery.getColumnCount()) {
118                throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
119            }
120        }
121        if (pkColumns != null) {
122            for (Column c : data.columns) {
123                for (IndexColumn idxCol : pkColumns) {
124                    if (c.getName().equals(idxCol.columnName)) {
125                        c.setNullable(false);
126                    }
127                }
128            }
129        }
130        data.id = getObjectId();
131        data.create = create;
132        data.session = session;
133        boolean isSessionTemporary = data.temporary && !data.globalTemporary;
134        if (!isSessionTemporary) {
135            db.lockMeta(session);
136        }
137        Table table = getSchema().createTable(data);
138        ArrayList<Sequence> sequences = New.arrayList();
139        for (Column c : data.columns) {
140            if (c.isAutoIncrement()) {
141                int objId = getObjectId();
142                c.convertAutoIncrementToSequence(session, getSchema(), objId, data.temporary);
143            }
144            Sequence seq = c.getSequence();
145            if (seq != null) {
146                sequences.add(seq);
147            }
148        }
149        table.setComment(comment);
150        if (isSessionTemporary) {
151            if (onCommitDrop) {
152                table.setOnCommitDrop(true);
153            }
154            if (onCommitTruncate) {
155                table.setOnCommitTruncate(true);
156            }
157            session.addLocalTempTable(table);
158        } else {
159            db.lockMeta(session);
160            db.addSchemaObject(session, table);
161        }
162        try {
163            for (Column c : data.columns) {
164                c.prepareExpression(session);
165            }
166            for (Sequence sequence : sequences) {
167                table.addSequence(sequence);
168            }
169            for (DefineCommand command : constraintCommands) {
170                command.setTransactional(transactional);
171                command.update();
172            }
173            if (asQuery != null) {
174                boolean old = session.isUndoLogEnabled();
175                try {
176                    session.setUndoLogEnabled(false);
177                    session.startStatementWithinTransaction();
178                    Insert insert = null;
179                    insert = new Insert(session);
180                    insert.setSortedInsertMode(sortedInsertMode);
181                    insert.setQuery(asQuery);
182                    insert.setTable(table);
183                    insert.setInsertFromSelect(true);
184                    insert.prepare();
185                    insert.update();
186                } finally {
187                    session.setUndoLogEnabled(old);
188                }
189            }
190            HashSet<DbObject> set = New.hashSet();
191            set.clear();
192            table.addDependencies(set);
193            for (DbObject obj : set) {
194                if (obj == table) {
195                    continue;
196                }
197                if (obj.getType() == DbObject.TABLE_OR_VIEW) {
198                    if (obj instanceof Table) {
199                        Table t = (Table) obj;
200                        if (t.getId() > table.getId()) {
201                            throw DbException.get(
202                                    ErrorCode.FEATURE_NOT_SUPPORTED_1,
203                                    "Table depends on another table " +
204                                    "with a higher ID: " + t +
205                                    ", this is currently not supported, " +
206                                    "as it would prevent the database from " +
207                                    "being re-opened");
208                        }
209                    }
210                }
211            }
212        } catch (DbException e) {
213            db.checkPowerOff();
214            db.removeSchemaObject(session, table);
215            if (!transactional) {
216                session.commit(true);
217            }
218            throw e;
219        }
220        return 0;
221    }
222 
223    private void generateColumnsFromQuery() {
224        int columnCount = asQuery.getColumnCount();
225        ArrayList<Expression> expressions = asQuery.getExpressions();
226        for (int i = 0; i < columnCount; i++) {
227            Expression expr = expressions.get(i);
228            int type = expr.getType();
229            String name = expr.getAlias();
230            long precision = expr.getPrecision();
231            int displaySize = expr.getDisplaySize();
232            DataType dt = DataType.getDataType(type);
233            if (precision > 0 && (dt.defaultPrecision == 0 ||
234                    (dt.defaultPrecision > precision && dt.defaultPrecision < Byte.MAX_VALUE))) {
235                // dont' set precision to MAX_VALUE if this is the default
236                precision = dt.defaultPrecision;
237            }
238            int scale = expr.getScale();
239            if (scale > 0 && (dt.defaultScale == 0 ||
240                    (dt.defaultScale > scale && dt.defaultScale < precision))) {
241                scale = dt.defaultScale;
242            }
243            if (scale > precision) {
244                precision = scale;
245            }
246            Column col = new Column(name, type, precision, scale, displaySize);
247            addColumn(col);
248        }
249    }
250 
251    /**
252     * Sets the primary key columns, but also check if a primary key
253     * with different columns is already defined.
254     *
255     * @param columns the primary key columns
256     * @return true if the same primary key columns where already set
257     */
258    private boolean setPrimaryKeyColumns(IndexColumn[] columns) {
259        if (pkColumns != null) {
260            int len = columns.length;
261            if (len != pkColumns.length) {
262                throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
263            }
264            for (int i = 0; i < len; i++) {
265                if (!columns[i].columnName.equals(pkColumns[i].columnName)) {
266                    throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
267                }
268            }
269            return true;
270        }
271        this.pkColumns = columns;
272        return false;
273    }
274 
275    public void setPersistIndexes(boolean persistIndexes) {
276        data.persistIndexes = persistIndexes;
277    }
278 
279    public void setGlobalTemporary(boolean globalTemporary) {
280        data.globalTemporary = globalTemporary;
281    }
282 
283    /**
284     * This temporary table is dropped on commit.
285     */
286    public void setOnCommitDrop() {
287        this.onCommitDrop = true;
288    }
289 
290    /**
291     * This temporary table is truncated on commit.
292     */
293    public void setOnCommitTruncate() {
294        this.onCommitTruncate = true;
295    }
296 
297    public void setComment(String comment) {
298        this.comment = comment;
299    }
300 
301    public void setPersistData(boolean persistData) {
302        data.persistData = persistData;
303        if (!persistData) {
304            data.persistIndexes = false;
305        }
306    }
307 
308    public void setSortedInsertMode(boolean sortedInsertMode) {
309        this.sortedInsertMode = sortedInsertMode;
310    }
311 
312    public void setTableEngine(String tableEngine) {
313        data.tableEngine = tableEngine;
314    }
315 
316    public void setTableEngineParams(ArrayList<String> tableEngineParams) {
317        data.tableEngineParams = tableEngineParams;
318    }
319 
320    public void setHidden(boolean isHidden) {
321        data.isHidden = isHidden;
322    }
323 
324    @Override
325    public int getType() {
326        return CommandInterface.CREATE_TABLE;
327    }
328 
329}

[all classes][org.h2.command.ddl]
EMMA 2.0.5312 (C) Vladimir Roubtsov