KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > DatabaseCommandInterpreter


1 /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the Hypersonic SQL Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This software consists of voluntary contributions made by many individuals
31  * on behalf of the Hypersonic SQL Group.
32  *
33  *
34  * For work added by the HSQL Development Group:
35  *
36  * Copyright (c) 2001-2005, The HSQL Development Group
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  * Redistributions of source code must retain the above copyright notice, this
43  * list of conditions and the following disclaimer.
44  *
45  * Redistributions in binary form must reproduce the above copyright notice,
46  * this list of conditions and the following disclaimer in the documentation
47  * and/or other materials provided with the distribution.
48  *
49  * Neither the name of the HSQL Development Group nor the names of its
50  * contributors may be used to endorse or promote products derived from this
51  * software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
57  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */

65
66
67 package org.hsqldb;
68
69 import java.io.IOException JavaDoc;
70 import java.io.LineNumberReader JavaDoc;
71 import java.io.StringReader JavaDoc;
72 import java.util.Locale JavaDoc;
73
74 import org.hsqldb.HsqlNameManager.HsqlName;
75 import org.hsqldb.lib.ArrayUtil;
76 import org.hsqldb.lib.HashMappedList;
77 import org.hsqldb.lib.HsqlArrayList;
78 import org.hsqldb.lib.StringUtil;
79 import org.hsqldb.lib.java.JavaSystem;
80 import org.hsqldb.persist.HsqlDatabaseProperties;
81 import org.hsqldb.scriptio.ScriptWriterBase;
82 import org.hsqldb.scriptio.ScriptWriterText;
83
84 /**
85  * Provides SQL Interpreter services relative to a Session and
86  * its Database.
87  *
88  * The core functionality of this class was inherited from Hypersonic and
89  * extensively rewritten and extended in successive versions of HSQLDB.
90  *
91  * @author Thomas Mueller (Hypersonic SQL Group)
92  * @version 1.8.0
93  * @since 1.7.2
94  */

95
96 // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - various corrections
97
// fredt@users 20020430 - patch 549741 by velichko - ALTER TABLE RENAME
98
// fredt@users 20020405 - patch 1.7.0 - other ALTER TABLE statements
99
// tony_lai@users 20020820 - patch 595099 - use user-defined PK name
100
// tony_lai@users 20020820 - patch 595156 - violation of constraint name
101
// fredt@users 20020912 - patch 1.7.1 by fredt - log alter statements
102
// kloska@users 20021030 - patch 1.7.2 - ON UPDATE CASCADE | SET NULL | SET DEFAULT
103
// kloska@users 20021112 - patch 1.7.2 - ON DELETE SET NULL | SET DEFAULT
104
// boucherb@users 20020310 - disable ALTER TABLE DDL on VIEWs (avoid NPE)
105
// fredt@users 20030314 - patch 1.7.2 by gilead@users - drop table if exists syntax
106
// boucherb@users 20030425 - DDL methods are moved to DatabaseCommandInterpreter.java
107
// boucherb@users 20030425 - refactoring DDL methods into smaller units
108
// fredt@users 20030609 - support for ALTER COLUMN SET/DROP DEFAULT / RENAME TO
109
// wondersonic@users 20031205 - IF EXISTS support for DROP INDEX
110
// fredt@users 20031224 - support for CREATE SEQUENCE ...
111
// fredt@users 20041209 - patch by tytar@users to set default table type
112
class DatabaseCommandInterpreter {
113
114     private Tokenizer tokenizer = new Tokenizer();
115     private Database database;
116     private Session session;
117
118     /**
119      * Constructs a new DatabaseCommandInterpreter for the given Session
120      *
121      * @param s session
122      */

123     DatabaseCommandInterpreter(Session s) {
124         session = s;
125         database = s.getDatabase();
126     }
127
128     /**
129      * Executes the SQL String. This method is always called from a block
130      * synchronized on the database object.
131      *
132      * @param sql query
133      * @return the result of executing the given SQL String
134      */

135     Result execute(String JavaDoc sql) {
136
137         Result result;
138         String JavaDoc token;
139         int cmd;
140
141         JavaSystem.gc();
142
143         result = null;
144         cmd = Token.UNKNOWNTOKEN;
145
146         try {
147             tokenizer.reset(sql);
148
149             while (true) {
150                 tokenizer.setPartMarker();
151                 session.setScripting(false);
152
153                 token = tokenizer.getSimpleToken();
154
155                 if (token.length() == 0) {
156                     session.endSchemaDefinition();
157
158                     break;
159                 }
160
161                 cmd = Token.get(token);
162
163                 if (cmd == Token.SEMICOLON) {
164                     session.endSchemaDefinition();
165
166                     continue;
167                 }
168
169                 result = executePart(cmd, token);
170
171                 if (result.isError()) {
172                     session.endSchemaDefinition();
173
174                     break;
175                 }
176
177                 if (session.getScripting()) {
178                     database.logger.writeToLog(session,
179                                                tokenizer.getLastPart());
180                 }
181             }
182         } catch (Throwable JavaDoc t) {
183             try {
184                 if (session.isSchemaDefintion()) {
185                     HsqlName schemaName = session.getSchemaHsqlName(null);
186
187                     database.schemaManager.dropSchema(schemaName.name, true);
188                     database.logger.writeToLog(session,
189                                                Token.T_DROP + ' '
190                                                + Token.T_SCHEMA + ' '
191                                                + schemaName.statementName
192                                                + ' ' + Token.T_CASCADE);
193                     session.endSchemaDefinition();
194                 }
195             } catch (HsqlException e) {}
196
197             result = new Result(t, tokenizer.getLastPart());
198         }
199
200         return result == null ? Session.emptyUpdateCount
201                               : result;
202     }
203
204     private Result executePart(int cmd, String JavaDoc token) throws Throwable JavaDoc {
205
206         Result result = Session.emptyUpdateCount;
207         int brackets = 0;
208
209         if (session.isSchemaDefintion()) {
210             switch (cmd) {
211
212                 case Token.CREATE :
213                 case Token.GRANT :
214                     break;
215
216                 default :
217                     throw Trace.error(Trace.INVALID_IDENTIFIER,
218                                       Trace.IN_SCHEMA_DEFINITION,
219                                       new Object JavaDoc[]{ token });
220             }
221         }
222
223         switch (cmd) {
224
225             case Token.OPENBRACKET : {
226                 Parser parser = new Parser(session, database, tokenizer);
227
228                 brackets = parser.parseOpenBracketsSelect() + 1;
229             }
230             case Token.SELECT : {
231                 Parser parser = new Parser(session, database, tokenizer);
232                 CompiledStatement cStatement =
233                     parser.compileSelectStatement(brackets);
234
235                 if (cStatement.parameters.length != 0) {
236                     Trace.doAssert(
237                         false,
238                         Trace.getMessage(
239                             Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
240                 }
241
242                 result = session.sqlExecuteCompiledNoPreChecks(cStatement,
243                         null);
244
245                 break;
246             }
247             case Token.INSERT : {
248                 Parser parser = new Parser(session, database, tokenizer);
249                 CompiledStatement cStatement =
250                     parser.compileInsertStatement();
251
252                 if (cStatement.parameters.length != 0) {
253                     Trace.doAssert(
254                         false,
255                         Trace.getMessage(
256                             Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
257                 }
258
259                 result = session.sqlExecuteCompiledNoPreChecks(cStatement,
260                         null);
261
262                 break;
263             }
264             case Token.UPDATE : {
265                 Parser parser = new Parser(session, database, tokenizer);
266                 CompiledStatement cStatement =
267                     parser.compileUpdateStatement();
268
269                 if (cStatement.parameters.length != 0) {
270                     Trace.doAssert(
271                         false,
272                         Trace.getMessage(
273                             Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
274                 }
275
276                 result = session.sqlExecuteCompiledNoPreChecks(cStatement,
277                         null);
278
279                 break;
280             }
281             case Token.DELETE : {
282                 Parser parser = new Parser(session, database, tokenizer);
283                 CompiledStatement cStatement =
284                     parser.compileDeleteStatement();
285
286                 if (cStatement.parameters.length != 0) {
287                     Trace.doAssert(
288                         false,
289                         Trace.getMessage(
290                             Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
291                 }
292
293                 result = session.sqlExecuteCompiledNoPreChecks(cStatement,
294                         null);
295
296                 break;
297             }
298             case Token.CALL : {
299                 Parser parser = new Parser(session, database, tokenizer);
300                 CompiledStatement cStatement = parser.compileCallStatement();
301
302                 if (cStatement.parameters.length != 0) {
303                     Trace.doAssert(
304                         false,
305                         Trace.getMessage(
306                             Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
307                 }
308
309                 result = session.sqlExecuteCompiledNoPreChecks(cStatement,
310                         null);
311
312                 break;
313             }
314             case Token.SET :
315                 processSet();
316                 break;
317
318             case Token.COMMIT :
319                 processCommit();
320                 break;
321
322             case Token.ROLLBACK :
323                 processRollback();
324                 break;
325
326             case Token.SAVEPOINT :
327                 processSavepoint();
328                 break;
329
330             case Token.RELEASE :
331                 processReleaseSavepoint();
332                 break;
333
334             case Token.CREATE :
335                 processCreate();
336                 database.setMetaDirty(false);
337                 break;
338
339             case Token.ALTER :
340                 processAlter();
341                 database.setMetaDirty(true);
342                 break;
343
344             case Token.DROP :
345                 processDrop();
346                 database.setMetaDirty(true);
347                 break;
348
349             case Token.GRANT :
350                 processGrantOrRevoke(true);
351                 database.setMetaDirty(false);
352                 break;
353
354             case Token.REVOKE :
355                 processGrantOrRevoke(false);
356                 database.setMetaDirty(true);
357                 break;
358
359             case Token.CONNECT :
360                 processConnect();
361                 database.setMetaDirty(false);
362                 session.setScripting(false);
363                 break;
364
365             case Token.DISCONNECT :
366                 processDisconnect();
367                 session.setScripting(true);
368                 break;
369
370             case Token.SCRIPT :
371                 result = processScript();
372                 break;
373
374             case Token.SHUTDOWN :
375                 processShutdown();
376                 break;
377
378             case Token.CHECKPOINT :
379                 processCheckpoint();
380                 break;
381
382             case Token.EXPLAIN :
383                 result = processExplainPlan();
384                 break;
385
386             default :
387                 throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
388         }
389
390         return result;
391     }
392
393     /**
394      * Responsible for parsing and executing the SCRIPT SQL statement
395      *
396      * @return either an empty result or one in which each row is a DDL or DML
397      * @throws IOException
398      * @throws HsqlException
399      */

400     private Result processScript() throws IOException JavaDoc, HsqlException {
401
402         String JavaDoc token = tokenizer.getString();
403         ScriptWriterText dsw = null;
404
405         session.checkAdmin();
406
407         try {
408             if (tokenizer.wasValue()) {
409                 if (tokenizer.getType() != Types.VARCHAR) {
410                     throw Trace.error(Trace.INVALID_IDENTIFIER);
411                 }
412
413                 dsw = new ScriptWriterText(database, token, true, true, true);
414
415                 dsw.writeAll();
416
417                 return new Result(ResultConstants.UPDATECOUNT);
418             } else {
419                 tokenizer.back();
420
421                 return DatabaseScript.getScript(database, false);
422             }
423         } finally {
424             if (dsw != null) {
425                 dsw.close();
426             }
427         }
428     }
429
430     /**
431      * Responsible for handling CREATE ...
432      *
433      * All CREATE command require an ADMIN user except: <p>
434      *
435      * <pre>
436      * CREATE TEMP [MEMORY] TABLE
437      * </pre>
438      *
439      * @throws HsqlException
440      */

441     private void processCreate() throws HsqlException {
442
443         boolean unique = false;
444         int tableType;
445         boolean isTempTable = false;
446         String JavaDoc token;
447
448         session.checkAdmin();
449         session.checkDDLWrite();
450         session.setScripting(true);
451
452         if (tokenizer.isGetThis(Token.T_GLOBAL)) {
453             tokenizer.getThis(Token.T_TEMPORARY);
454
455             isTempTable = true;
456         } else if (tokenizer.isGetThis(Token.T_TEMP)) {
457             isTempTable = true;
458         } else if (tokenizer.isGetThis(Token.T_TEMPORARY)) {
459             isTempTable = true;
460         }
461
462         token = tokenizer.getSimpleToken();
463
464         switch (Token.get(token)) {
465
466             // table
467
case Token.MEMORY :
468                 tokenizer.getThis(Token.T_TABLE);
469             case Token.TABLE :
470                 tableType = isTempTable ? Table.TEMP_TABLE
471                                         : database.getDefaultTableType();
472
473                 processCreateTable(tableType);
474
475                 return;
476
477             case Token.CACHED :
478                 if (isTempTable) {
479                     throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
480                 }
481
482                 tokenizer.getThis(Token.T_TABLE);
483                 processCreateTable(Table.CACHED_TABLE);
484
485                 return;
486
487             case Token.TEXT :
488                 if (isTempTable) {
489                     throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
490                 }
491
492                 tokenizer.getThis(Token.T_TABLE);
493                 processCreateTable(Table.TEXT_TABLE);
494
495                 return;
496
497             default :
498                 if (isTempTable) {
499                     throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
500                 }
501         }
502
503         switch (Token.get(token)) {
504
505             // other objects
506
case Token.ALIAS :
507                 processCreateAlias();
508                 break;
509
510             case Token.SEQUENCE :
511                 processCreateSequence();
512                 break;
513
514             case Token.SCHEMA :
515                 session.setScripting(false);
516                 processCreateSchema();
517                 break;
518
519             case Token.TRIGGER :
520                 processCreateTrigger();
521                 break;
522
523             case Token.USER :
524                 processCreateUser();
525                 break;
526
527             case Token.ROLE :
528                 database.getGranteeManager().addRole(getUserIdentifier());
529                 break;
530
531             case Token.VIEW :
532                 processCreateView();
533                 break;
534
535             // index
536
case Token.UNIQUE :
537                 unique = true;
538
539                 tokenizer.getThis(Token.T_INDEX);
540
541             //fall thru
542
case Token.INDEX :
543                 processCreateIndex(unique);
544                 break;
545
546             default : {
547                 throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
548             }
549         }
550     }
551
552     /**
553      * Process a bracketed column list as used in the declaration of SQL
554      * CONSTRAINTS and return an array containing the indexes of the columns
555      * within the table.
556      *
557      * @param t table that contains the columns
558      * @return column index map
559      * @throws HsqlException if a column is not found or is duplicate
560      */

561     private int[] processColumnList(Table t,
562                                     boolean acceptAscDesc)
563                                     throws HsqlException {
564
565         HashMappedList list = Parser.processColumnList(tokenizer,
566             acceptAscDesc);
567         int size = list.size();
568         int[] col = new int[size];
569
570         for (int i = 0; i < size; i++) {
571             col[i] = t.getColumnNr((String JavaDoc) list.getKey(i));
572         }
573
574         return col;
575     }
576
577     /**
578      * Responsible for handling the execution of CREATE TRIGGER SQL
579      * statements. <p>
580      *
581      * typical sql is: CREATE TRIGGER tr1 AFTER INSERT ON tab1 CALL "pkg.cls"
582      *
583      * @throws HsqlException
584      */

585     private void processCreateTrigger() throws HsqlException {
586
587         Table t;
588         boolean isForEach;
589         boolean isNowait;
590         int queueSize;
591         String JavaDoc triggerName;
592         boolean isQuoted;
593         String JavaDoc sWhen;
594         String JavaDoc sOper;
595         String JavaDoc tableName;
596         String JavaDoc token;
597         String JavaDoc className;
598         TriggerDef td;
599         Trigger o;
600
601         triggerName = tokenizer.getName();
602
603         String JavaDoc schemaname = tokenizer.getLongNameFirst();
604
605         database.schemaManager.checkTriggerExists(triggerName,
606                 session.getSchemaNameForWrite(schemaname), false);
607
608         isQuoted = tokenizer.wasQuotedIdentifier();
609         isForEach = false;
610         isNowait = false;
611         queueSize = TriggerDef.getDefaultQueueSize();
612         sWhen = tokenizer.getSimpleToken();
613         sOper = tokenizer.getSimpleToken();
614
615         tokenizer.getThis(Token.T_ON);
616
617         tableName = tokenizer.getName();
618
619         if (schemaname == null) {
620             schemaname =
621                 session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
622         } else if (!schemaname.equals(
623                 session.getSchemaNameForWrite(
624                     tokenizer.getLongNameFirst()))) {
625             throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
626         }
627
628         t = database.schemaManager.getUserTable(session, tableName,
629                 schemaname);
630
631         if (t.isView()) {
632             throw Trace.error(Trace.NOT_A_TABLE);
633         }
634
635         session.setScripting(true);
636
637         // "FOR EACH ROW" or "CALL"
638
token = tokenizer.getSimpleToken();
639
640         if (token.equals(Token.T_FOR)) {
641             token = tokenizer.getSimpleToken();
642
643             if (token.equals(Token.T_EACH)) {
644                 token = tokenizer.getSimpleToken();
645
646                 if (token.equals(Token.T_ROW)) {
647                     isForEach = true;
648
649                     // should be 'NOWAIT' or 'QUEUE' or 'CALL'
650
token = tokenizer.getSimpleToken();
651                 } else {
652                     throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
653                 }
654             } else {
655                 throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
656             }
657         }
658
659         if (token.equals(Token.T_NOWAIT)) {
660             isNowait = true;
661
662             // should be 'CALL' or 'QUEUE'
663
token = tokenizer.getSimpleToken();
664         }
665
666         if (token.equals(Token.T_QUEUE)) {
667             queueSize = tokenizer.getInt();
668
669             // should be 'CALL'
670
token = tokenizer.getSimpleToken();
671         }
672
673         if (!token.equals(Token.T_CALL)) {
674             throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
675         }
676
677         className = tokenizer.getSimpleName();
678
679         if (!tokenizer.wasQuotedIdentifier()) {
680             throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, className);
681         }
682
683         HsqlName name = database.nameManager.newHsqlName(triggerName,
684             isQuoted);
685
686         td = new TriggerDef(name, sWhen, sOper, isForEach, t, className,
687                             isNowait, queueSize, database.classLoader);
688
689         t.addTrigger(td);
690
691         if (td.isValid()) {
692             try {
693
694                 // start the trigger thread
695
td.start();
696             } catch (Exception JavaDoc e) {
697                 throw Trace.error(Trace.UNKNOWN_FUNCTION, e.toString());
698             }
699         }
700
701         database.schemaManager.registerTriggerName(triggerName, t.getName());
702
703 // --
704
}
705
706     private Column processCreateColumn() throws HsqlException {
707
708         String JavaDoc token = tokenizer.getSimpleName();
709         boolean isQuoted = tokenizer.wasQuotedIdentifier();
710         HsqlName hsqlName = database.nameManager.newHsqlName(token, isQuoted);
711
712         return processCreateColumn(hsqlName);
713     }
714
715     /**
716      * Responsible for handling the creation of table columns during the
717      * process of executing CREATE TABLE DDL statements.
718      *
719      * @param hsqlName name of the column
720      * @return a Column object with indicated attributes
721      * @throws HsqlException
722      */

723     private Column processCreateColumn(HsqlName hsqlName)
724     throws HsqlException {
725
726         boolean isIdentity = false;
727         long identityStart = database.firstIdentity;
728         long identityIncrement = 1;
729         boolean isPrimaryKey = false;
730         String JavaDoc typeName;
731         int type;
732         int length = 0;
733         int scale = 0;
734         boolean hasLength = false;
735         boolean isNullable = true;
736         Expression defaultExpr = null;
737         String JavaDoc token;
738
739         typeName = tokenizer.getSimpleToken();
740         type = Types.getTypeNr(typeName);
741
742         if (type == Types.CHAR) {
743             if (tokenizer.isGetThis(Token.T_VARYING)) {
744                 type = Types.VARCHAR;
745             }
746         }
747
748         if (typeName.equals(Token.T_IDENTITY)) {
749             isIdentity = true;
750             isPrimaryKey = true;
751         }
752
753         // fredt - when SET IGNORECASE is in effect, all new VARCHAR columns are defined as VARCHAR_IGNORECASE
754
if (type == Types.DOUBLE) {
755             tokenizer.isGetThis(Token.T_PRECISION);
756         }
757
758         if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
759             hasLength = true;
760             length = tokenizer.getInt();
761
762             Trace.check(Types.acceptsPrecisionCreateParam(type),
763                         Trace.UNEXPECTED_TOKEN);
764
765             if (type != Types.TIMESTAMP && type != Types.TIME
766                     && length == 0) {
767                 throw Trace.error(Trace.INVALID_SIZE_PRECISION);
768             }
769
770             if (tokenizer.isGetThis(Token.T_COMMA)) {
771                 Trace.check(Types.acceptsScaleCreateParam(type),
772                             Trace.UNEXPECTED_TOKEN);
773
774                 scale = tokenizer.getInt();
775             }
776
777             tokenizer.getThis(Token.T_CLOSEBRACKET);
778         } else if (type == Types.CHAR && database.sqlEnforceStrictSize) {
779             length = 1;
780         } else if (type == Types.VARCHAR && database.sqlEnforceStrictSize) {
781             throw Trace.error(Trace.COLUMN_SIZE_REQUIRED);
782         }
783
784         /**
785          * @todo fredt - drop support for SET IGNORECASE and replace the
786          * type name with a qualifier specifying the case sensitivity of VARCHAR
787          */

788         if (type == Types.VARCHAR && database.isIgnoreCase()) {
789             type = Types.VARCHAR_IGNORECASE;
790         }
791
792         if (type == Types.FLOAT && length > 53) {
793             throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
794         }
795
796         if (type == Types.TIMESTAMP) {
797             if (!hasLength) {
798                 length = 6;
799             } else if (length != 0 && length != 6) {
800                 throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
801             }
802         }
803
804         if (type == Types.TIME) {
805             if (length != 0) {
806                 throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
807             }
808         }
809
810         token = tokenizer.getSimpleToken();
811
812         if (token.equals(Token.T_DEFAULT)) {
813             defaultExpr = processCreateDefaultExpression(type, length, scale);
814             token = tokenizer.getSimpleToken();
815         } else if (token.equals(Token.T_GENERATED)) {
816             tokenizer.getThis(Token.T_BY);
817             tokenizer.getThis(Token.T_DEFAULT);
818             tokenizer.getThis(Token.T_AS);
819             tokenizer.getThis(Token.T_IDENTITY);
820
821             if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
822                 tokenizer.getThis(Token.T_START);
823                 tokenizer.getThis(Token.T_WITH);
824
825                 identityStart = tokenizer.getBigint();
826
827                 if (tokenizer.isGetThis(Token.T_COMMA)) {
828                     tokenizer.getThis(Token.T_INCREMENT);
829                     tokenizer.getThis(Token.T_BY);
830
831                     identityIncrement = tokenizer.getBigint();
832                 }
833
834                 tokenizer.getThis(Token.T_CLOSEBRACKET);
835             }
836
837             isIdentity = true;
838             isPrimaryKey = true;
839             token = tokenizer.getSimpleToken();
840         }
841
842         // fredt@users - accept IDENTITY before or after NOT NULL
843
if (token.equals(Token.T_IDENTITY)) {
844             isIdentity = true;
845             isPrimaryKey = true;
846             token = tokenizer.getSimpleToken();
847         }
848
849         if (token.equals(Token.T_NULL)) {
850             token = tokenizer.getSimpleToken();
851         } else if (token.equals(Token.T_NOT)) {
852             tokenizer.getThis(Token.T_NULL);
853
854             isNullable = false;
855             token = tokenizer.getSimpleToken();
856         }
857
858         if (token.equals(Token.T_IDENTITY)) {
859             if (isIdentity) {
860                 throw Trace.error(Trace.SECOND_PRIMARY_KEY, Token.T_IDENTITY);
861             }
862
863             isIdentity = true;
864             isPrimaryKey = true;
865             token = tokenizer.getSimpleToken();
866         }
867
868         if (token.equals(Token.T_PRIMARY)) {
869             tokenizer.getThis(Token.T_KEY);
870
871             isPrimaryKey = true;
872         } else {
873             tokenizer.back();
874         }
875
876         // make sure IDENTITY and DEFAULT are not used together
877
if (isIdentity && defaultExpr != null) {
878             throw Trace.error(Trace.UNEXPECTED_TOKEN, Token.T_DEFAULT);
879         }
880
881         Column column = new Column(hsqlName, isNullable, type, length, scale,
882                                    isPrimaryKey, defaultExpr);
883
884         column.setIdentity(isIdentity, identityStart, identityIncrement);
885
886         return column;
887     }
888
889     /**
890      * @param type data type of column
891      * @param length maximum length of column
892      * @throws HsqlException
893      * @return new Expression
894      */

895     private Expression processCreateDefaultExpression(int type, int length,
896             int scale) throws HsqlException {
897
898         if (type == Types.OTHER) {
899             throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
900         }
901
902         Parser parser = new Parser(session, database, tokenizer);
903         Expression expr = parser.readDefaultClause(type);
904
905         expr.resolveTypes(session);
906
907         int newType = expr.getType();
908
909         if (newType == Expression.VALUE || newType == Expression.TRUE
910                 || newType == Expression.FALSE
911                 || (newType == Expression.FUNCTION
912                     && expr.function.isSimple)) {
913             Object JavaDoc defValTemp;
914
915             try {
916                 defValTemp = expr.getValue(session, type);
917             } catch (HsqlException e) {
918                 throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
919             }
920
921             if (defValTemp != null && database.sqlEnforceStrictSize) {
922                 try {
923                     Column.enforceSize(defValTemp, type, length, scale, true);
924                 } catch (HsqlException e) {
925
926                     // default value is too long for fixed size column
927
throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
928                 }
929             }
930
931             return expr;
932         }
933
934         throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
935     }
936
937     public static void checkBooleanDefault(String JavaDoc s,
938                                            int type) throws HsqlException {
939
940         if (type != Types.BOOLEAN || s == null) {
941             return;
942         }
943
944         s = s.toUpperCase();
945
946         if (s.equals(Token.T_TRUE) || s.equals(Token.T_FALSE)) {
947             return;
948         }
949
950         if (s.equals("0") || s.equals("1")) {
951             return;
952         }
953
954         throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE, s);
955     }
956
957     /**
958      * Responsible for handling constraints section of CREATE TABLE ...
959      *
960      * @param t table
961      * @param constraint CONSTRAINT keyword used
962      * @param primarykeycolumn primary columns
963      * @throws HsqlException
964      * @return list of constraints
965      */

966     private HsqlArrayList processCreateConstraints(Table t,
967             boolean constraint, int[] primarykeycolumn) throws HsqlException {
968
969         String JavaDoc token;
970         HsqlArrayList tcList;
971         Constraint tempConst;
972         HsqlName pkHsqlName;
973
974 // fredt@users 20020225 - comment
975
// HSQLDB relies on primary index to be the first one defined
976
// and needs original or system added primary key before any
977
// non-unique index is created
978
tcList = new HsqlArrayList();
979         tempConst = new Constraint(null, primarykeycolumn, null, null,
980                                    Constraint.MAIN, Constraint.NO_ACTION,
981                                    Constraint.NO_ACTION);
982
983 // tony_lai@users 20020820 - patch 595099
984
pkHsqlName = null;
985
986         tcList.add(tempConst);
987
988         if (!constraint) {
989             return tcList;
990         }
991
992         while (true) {
993             HsqlName cname = null;
994
995             if (tokenizer.isGetThis(Token.T_CONSTRAINT)) {
996                 token = tokenizer.getName();
997
998                 String JavaDoc constraintSchema = tokenizer.getLongNameFirst();
999
1000                if (constraintSchema != null) {
1001                    constraintSchema = session.getSchemaNameForWrite(
1002                        tokenizer.getLongNameFirst());
1003
1004                    if (!t.getSchemaName().equals(constraintSchema)) {
1005                        throw Trace.error(
1006                            Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
1007                            constraintSchema);
1008                    }
1009                }
1010
1011                cname = database.nameManager.newHsqlName(token,
1012                        tokenizer.wasQuotedIdentifier());
1013            }
1014
1015            token = tokenizer.getSimpleToken();
1016
1017            switch (Token.get(token)) {
1018
1019                case Token.PRIMARY : {
1020                    tokenizer.getThis(Token.T_KEY);
1021
1022                    // tony_lai@users 20020820 - patch 595099
1023
pkHsqlName = cname;
1024
1025                    int[] cols = processColumnList(t, false);
1026                    Constraint mainConst;
1027
1028                    mainConst = (Constraint) tcList.get(0);
1029
1030                    if (mainConst.core.mainColArray != null) {
1031                        if (!ArrayUtil.areEqual(mainConst.core.mainColArray,
1032                                                cols, cols.length, true)) {
1033                            throw Trace.error(Trace.SECOND_PRIMARY_KEY);
1034                        }
1035                    }
1036
1037                    mainConst.core.mainColArray = cols;
1038                    mainConst.constName = pkHsqlName;
1039
1040                    break;
1041                }
1042                case Token.UNIQUE : {
1043                    int[] col = processColumnList(t, false);
1044
1045                    if (cname == null) {
1046                        cname = database.nameManager.newAutoName("CT");
1047                    }
1048
1049                    tempConst = new Constraint(cname, col, null, null,
1050                                               Constraint.UNIQUE,
1051                                               Constraint.NO_ACTION,
1052                                               Constraint.NO_ACTION);
1053
1054                    tcList.add(tempConst);
1055
1056                    break;
1057                }
1058                case Token.FOREIGN : {
1059                    tokenizer.getThis(Token.T_KEY);
1060
1061                    tempConst = processCreateFK(t, cname);
1062
1063                    if (tempConst.core.refColArray == null) {
1064                        Constraint mainConst = (Constraint) tcList.get(0);
1065
1066                        tempConst.core.refColArray =
1067                            mainConst.core.mainColArray;
1068
1069                        if (tempConst.core.refColArray == null) {
1070                            throw Trace.error(Trace.CONSTRAINT_NOT_FOUND,
1071                                              Trace.TABLE_HAS_NO_PRIMARY_KEY);
1072                        }
1073                    }
1074
1075                    checkFKColumnDefaults(t, tempConst);
1076                    t.checkColumnsMatch(tempConst.core.mainColArray,
1077                                        tempConst.core.refTable,
1078                                        tempConst.core.refColArray);
1079                    tcList.add(tempConst);
1080
1081                    break;
1082                }
1083                case Token.CHECK : {
1084                    if (cname == null) {
1085                        cname = database.nameManager.newAutoName("CT");
1086                    }
1087
1088                    tempConst = new Constraint(cname, null, null, null,
1089                                               Constraint.CHECK,
1090                                               Constraint.NO_ACTION,
1091                                               Constraint.NO_ACTION);
1092
1093                    processCreateCheckConstraintCondition(tempConst);
1094                    tcList.add(tempConst);
1095
1096                    break;
1097                }
1098            }
1099
1100            token = tokenizer.getSimpleToken();
1101
1102            if (token.equals(Token.T_COMMA)) {
1103                continue;
1104            }
1105
1106            if (token.equals(Token.T_CLOSEBRACKET)) {
1107                break;
1108            }
1109
1110            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1111        }
1112
1113        return tcList;
1114    }
1115
1116    /**
1117     * Responsible for handling check constraints section of CREATE TABLE ...
1118     *
1119     * @param c check constraint
1120     * @throws HsqlException
1121     */

1122    private void processCreateCheckConstraintCondition(Constraint c)
1123    throws HsqlException {
1124
1125        tokenizer.getThis(Token.T_OPENBRACKET);
1126
1127        Parser parser = new Parser(session, database, tokenizer);
1128        Expression condition = parser.parseExpression();
1129
1130        tokenizer.getThis(Token.T_CLOSEBRACKET);
1131
1132        c.core.check = condition;
1133    }
1134
1135    /**
1136     * Responsible for handling the execution CREATE TABLE SQL statements.
1137     *
1138     * @param type Description of the Parameter
1139     * @throws HsqlException
1140     */

1141    private void processCreateTable(int type) throws HsqlException {
1142
1143        String JavaDoc token = tokenizer.getName();
1144        HsqlName schemaname =
1145            session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst());
1146
1147        database.schemaManager.checkUserTableNotExists(session, token,
1148                schemaname.name);
1149
1150        boolean isnamequoted = tokenizer.wasQuotedIdentifier();
1151        int[] pkCols = null;
1152        int colIndex = 0;
1153        boolean constraint = false;
1154        Table t = newTable(type, token, isnamequoted, schemaname);
1155
1156        tokenizer.getThis(Token.T_OPENBRACKET);
1157
1158        while (true) {
1159            token = tokenizer.getString();
1160
1161            switch (Token.get(token)) {
1162
1163                case Token.CONSTRAINT :
1164                case Token.PRIMARY :
1165                case Token.FOREIGN :
1166                case Token.UNIQUE :
1167                case Token.CHECK :
1168
1169                    // fredt@users : check for quoted reserved words used as column names
1170
constraint = !tokenizer.wasQuotedIdentifier()
1171                                 &&!tokenizer.wasLongName();
1172            }
1173
1174            tokenizer.back();
1175
1176            if (constraint) {
1177                break;
1178            }
1179
1180            Column newcolumn = processCreateColumn();
1181
1182            t.addColumn(newcolumn);
1183
1184            if (newcolumn.isPrimaryKey()) {
1185                Trace.check(pkCols == null, Trace.SECOND_PRIMARY_KEY,
1186                            newcolumn.columnName.name);
1187
1188                pkCols = new int[]{ colIndex };
1189            }
1190
1191            token = tokenizer.getSimpleToken();
1192
1193            if (token.equals(Token.T_COMMA)) {
1194                colIndex++;
1195
1196                continue;
1197            }
1198
1199            if (token.equals(Token.T_CLOSEBRACKET)) {
1200                break;
1201            }
1202
1203            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1204        }
1205
1206        HsqlArrayList tempConstraints = processCreateConstraints(t,
1207            constraint, pkCols);
1208
1209        if (tokenizer.isGetThis(Token.T_ON)) {
1210            if (!t.isTemp) {
1211                throw Trace.error(Trace.UNEXPECTED_TOKEN, Token.T_ON);
1212            }
1213
1214            tokenizer.getThis(Token.T_COMMIT);
1215
1216            token = tokenizer.getSimpleToken();
1217
1218            if (token.equals(Token.T_DELETE)) {}
1219            else if (token.equals(Token.T_PRESERVE)) {
1220                t.onCommitPreserve = true;
1221            } else {
1222                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1223            }
1224
1225            tokenizer.getThis(Token.T_ROWS);
1226        }
1227
1228        try {
1229            session.commit();
1230
1231            Constraint primaryConst = (Constraint) tempConstraints.get(0);
1232
1233            t.createPrimaryKey(null, primaryConst.core.mainColArray, true);
1234
1235            if (primaryConst.core.mainColArray != null) {
1236                if (primaryConst.constName == null) {
1237                    primaryConst.constName = t.makeSysPKName();
1238                }
1239
1240                Constraint newconstraint =
1241                    new Constraint(primaryConst.constName, t, t.getPrimaryIndex(),
1242                                   Constraint.PRIMARY_KEY);
1243
1244                t.addConstraint(newconstraint);
1245                database.schemaManager.registerConstraintName(
1246                    primaryConst.constName.name, t.getName());
1247            }
1248
1249            for (int i = 1; i < tempConstraints.size(); i++) {
1250                Constraint tempConst = (Constraint) tempConstraints.get(i);
1251
1252                if (tempConst.constType == Constraint.UNIQUE) {
1253                    TableWorks tableWorks = new TableWorks(session, t);
1254
1255                    tableWorks.createUniqueConstraint(
1256                        tempConst.core.mainColArray, tempConst.constName);
1257
1258                    t = tableWorks.getTable();
1259                }
1260
1261                if (tempConst.constType == Constraint.FOREIGN_KEY) {
1262                    TableWorks tableWorks = new TableWorks(session, t);
1263
1264                    tableWorks.createForeignKey(tempConst.core.mainColArray,
1265                                                tempConst.core.refColArray,
1266                                                tempConst.constName,
1267                                                tempConst.core.refTable,
1268                                                tempConst.core.deleteAction,
1269                                                tempConst.core.updateAction);
1270
1271                    t = tableWorks.getTable();
1272                }
1273
1274                if (tempConst.constType == Constraint.CHECK) {
1275                    TableWorks tableWorks = new TableWorks(session, t);
1276
1277                    tableWorks.createCheckConstraint(tempConst,
1278                                                     tempConst.constName);
1279
1280                    t = tableWorks.getTable();
1281                }
1282            }
1283
1284            database.schemaManager.linkTable(t);
1285        } catch (HsqlException e) {
1286
1287// fredt@users 20020225 - comment
1288
// if a HsqlException is thrown while creating table, any foreign key that has
1289
// been created leaves it modification to the expTable in place
1290
// need to undo those modifications. This should not happen in practice.
1291
database.schemaManager.removeExportedKeys(t);
1292            database.schemaManager.removeIndexNames(t.tableName);
1293            database.schemaManager.removeConstraintNames(t.tableName);
1294
1295            throw e;
1296        }
1297    }
1298
1299// fredt@users 20020221 - patch 520213 by boucherb@users - self reference FK
1300
// allows foreign keys that reference a column in the same table
1301

1302    /**
1303     * @param t table
1304     * @param cname foreign key name
1305     * @throws HsqlException
1306     * @return constraint
1307     */

1308    private Constraint processCreateFK(Table t,
1309                                       HsqlName cname) throws HsqlException {
1310
1311        int[] localcol;
1312        int[] expcol;
1313        String JavaDoc expTableName;
1314        Table expTable;
1315        String JavaDoc token;
1316
1317        localcol = processColumnList(t, false);
1318
1319        tokenizer.getThis(Token.T_REFERENCES);
1320
1321        expTableName = tokenizer.getName();
1322
1323        String JavaDoc constraintSchema = tokenizer.getLongNameFirst();
1324
1325        if (constraintSchema != null) {
1326            constraintSchema =
1327                session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
1328
1329            if (!t.getSchemaName().equals(constraintSchema)) {
1330                throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
1331                                  constraintSchema);
1332            }
1333        }
1334
1335        if (t.getName().name.equals(expTableName)) {
1336            expTable = t;
1337        } else {
1338            expTable = database.schemaManager.getTable(session, expTableName,
1339                    t.getSchemaName());
1340        }
1341
1342        expcol = null;
1343        token = tokenizer.getSimpleToken();
1344
1345        tokenizer.back();
1346
1347        if (token.equals(Token.T_OPENBRACKET)) {
1348            expcol = processColumnList(expTable, false);
1349        } else {
1350            if (expTable.getPrimaryKey() == null) {
1351
1352                // getPrimaryKey() == null is true while creating the table
1353
// fredt - FK statement is part of CREATE TABLE and is self-referencing
1354
// reference must be to same table being created
1355
// it is resolved in the calling method
1356
Trace.check(t == expTable, Trace.TABLE_HAS_NO_PRIMARY_KEY);
1357            } else {
1358                if (expTable.hasPrimaryKey()) {
1359                    expcol = expTable.getPrimaryKey();
1360                } else {
1361                    throw Trace.error(Trace.CONSTRAINT_NOT_FOUND,
1362                                      Trace.TABLE_HAS_NO_PRIMARY_KEY);
1363                }
1364            }
1365        }
1366
1367        token = tokenizer.getSimpleToken();
1368
1369        // -- In a while loop we parse a maximium of two
1370
// -- "ON" statements following the foreign key
1371
// -- definition this can be
1372
// -- ON [UPDATE|DELETE] [NO ACTION|RESTRICT|CASCADE|SET [NULL|DEFAULT]]
1373
int deleteAction = Constraint.NO_ACTION;
1374        int updateAction = Constraint.NO_ACTION;
1375
1376        while (token.equals(Token.T_ON)) {
1377            token = tokenizer.getSimpleToken();
1378
1379            if (deleteAction == Constraint.NO_ACTION
1380                    && token.equals(Token.T_DELETE)) {
1381                token = tokenizer.getSimpleToken();
1382
1383                if (token.equals(Token.T_SET)) {
1384                    token = tokenizer.getSimpleToken();
1385
1386                    if (token.equals(Token.T_DEFAULT)) {
1387                        deleteAction = Constraint.SET_DEFAULT;
1388                    } else if (token.equals(Token.T_NULL)) {
1389                        deleteAction = Constraint.SET_NULL;
1390                    } else {
1391                        throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1392                    }
1393                } else if (token.equals(Token.T_CASCADE)) {
1394                    deleteAction = Constraint.CASCADE;
1395                } else if (token.equals(Token.T_RESTRICT)) {
1396
1397                    // LEGACY compatibility/usability
1398
// - same as NO ACTION or nothing at all
1399
} else {
1400                    tokenizer.matchThis(Token.T_NO);
1401                    tokenizer.getThis(Token.T_ACTION);
1402                }
1403            } else if (updateAction == Constraint.NO_ACTION
1404                       && token.equals(Token.T_UPDATE)) {
1405                token = tokenizer.getSimpleToken();
1406
1407                if (token.equals(Token.T_SET)) {
1408                    token = tokenizer.getSimpleToken();
1409
1410                    if (token.equals(Token.T_DEFAULT)) {
1411                        updateAction = Constraint.SET_DEFAULT;
1412                    } else if (token.equals(Token.T_NULL)) {
1413                        updateAction = Constraint.SET_NULL;
1414                    } else {
1415                        throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1416                    }
1417                } else if (token.equals(Token.T_CASCADE)) {
1418                    updateAction = Constraint.CASCADE;
1419                } else if (token.equals(Token.T_RESTRICT)) {
1420
1421                    // LEGACY compatibility/usability
1422
// - same as NO ACTION or nothing at all
1423
} else {
1424                    tokenizer.matchThis(Token.T_NO);
1425                    tokenizer.getThis(Token.T_ACTION);
1426                }
1427            } else {
1428                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1429            }
1430
1431            token = tokenizer.getSimpleToken();
1432        }
1433
1434        tokenizer.back();
1435
1436        if (cname == null) {
1437            cname = database.nameManager.newAutoName("FK");
1438        }
1439
1440        return new Constraint(cname, localcol, expTable, expcol,
1441                              Constraint.FOREIGN_KEY, deleteAction,
1442                              updateAction);
1443    }
1444
1445    /**
1446     * Responsible for handling the execution CREATE VIEW SQL statements.
1447     *
1448     * @throws HsqlException
1449     */

1450    private void processCreateView() throws HsqlException {
1451
1452        String JavaDoc name = tokenizer.getName();
1453        HsqlName schemaname =
1454            session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst());
1455        int logposition = tokenizer.getPartMarker();
1456
1457        database.schemaManager.checkUserViewNotExists(session, name,
1458                schemaname.name);
1459
1460        HsqlName viewHsqlName = database.nameManager.newHsqlName(name,
1461            tokenizer.wasQuotedIdentifier());
1462
1463        viewHsqlName.schema = schemaname;
1464
1465        HsqlName[] colList = null;
1466
1467        // fredt - a bug in 1.8.0.0 and previous versions causes view
1468
// definitions to script without double quotes around column names
1469
// in certain cases; the workaround here discards such scripted column
1470
// lists when used in OOo
1471
if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
1472            try {
1473                HsqlArrayList list = Parser.getColumnNames(database, null,
1474                    tokenizer, true);
1475
1476                colList = new HsqlName[list.size()];
1477                colList = (HsqlName[]) list.toArray(colList);
1478
1479                //added lines to make sure all valid columns are quoted
1480
if (database.isStoredFileAccess()) {
1481                    for (int i = 0; i < colList.length; i++) {
1482                        if (!colList[i].isNameQuoted) {
1483                            colList = null;
1484
1485                            break;
1486                        }
1487                    }
1488                }
1489            } catch (HsqlException e) {
1490
1491                //added lines to catch unquoted names with spaces
1492
if (database.isStoredFileAccess()) {
1493                    while (!tokenizer.getString().equals(
1494                            Token.T_CLOSEBRACKET)) {}
1495                } else {
1496                    throw e;
1497                }
1498            }
1499        }
1500
1501        tokenizer.getThis(Token.T_AS);
1502        tokenizer.setPartMarker();
1503
1504        Parser parser = new Parser(session, database, tokenizer);
1505        int brackets = parser.parseOpenBracketsSelect();
1506        Select select;
1507
1508        // accept ORDER BY or ORDRY BY with LIMIT - accept unions
1509
select = parser.parseSelect(brackets, true, false, true, true);
1510
1511        if (select.sIntoTable != null) {
1512            throw (Trace.error(Trace.INVALID_IDENTIFIER, Token.INTO));
1513        }
1514
1515        select.prepareResult(session);
1516
1517        View view = new View(session, database, viewHsqlName,
1518                             tokenizer.getLastPart(), colList);
1519
1520        session.commit();
1521        database.schemaManager.linkTable(view);
1522        tokenizer.setPartMarker(logposition);
1523    }
1524
1525    /**
1526     * Responsible for handling tail of ALTER TABLE ... RENAME ...
1527     * @param t table
1528     * @throws HsqlException
1529     */

1530    private void processAlterTableRename(Table t) throws HsqlException {
1531
1532        String JavaDoc schema = t.getSchemaName();
1533        String JavaDoc newName;
1534        boolean isquoted;
1535
1536        // ensures that if temp table, it also belongs to this session
1537
/*
1538        if (!t.equals(session, name)) {
1539            throw Trace.error(Trace.TABLE_NOT_FOUND);
1540        }
1541*/

1542        tokenizer.getThis(Token.T_TO);
1543
1544        newName = tokenizer.getName();
1545
1546        String JavaDoc newSchema = tokenizer.getLongNameFirst();
1547
1548        isquoted = tokenizer.wasQuotedIdentifier();
1549        newSchema = newSchema == null ? schema
1550                                      : session.getSchemaNameForWrite(
1551                                          newSchema);
1552
1553        if (!schema.equals(newSchema)) {
1554            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
1555        }
1556
1557        database.schemaManager.checkUserTableNotExists(session, newName,
1558                schema);
1559        session.commit();
1560        session.setScripting(true);
1561        database.schemaManager.renameTable(session, t, newName, isquoted);
1562    }
1563
1564    /**
1565     * Handles ALTER TABLE statements. <p>
1566     *
1567     * ALTER TABLE <name> RENAME TO <newname>
1568     * ALTER INDEX <name> RENAME TO <newname>
1569     *
1570     * ALTER TABLE <name> ADD CONSTRAINT <constname> FOREIGN KEY (<col>, ...)
1571     * REFERENCE <other table> (<col>, ...) [ON DELETE CASCADE]
1572     *
1573     * ALTER TABLE <name> ADD CONSTRAINT <constname> UNIQUE (<col>, ...)
1574     *
1575     * @throws HsqlException
1576     */

1577    private void processAlter() throws HsqlException {
1578
1579        String JavaDoc token;
1580
1581        session.checkAdmin();
1582        session.checkDDLWrite();
1583        session.setScripting(true);
1584
1585        token = tokenizer.getSimpleToken();
1586
1587        switch (Token.get(token)) {
1588
1589            case Token.INDEX : {
1590                processAlterIndex();
1591
1592                break;
1593            }
1594            case Token.SCHEMA : {
1595                processAlterSchema();
1596
1597                break;
1598            }
1599            case Token.SEQUENCE : {
1600                processAlterSequence();
1601
1602                break;
1603            }
1604            case Token.TABLE : {
1605                processAlterTable();
1606
1607                break;
1608            }
1609            case Token.USER : {
1610                processAlterUser();
1611
1612                break;
1613            }
1614            default : {
1615                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1616            }
1617        }
1618    }
1619
1620    /**
1621     * Handles ALTER TABLE DDL.
1622     *
1623     * @throws HsqlException
1624     */

1625    private void processAlterTable() throws HsqlException {
1626
1627        String JavaDoc tableName = tokenizer.getName();
1628        String JavaDoc schema =
1629            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
1630        Table t = database.schemaManager.getUserTable(session, tableName,
1631            schema);
1632        String JavaDoc token;
1633
1634        if (t.isView()) {
1635            throw Trace.error(Trace.NOT_A_TABLE);
1636        }
1637
1638        session.setScripting(true);
1639
1640        token = tokenizer.getSimpleToken();
1641
1642        switch (Token.get(token)) {
1643
1644            case Token.RENAME : {
1645                processAlterTableRename(t);
1646
1647                return;
1648            }
1649            case Token.ADD : {
1650                HsqlName cname = null;
1651
1652                if (tokenizer.isGetThis(Token.T_CONSTRAINT)) {
1653                    token = tokenizer.getName();
1654
1655                    String JavaDoc constraintSchema = tokenizer.getLongNameFirst();
1656
1657                    if (constraintSchema != null) {
1658                        constraintSchema = session.getSchemaNameForWrite(
1659                            tokenizer.getLongNameFirst());
1660
1661                        if (!t.getSchemaName().equals(constraintSchema)) {
1662                            throw Trace.error(
1663                                Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
1664                                constraintSchema);
1665                        }
1666                    }
1667
1668                    cname = database.nameManager.newHsqlName(token,
1669                            tokenizer.wasQuotedIdentifier());
1670                }
1671
1672                token = tokenizer.getString();
1673
1674                if (tokenizer.wasQuotedIdentifier()
1675                        && tokenizer.wasSimpleName()) {
1676                    tokenizer.back();
1677                    processAlterTableAddColumn(t);
1678
1679                    return;
1680                }
1681
1682                if (!tokenizer.wasSimpleToken()) {
1683                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1684                }
1685
1686                switch (Token.get(token)) {
1687
1688                    case Token.FOREIGN :
1689                        tokenizer.getThis(Token.T_KEY);
1690                        processAlterTableAddForeignKeyConstraint(t, cname);
1691
1692                        return;
1693
1694                    case Token.UNIQUE :
1695                        processAlterTableAddUniqueConstraint(t, cname);
1696
1697                        return;
1698
1699                    case Token.CHECK :
1700                        processAlterTableAddCheckConstraint(t, cname);
1701
1702                        return;
1703
1704                    case Token.PRIMARY :
1705                        tokenizer.getThis(Token.T_KEY);
1706                        processAlterTableAddPrimaryKey(t, cname);
1707
1708                        return;
1709
1710                    default :
1711                        if (cname != null) {
1712                            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1713                        }
1714
1715                        tokenizer.back();
1716                    case Token.COLUMN :
1717                        processAlterTableAddColumn(t);
1718
1719                        return;
1720                }
1721            }
1722            case Token.DROP : {
1723                token = tokenizer.getString();
1724
1725                if (tokenizer.wasQuotedIdentifier()
1726                        && tokenizer.wasSimpleName()) {
1727                    tokenizer.back();
1728                    processAlterTableDropColumn(t);
1729
1730                    return;
1731                }
1732
1733                if (!tokenizer.wasSimpleToken()) {
1734                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1735                }
1736
1737                switch (Token.get(token)) {
1738
1739                    case Token.PRIMARY :
1740                        tokenizer.getThis(Token.T_KEY);
1741
1742                        if (t.hasPrimaryKey()) {
1743                            processAlterTableDropConstraint(
1744                                t, t.getPrimaryConstraint().getName().name);
1745                        } else {
1746                            throw Trace.error(Trace.CONSTRAINT_NOT_FOUND,
1747                                              Trace.TABLE_HAS_NO_PRIMARY_KEY,
1748                                              new Object JavaDoc[] {
1749                                "PRIMARY KEY", t.getName().name
1750                            });
1751                        }
1752
1753                        return;
1754
1755                    case Token.CONSTRAINT :
1756                        processAlterTableDropConstraint(t);
1757
1758                        return;
1759
1760                    default :
1761                        tokenizer.back();
1762                    case Token.COLUMN :
1763                        processAlterTableDropColumn(t);
1764
1765                        return;
1766                }
1767            }
1768            case Token.ALTER : {
1769                tokenizer.isGetThis(Token.T_COLUMN);
1770                processAlterColumn(t);
1771
1772                return;
1773            }
1774            default : {
1775                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1776            }
1777        }
1778    }
1779
1780    /**
1781     * Handles ALTER COLUMN
1782     *
1783     * @param t table
1784     * @throws HsqlException
1785     */

1786    private void processAlterColumn(Table t) throws HsqlException {
1787
1788        String JavaDoc columnName = tokenizer.getSimpleName();
1789        int columnIndex = t.getColumnNr(columnName);
1790        Column column = t.getColumn(columnIndex);
1791        String JavaDoc token = tokenizer.getSimpleToken();
1792
1793        switch (Token.get(token)) {
1794
1795            case Token.RENAME : {
1796                tokenizer.getThis(Token.T_TO);
1797                processAlterColumnRename(t, column);
1798
1799                return;
1800            }
1801            case Token.DROP : {
1802                tokenizer.getThis(Token.T_DEFAULT);
1803
1804                TableWorks tw = new TableWorks(session, t);
1805
1806                tw.setColDefaultExpression(columnIndex, null);
1807
1808                return;
1809            }
1810            case Token.SET : {
1811
1812//4-8-2005 MarcH and HuugO ALTER TABLE <tablename> ALTER COLUMN <column name> SET [NOT] NULL support added
1813
token = tokenizer.getSimpleToken();
1814
1815                if (token.equals(Token.T_NOT)) {
1816                    tokenizer.getThis(Token.T_NULL);
1817
1818                    TableWorks tw = new TableWorks(session, t);
1819
1820                    tw.setColNullability(column, false);
1821                } else if (token.equals(Token.T_NULL)) {
1822                    TableWorks tw = new TableWorks(session, t);
1823
1824                    tw.setColNullability(column, true);
1825                } else if (token.equals(Token.T_DEFAULT)) {
1826
1827                    //alter table alter column set default
1828
TableWorks tw = new TableWorks(session, t);
1829                    int type = column.getType();
1830                    int length = column.getSize();
1831                    int scale = column.getScale();
1832                    Expression expr = processCreateDefaultExpression(type,
1833                        length, scale);
1834
1835                    tw.setColDefaultExpression(columnIndex, expr);
1836                } else {
1837                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1838                }
1839
1840                return;
1841            }
1842            case Token.RESTART : {
1843                tokenizer.getThis(Token.T_WITH);
1844
1845                long identityStart = tokenizer.getBigint();
1846                int id = t.getIdentityColumn();
1847
1848                if (id == -1) {
1849                    throw Trace.error(Trace.OPERATION_NOT_SUPPORTED);
1850                }
1851
1852                t.identitySequence.reset(identityStart);
1853
1854                return;
1855            }
1856            default : {
1857                tokenizer.back();
1858                processAlterColumnType(t, column);
1859            }
1860        }
1861    }
1862
1863    private void processAlterColumnType(Table table,
1864                                        Column oldCol) throws HsqlException {
1865
1866        Column newCol = processCreateColumn(oldCol.columnName);
1867        TableWorks tw = new TableWorks(session, table);
1868
1869        tw.reTypeColumn(oldCol, newCol);
1870    }
1871
1872    /**
1873     * Responsible for handling tail of ALTER COLUMN ... RENAME ...
1874     * @param t table
1875     * @param column column
1876     * @throws HsqlException
1877     */

1878    private void processAlterColumnRename(Table t,
1879                                          Column column)
1880                                          throws HsqlException {
1881
1882        String JavaDoc newName = tokenizer.getSimpleName();
1883        boolean isquoted = tokenizer.wasQuotedIdentifier();
1884
1885        if (t.findColumn(newName) > -1) {
1886            throw Trace.error(Trace.COLUMN_ALREADY_EXISTS, newName);
1887        }
1888
1889        t.database.schemaManager.checkColumnIsInView(t,
1890                column.columnName.name);
1891        session.commit();
1892        session.setScripting(true);
1893        t.renameColumn(column, newName, isquoted);
1894    }
1895
1896    /**
1897     * Handles ALTER INDEX.
1898     *
1899     * @throws HsqlException
1900     */

1901    private void processAlterIndex() throws HsqlException {
1902
1903        // only the one supported operation, so far
1904
processAlterIndexRename();
1905    }
1906
1907    private void processAlterSchema() throws HsqlException {
1908
1909        // only the one supported operation, so far
1910
processAlterSchemaRename();
1911    }
1912
1913    /**
1914     * Responsible for handling parse and execute of SQL DROP DDL
1915     *
1916     * @throws HsqlException
1917     */

1918    private void processDrop() throws HsqlException {
1919
1920        String JavaDoc token;
1921        boolean isview;
1922
1923        session.checkReadWrite();
1924        session.checkAdmin();
1925        session.setScripting(true);
1926
1927        token = tokenizer.getSimpleToken();
1928        isview = false;
1929
1930        switch (Token.get(token)) {
1931
1932            case Token.INDEX : {
1933                processDropIndex();
1934
1935                break;
1936            }
1937            case Token.SCHEMA : {
1938                processDropSchema();
1939
1940                break;
1941            }
1942            case Token.SEQUENCE : {
1943                processDropSequence();
1944
1945                break;
1946            }
1947            case Token.TRIGGER : {
1948                processDropTrigger();
1949
1950                break;
1951            }
1952            case Token.USER : {
1953                processDropUser();
1954
1955                break;
1956            }
1957            case Token.ROLE : {
1958                database.getGranteeManager().dropRole(
1959                    tokenizer.getSimpleName());
1960
1961                break;
1962            }
1963            case Token.VIEW : {
1964                isview = true;
1965            } //fall thru
1966
case Token.TABLE : {
1967                processDropTable(isview);
1968
1969                break;
1970            }
1971            default : {
1972                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
1973            }
1974        }
1975    }
1976
1977    /**
1978     * Responsible for handling the execution of GRANT and REVOKE SQL
1979     * statements.
1980     *
1981     * @param grant true if grant, false if revoke
1982     * @throws HsqlException
1983     */

1984    private void processGrantOrRevoke(boolean grant) throws HsqlException {
1985
1986        int right;
1987        Object JavaDoc accessKey;
1988        String JavaDoc token;
1989
1990        session.checkAdmin();
1991        session.checkDDLWrite();
1992        session.setScripting(true);
1993
1994        right = 0;
1995        token = tokenizer.getSimpleToken();
1996
1997        tokenizer.back();
1998
1999        if (!GranteeManager.validRightString(token)) {
2000            processRoleGrantOrRevoke(grant);
2001
2002            return;
2003        }
2004
2005        do {
2006            token = tokenizer.getSimpleToken();
2007            right |= GranteeManager.getCheckRight(token);
2008        } while (tokenizer.isGetThis(Token.T_COMMA));
2009
2010        tokenizer.getThis(Token.T_ON);
2011
2012        accessKey = null;
2013
2014        if (tokenizer.isGetThis(Token.T_CLASS)) {
2015            accessKey = tokenizer.getSimpleName();
2016
2017            if (!tokenizer.wasQuotedIdentifier()) {
2018                throw Trace.error(Trace.QUOTED_IDENTIFIER_REQUIRED);
2019            }
2020        } else {
2021            token = tokenizer.getName();
2022
2023            String JavaDoc schema =
2024                session.getSchemaName(tokenizer.getLongNameFirst());
2025            Table t = database.schemaManager.getTable(session, token, schema);
2026
2027            accessKey = t.getName();
2028
2029            session.setScripting(true);
2030        }
2031
2032        tokenizer.getThis(grant ? Token.T_TO
2033                                : Token.T_FROM);
2034
2035        token = getUserIdentifier();
2036
2037        GranteeManager gm = database.getGranteeManager();
2038
2039        if (grant) {
2040            gm.grant(token, accessKey, right);
2041        } else {
2042            gm.revoke(token, accessKey, right);
2043        }
2044    }
2045
2046    /**
2047     * Responsible for handling CONNECT
2048     *
2049     * @throws HsqlException
2050     */

2051    private void processConnect() throws HsqlException {
2052
2053        String JavaDoc userName;
2054        String JavaDoc password;
2055        User user;
2056
2057        tokenizer.getThis(Token.T_USER);
2058
2059        userName = getUserIdentifier();
2060
2061        if (tokenizer.isGetThis(Token.T_PASSWORD)) {
2062
2063            // legacy log statement or connect statement issued by user
2064
password = getPassword();
2065            user = database.getUserManager().getUser(userName, password);
2066
2067            session.commit();
2068            session.setUser(user);
2069            database.logger.logConnectUser(session);
2070        } else if (session.isProcessingLog) {
2071
2072            // processing log statement
2073
// do not change the user, as isSys() must remain true when processing log
2074
session.commit();
2075        } else {
2076
2077            // force throw if not log statement
2078
tokenizer.getThis(Token.T_PASSWORD);
2079        }
2080    }
2081
2082    /**
2083     * Responsible for handling the execution of SET SQL statements
2084     *
2085     * @throws HsqlException
2086     */

2087    private void processSet() throws HsqlException {
2088
2089        String JavaDoc token;
2090
2091        session.setScripting(true);
2092
2093        token = tokenizer.getSimpleToken();
2094
2095        switch (Token.get(token)) {
2096
2097            case Token.PROPERTY : {
2098                HsqlDatabaseProperties p;
2099
2100                session.checkAdmin();
2101
2102                token = tokenizer.getSimpleName();
2103
2104                if (!tokenizer.wasQuotedIdentifier()) {
2105                    throw Trace.error(Trace.QUOTED_IDENTIFIER_REQUIRED);
2106                }
2107
2108                p = database.getProperties();
2109
2110                boolean isboolean = p.isBoolean(token);
2111                boolean isintegral = p.isIntegral(token);
2112                boolean isstring = p.isString(token);
2113
2114                Trace.check(isboolean || isintegral || isstring,
2115                            Trace.ACCESS_IS_DENIED, token);
2116
2117                int type = isboolean ? Types.BOOLEAN
2118                                         : isintegral ? Types.INTEGER
2119                                                      : Types.VARCHAR;
2120                Object JavaDoc value = tokenizer.getInType(type);
2121
2122                if (HsqlDatabaseProperties.hsqldb_cache_file_scale.equals(
2123                        token)) {
2124                    if (database.logger.hasCache()
2125                            || ((Integer JavaDoc) value).intValue() != 8) {
2126                        Trace.throwerror(Trace.ACCESS_IS_DENIED, token);
2127                    }
2128                }
2129
2130                p.setDatabaseProperty(token, value.toString().toLowerCase());
2131                p.setDatabaseVariables();
2132
2133                break;
2134            }
2135            case Token.SCHEMA : {
2136                session.setScripting(false);
2137                session.setSchema(tokenizer.getSimpleName());
2138
2139                break;
2140            }
2141            case Token.PASSWORD : {
2142                session.checkDDLWrite();
2143                session.getUser().setPassword(getPassword());
2144
2145                break;
2146            }
2147            case Token.READONLY : {
2148                session.commit();
2149                session.setReadOnly(processTrueOrFalse());
2150
2151                break;
2152            }
2153            case Token.LOGSIZE : {
2154                session.checkAdmin();
2155                session.checkDDLWrite();
2156
2157                int i = tokenizer.getInt();
2158
2159                database.logger.setLogSize(i);
2160
2161                break;
2162            }
2163            case Token.SCRIPTFORMAT : {
2164                session.checkAdmin();
2165                session.checkDDLWrite();
2166                session.setScripting(false);
2167
2168                token = tokenizer.getSimpleToken();
2169
2170                int i = ArrayUtil.find(ScriptWriterBase.LIST_SCRIPT_FORMATS,
2171                                       token);
2172
2173                if (i == 0 || i == 1 || i == 3) {
2174                    database.logger.setScriptType(i);
2175                } else {
2176                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
2177                }
2178
2179                break;
2180            }
2181            case Token.IGNORECASE : {
2182                session.checkAdmin();
2183                session.checkDDLWrite();
2184                database.setIgnoreCase(processTrueOrFalse());
2185
2186                break;
2187            }
2188            case Token.MAXROWS : {
2189                session.setScripting(false);
2190
2191                int i = tokenizer.getInt();
2192
2193                session.setSQLMaxRows(i);
2194
2195                break;
2196            }
2197            case Token.AUTOCOMMIT : {
2198                session.setAutoCommit(processTrueOrFalse());
2199
2200                break;
2201            }
2202            case Token.TABLE : {
2203                session.checkAdmin();
2204                session.checkDDLWrite();
2205
2206                token = tokenizer.getName();
2207
2208                String JavaDoc schema = session.getSchemaNameForWrite(
2209                    tokenizer.getLongNameFirst());
2210                Table t = database.schemaManager.getTable(session, token,
2211                    schema);
2212
2213                token = tokenizer.getSimpleToken();
2214
2215                session.setScripting(true);
2216
2217                switch (Token.get(token)) {
2218
2219                    default : {
2220                        throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
2221                    }
2222                    case Token.SOURCE : {
2223                        session.checkAdmin();
2224
2225                        if (tokenizer.isGetThis(Token.T_HEADER)) {
2226                            token = tokenizer.getString();
2227
2228                            if (!tokenizer.wasQuotedIdentifier()) {
2229                                throw Trace.error(Trace.TEXT_TABLE_SOURCE);
2230                            }
2231
2232                            t.setHeader(token);
2233
2234                            break;
2235                        }
2236
2237                        token = tokenizer.getString();
2238
2239                        if (!tokenizer.wasQuotedIdentifier()) {
2240                            throw Trace.error(Trace.TEXT_TABLE_SOURCE);
2241                        }
2242
2243                        boolean isDesc = false;
2244
2245                        isDesc = tokenizer.isGetThis(Token.T_DESC);
2246
2247                        t.setDataSource(session, token, isDesc, false);
2248
2249                        break;
2250                    }
2251                    case Token.READONLY : {
2252                        session.checkAdmin();
2253                        t.setDataReadOnly(processTrueOrFalse());
2254
2255                        break;
2256                    }
2257                    case Token.INDEX : {
2258                        session.checkAdmin();
2259
2260                        String JavaDoc roots =
2261                            (String JavaDoc) tokenizer.getInType(Types.VARCHAR);
2262
2263                        t.setIndexRoots(roots);
2264
2265                        break;
2266                    }
2267                }
2268
2269                break;
2270            }
2271            case Token.REFERENTIAL_INTEGRITY : {
2272                session.checkAdmin();
2273                session.checkDDLWrite();
2274                session.setScripting(false);
2275                database.setReferentialIntegrity(processTrueOrFalse());
2276
2277                break;
2278            }
2279            case Token.CHECKPOINT : {
2280                session.checkAdmin();
2281                session.checkDDLWrite();
2282                tokenizer.getThis(Token.T_DEFRAG);
2283
2284                int size = tokenizer.getInt();
2285
2286                database.getProperties().setProperty(
2287                    HsqlDatabaseProperties.hsqldb_defrag_limit, size);
2288
2289                break;
2290            }
2291            case Token.WRITE_DELAY : {
2292                session.checkAdmin();
2293                session.checkDDLWrite();
2294
2295                int delay = 0;
2296
2297                tokenizer.getString();
2298
2299                Object JavaDoc value = tokenizer.getAsValue();
2300
2301                if (tokenizer.getType() == Types.INTEGER) {
2302                    delay = ((Integer JavaDoc) value).intValue();
2303                } else if (Boolean.TRUE.equals(value)) {
2304                    delay = database.getProperties().getDefaultWriteDelay();
2305                } else if (Boolean.FALSE.equals(value)) {
2306                    delay = 0;
2307                } else {
2308                    throw Trace.error(Trace.UNEXPECTED_TOKEN);
2309                }
2310
2311                if (!tokenizer.isGetThis("MILLIS")) {
2312                    delay *= 1000;
2313                }
2314
2315                database.logger.setWriteDelay(delay);
2316
2317                break;
2318            }
2319            case Token.DATABASE : {
2320                session.checkAdmin();
2321                session.checkDDLWrite();
2322                tokenizer.getThis(Token.T_COLLATION);
2323
2324                String JavaDoc cname = tokenizer.getSimpleName();
2325
2326                if (!tokenizer.wasQuotedIdentifier()) {
2327                    throw Trace.error(Trace.INVALID_IDENTIFIER);
2328                }
2329
2330                database.collation.setCollation(cname);
2331
2332                break;
2333            }
2334            default : {
2335                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
2336            }
2337        }
2338    }
2339
2340    /**
2341     * Retrieves boolean value corresponding to the next token.
2342     *
2343     * @return true if next token is "TRUE"; false if next token is "FALSE"
2344     * @throws HsqlException if the next token is neither "TRUE" or "FALSE"
2345     */

2346    private boolean processTrueOrFalse() throws HsqlException {
2347
2348        String JavaDoc sToken = tokenizer.getSimpleToken();
2349
2350        if (sToken.equals(Token.T_TRUE)) {
2351            return true;
2352        } else if (sToken.equals(Token.T_FALSE)) {
2353            return false;
2354        } else {
2355            throw Trace.error(Trace.UNEXPECTED_TOKEN, sToken);
2356        }
2357    }
2358
2359    /**
2360     * Responsible for handling the execution of COMMIT [WORK]
2361     *
2362     * @throws HsqlException
2363     */

2364    private void processCommit() throws HsqlException {
2365        tokenizer.isGetThis(Token.T_WORK);
2366        session.commit();
2367    }
2368
2369    /**
2370     * Responsible for handling the execution of ROLLBACK SQL statements.
2371     *
2372     * @throws HsqlException
2373     */

2374    private void processRollback() throws HsqlException {
2375
2376        String JavaDoc token;
2377        boolean toSavepoint;
2378
2379        token = tokenizer.getSimpleToken();
2380        toSavepoint = false;
2381
2382        if (token.equals(Token.T_WORK)) {
2383
2384            // do nothing
2385
} else if (token.equals(Token.T_TO)) {
2386            tokenizer.getThis(Token.T_SAVEPOINT);
2387
2388            token = tokenizer.getSimpleName();
2389            toSavepoint = true;
2390        } else {
2391            tokenizer.back();
2392        }
2393
2394        if (toSavepoint) {
2395            session.rollbackToSavepoint(token);
2396        } else {
2397            session.rollback();
2398        }
2399    }
2400
2401    /**
2402     * Responsible for handling the execution of SAVEPOINT SQL statements.
2403     *
2404     * @throws HsqlException
2405     */

2406    private void processSavepoint() throws HsqlException {
2407
2408        String JavaDoc token;
2409
2410        token = tokenizer.getSimpleName();
2411
2412        session.savepoint(token);
2413    }
2414
2415    /**
2416     * Responsible for handling the execution of SHUTDOWN SQL statements
2417     *
2418     * @throws HsqlException
2419     */

2420    private void processShutdown() throws HsqlException {
2421
2422        int closemode;
2423        String JavaDoc token;
2424
2425        // HUH? We should *NEVER* be able to get here if session is closed
2426
if (!session.isClosed()) {
2427            session.checkAdmin();
2428        }
2429
2430        closemode = Database.CLOSEMODE_NORMAL;
2431        token = tokenizer.getSimpleToken();
2432
2433        // fredt - todo - catch misspelt qualifiers here and elsewhere
2434
if (token.equals(Token.T_IMMEDIATELY)) {
2435            closemode = Database.CLOSEMODE_IMMEDIATELY;
2436        } else if (token.equals(Token.T_COMPACT)) {
2437            closemode = Database.CLOSEMODE_COMPACT;
2438        } else if (token.equals(Token.T_SCRIPT)) {
2439            closemode = Database.CLOSEMODE_SCRIPT;
2440        } else if (token.equals(Token.T_SEMICOLON)) {
2441
2442            // only semicolon is accepted here
2443
} else if (token.length() != 0) {
2444            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
2445        }
2446
2447        database.close(closemode);
2448    }
2449
2450    /**
2451     * Responsible for handling CHECKPOINT [DEFRAG].
2452     *
2453     * @throws HsqlException
2454     */

2455    private void processCheckpoint() throws HsqlException {
2456
2457        boolean defrag;
2458        String JavaDoc token;
2459
2460        session.checkAdmin();
2461        session.checkDDLWrite();
2462
2463        defrag = false;
2464        token = tokenizer.getSimpleToken();
2465
2466        if (token.equals(Token.T_DEFRAG)) {
2467            defrag = true;
2468        } else if (token.equals(Token.T_SEMICOLON)) {
2469
2470            // only semicolon is accepted here
2471
} else if (token.length() != 0) {
2472            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
2473        }
2474
2475        database.logger.checkpoint(defrag);
2476    }
2477
2478// --------------------- new methods / simplifications ------------------------
2479
private HsqlName newIndexHsqlName(String JavaDoc name,
2480                                      boolean isQuoted) throws HsqlException {
2481
2482        return HsqlName.isReservedIndexName(name)
2483               ? database.nameManager.newAutoName("USER", name)
2484               : database.nameManager.newHsqlName(name, isQuoted);
2485    }
2486
2487    private Table newTable(int type, String JavaDoc name, boolean quoted,
2488                           HsqlName schema) throws HsqlException {
2489
2490        HsqlName tableHsqlName = database.nameManager.newHsqlName(name,
2491            quoted);
2492
2493        tableHsqlName.schema = schema;
2494
2495        switch (type) {
2496
2497            case Table.TEMP_TEXT_TABLE :
2498            case Table.TEXT_TABLE : {
2499                return new TextTable(database, tableHsqlName, type);
2500            }
2501            default : {
2502                return new Table(database, tableHsqlName, type);
2503            }
2504        }
2505    }
2506
2507    /**
2508     * Checks if the attributes of the Column argument, c, are compatible with
2509     * the operation of adding such a Column to the Table argument, t.
2510     *
2511     * @param t to which to add the Column, c
2512     * @param c the Column to add to the Table, t
2513     * @throws HsqlException if the operation of adding the Column, c, to
2514     * the table t is not valid
2515     */

2516    private void checkAddColumn(Table t, Column c) throws HsqlException {
2517
2518        boolean canAdd = true;
2519
2520        if (t.findColumn(c.columnName.name) != -1) {
2521            throw Trace.error(Trace.COLUMN_ALREADY_EXISTS);
2522        }
2523
2524        if (c.isPrimaryKey() && t.hasPrimaryKey()) {
2525            canAdd = false;
2526        }
2527
2528        if (canAdd &&!t.isEmpty(session)) {
2529            canAdd = c.isNullable() || c.getDefaultExpression() != null;
2530        }
2531
2532        if (!canAdd) {
2533            throw Trace.error(Trace.BAD_ADD_COLUMN_DEFINITION);
2534        }
2535    }
2536
2537    private void checkFKColumnDefaults(Table t,
2538                                       Constraint tc) throws HsqlException {
2539
2540        boolean check = tc.core.updateAction == Constraint.SET_DEFAULT;
2541
2542        check = check || tc.core.deleteAction == Constraint.SET_DEFAULT;
2543
2544        if (check) {
2545            int[] localCol = tc.core.mainColArray;
2546
2547            for (int j = 0; j < localCol.length; j++) {
2548                Column column = t.getColumn(localCol[j]);
2549                Expression defExpr = column.getDefaultExpression();
2550
2551                if (defExpr == null) {
2552                    String JavaDoc columnName = column.columnName.name;
2553
2554                    throw Trace.error(Trace.NO_DEFAULT_VALUE_FOR_COLUMN,
2555                                      new Object JavaDoc[]{ columnName });
2556                }
2557            }
2558        }
2559    }
2560
2561    private void processAlterSequence() throws HsqlException {
2562
2563        long start;
2564        String JavaDoc name = tokenizer.getName();
2565        String JavaDoc schemaname = tokenizer.getLongNameFirst();
2566
2567        schemaname = session.getSchemaNameForWrite(schemaname);
2568
2569        tokenizer.getThis(Token.T_RESTART);
2570        tokenizer.getThis(Token.T_WITH);
2571
2572        start = tokenizer.getBigint();
2573
2574        NumberSequence seq = database.schemaManager.getSequence(name,
2575            schemaname);
2576
2577        seq.reset(start);
2578    }
2579
2580    /**
2581     * Handles ALTER INDEX &lt;index-name&gt; RENAME.
2582     *
2583     * @throws HsqlException
2584     */

2585    private void processAlterIndexRename() throws HsqlException {
2586
2587        String JavaDoc name = tokenizer.getName();
2588        String JavaDoc schema =
2589            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
2590
2591        tokenizer.getThis(Token.T_RENAME);
2592        tokenizer.getThis(Token.T_TO);
2593
2594        String JavaDoc newName = tokenizer.getName();
2595        String JavaDoc newSchema = tokenizer.getLongNameFirst();
2596
2597        newSchema = newSchema == null ? schema
2598                                      : session.getSchemaNameForWrite(
2599                                          newSchema);
2600
2601        boolean isQuoted = tokenizer.wasQuotedIdentifier();
2602
2603        if (!schema.equals(newSchema)) {
2604            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
2605        }
2606
2607        Table t = database.schemaManager.findUserTableForIndex(session, name,
2608            schema);
2609
2610        if (t == null) {
2611            throw Trace.error(Trace.INDEX_NOT_FOUND, name);
2612        }
2613
2614        database.schemaManager.checkIndexExists(name, t.getSchemaName(),
2615                true);
2616
2617        if (HsqlName.isReservedIndexName(name)) {
2618            throw Trace.error(Trace.SYSTEM_INDEX, name);
2619        }
2620
2621        if (HsqlName.isReservedIndexName(newName)) {
2622            throw Trace.error(Trace.BAD_INDEX_CONSTRAINT_NAME, newName);
2623        }
2624
2625        session.setScripting(true);
2626        session.commit();
2627        t.getIndex(name).setName(newName, isQuoted);
2628        database.schemaManager.renameIndex(name, newName, t.getName());
2629    }
2630
2631    /**
2632     * Handles ALTER SCHEMA ... RENAME TO .
2633     *
2634     * @throws HsqlException
2635     */

2636    private void processAlterSchemaRename() throws HsqlException {
2637
2638        String JavaDoc name = tokenizer.getSimpleName();
2639
2640        tokenizer.getThis(Token.T_RENAME);
2641        tokenizer.getThis(Token.T_TO);
2642
2643        String JavaDoc newName = tokenizer.getSimpleName();
2644        boolean isQuoted = tokenizer.wasQuotedIdentifier();
2645
2646        database.schemaManager.renameSchema(name, newName, isQuoted);
2647    }
2648
2649    /**
2650     *
2651     * @param t table
2652     * @throws HsqlException
2653     */

2654    private void processAlterTableAddColumn(Table t) throws HsqlException {
2655
2656        String JavaDoc token;
2657        int colindex = t.getColumnCount();
2658        Column column = processCreateColumn();
2659
2660        checkAddColumn(t, column);
2661
2662        if (tokenizer.isGetThis(Token.T_BEFORE)) {
2663            token = tokenizer.getSimpleName();
2664            colindex = t.getColumnNr(token);
2665        }
2666
2667        session.commit();
2668
2669        TableWorks tableWorks = new TableWorks(session, t);
2670
2671        tableWorks.addColumn(column, colindex);
2672
2673        return;
2674    }
2675
2676    /**
2677     * Responsible for handling tail of ALTER TABLE ... DROP COLUMN ...
2678     *
2679     * @param t table
2680     * @throws HsqlException
2681     */

2682    private void processAlterTableDropColumn(Table t) throws HsqlException {
2683
2684        String JavaDoc token;
2685        int colindex;
2686
2687        token = tokenizer.getName();
2688        colindex = t.getColumnNr(token);
2689
2690        session.commit();
2691
2692        TableWorks tableWorks = new TableWorks(session, t);
2693
2694        tableWorks.dropColumn(colindex);
2695    }
2696
2697    /**
2698     * Responsible for handling tail of ALTER TABLE ... DROP CONSTRAINT ...
2699     *
2700     * @param t table
2701     * @throws HsqlException
2702     */

2703    private void processAlterTableDropConstraint(Table t)
2704    throws HsqlException {
2705        processAlterTableDropConstraint(t, tokenizer.getName());
2706    }
2707
2708    /**
2709     * Responsible for handling tail of ALTER TABLE ... DROP CONSTRAINT ...
2710     *
2711     * @param t table
2712     * @param name
2713     * @throws HsqlException
2714     */

2715    private void processAlterTableDropConstraint(Table t,
2716            String JavaDoc cname) throws HsqlException {
2717
2718        session.commit();
2719
2720        TableWorks tableWorks = new TableWorks(session, t);
2721
2722        tableWorks.dropConstraint(cname);
2723
2724        return;
2725    }
2726
2727    /**
2728     * If an invalid alias is encountered while processing an old script,
2729     * simply discard it.
2730     */

2731    private void processCreateAlias() throws HsqlException {
2732
2733        String JavaDoc alias;
2734        String JavaDoc methodFQN;
2735
2736        try {
2737            alias = tokenizer.getSimpleName();
2738        } catch (HsqlException e) {
2739            if (session.isProcessingScript()) {
2740                alias = null;
2741            } else {
2742                throw e;
2743            }
2744        }
2745
2746        tokenizer.getThis(Token.T_FOR);
2747
2748        methodFQN = upgradeMethodFQN(tokenizer.getSimpleName());
2749
2750        if (alias != null) {
2751            database.getAliasMap().put(alias, methodFQN);
2752        }
2753    }
2754
2755    private void processCreateIndex(boolean unique) throws HsqlException {
2756
2757        Table t;
2758        String JavaDoc indexName = tokenizer.getName();
2759        String JavaDoc schema = tokenizer.getLongNameFirst();
2760        boolean indexNameQuoted = tokenizer.wasQuotedIdentifier();
2761
2762        tokenizer.getThis(Token.T_ON);
2763
2764        String JavaDoc tablename = tokenizer.getName();
2765        String JavaDoc tableschema =
2766            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
2767
2768        if (schema != null &&!schema.equals(tableschema)) {
2769            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
2770        }
2771
2772        t = database.schemaManager.getTable(session, tablename, tableschema);
2773
2774        database.schemaManager.checkIndexExists(indexName, t.getSchemaName(),
2775                false);
2776
2777        HsqlName indexHsqlName = newIndexHsqlName(indexName, indexNameQuoted);
2778        int[] indexColumns = processColumnList(t, true);
2779        String JavaDoc extra = tokenizer.getSimpleToken();
2780
2781        if (!Token.T_DESC.equals(extra) &&!Token.T_ASC.equals(extra)) {
2782            tokenizer.back();
2783        }
2784
2785        session.commit();
2786        session.setScripting(true);
2787
2788        TableWorks tableWorks = new TableWorks(session, t);
2789
2790        tableWorks.createIndex(indexColumns, indexHsqlName, unique, false,
2791                               false);
2792    }
2793
2794    /**
2795     * limitations in Tokenizer dictate that initial value or increment must
2796     * be positive
2797     * @throws HsqlException
2798     */

2799    private void processCreateSequence() throws HsqlException {
2800
2801/*
2802        CREATE SEQUENCE <name>
2803        [AS {INTEGER | BIGINT}]
2804        [START WITH <value>]
2805        [INCREMENT BY <value>]
2806*/

2807        int type = Types.INTEGER;
2808        long increment = 1;
2809        long start = 0;
2810        String JavaDoc name = tokenizer.getName();
2811        boolean isquoted = tokenizer.wasQuotedIdentifier();
2812        HsqlName schemaname =
2813            session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst());
2814
2815        if (tokenizer.isGetThis(Token.T_AS)) {
2816            String JavaDoc typestring = tokenizer.getSimpleToken();
2817
2818            type = Types.getTypeNr(typestring);
2819
2820            Trace.check(type == Types.INTEGER || type == Types.BIGINT,
2821                        Trace.WRONG_DATA_TYPE);
2822        }
2823
2824        if (tokenizer.isGetThis(Token.T_START)) {
2825            tokenizer.getThis(Token.T_WITH);
2826
2827            start = tokenizer.getBigint();
2828        }
2829
2830        if (tokenizer.isGetThis(Token.T_INCREMENT)) {
2831            tokenizer.getThis(Token.T_BY);
2832
2833            increment = tokenizer.getBigint();
2834        }
2835
2836        HsqlName hsqlname = database.nameManager.newHsqlName(name, isquoted);
2837
2838        hsqlname.schema = schemaname;
2839
2840        database.schemaManager.createSequence(hsqlname, start, increment,
2841                                              type);
2842    }
2843
2844    /**
2845     * CREATE SCHEMA PUBLIC in scripts should pass this, so we do not throw
2846     * if this schema is created a second time
2847     */

2848    private void processCreateSchema() throws HsqlException {
2849
2850        String JavaDoc name = tokenizer.getSimpleName();
2851        boolean isquoted = tokenizer.wasQuotedIdentifier();
2852
2853        if (session.isSchemaDefintion()) {
2854            throw Trace.error(Trace.INVALID_IDENTIFIER);
2855        }
2856
2857        tokenizer.getThis(Token.T_AUTHORIZATION);
2858        tokenizer.getThis(GranteeManager.DBA_ADMIN_ROLE_NAME);
2859
2860        if (database.schemaManager.schemaExists(name)) {
2861            if (!session.isProcessingScript) {
2862                throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
2863            }
2864        } else {
2865            database.schemaManager.createSchema(name, isquoted);
2866        }
2867
2868        HsqlName schemaName = database.schemaManager.getSchemaHsqlName(name);
2869
2870        database.logger.writeToLog(session,
2871                                   DatabaseScript.getSchemaCreateDDL(database,
2872                                       schemaName));
2873        database.logger.writeToLog(session,
2874                                   "SET SCHEMA " + schemaName.statementName);
2875        session.startSchemaDefinition(name);
2876
2877        session.loggedSchema = session.currentSchema;
2878    }
2879
2880    private void processCreateUser() throws HsqlException {
2881
2882        String JavaDoc name;
2883        String JavaDoc password;
2884        boolean admin;
2885
2886        name = getUserIdentifier();
2887
2888        tokenizer.getThis(Token.T_PASSWORD);
2889
2890        password = getPassword();
2891        admin = tokenizer.isGetThis(Token.T_ADMIN);
2892
2893        database.getUserManager().createUser(name, password);
2894
2895        if (admin) {
2896            database.getGranteeManager().grant(
2897                name, GranteeManager.DBA_ADMIN_ROLE_NAME);
2898        }
2899    }
2900
2901    private void processDisconnect() throws HsqlException {
2902        session.close();
2903    }
2904
2905    private void processDropTable(boolean isView) throws HsqlException {
2906
2907        boolean ifexists = false;
2908        boolean cascade = false;
2909
2910        if (tokenizer.isGetThis(Token.T_IF)) {
2911            tokenizer.getThis(Token.T_EXISTS);
2912
2913            ifexists = true;
2914        }
2915
2916        String JavaDoc name = tokenizer.getName();
2917        String JavaDoc schema = tokenizer.getLongNameFirst();
2918
2919        if (tokenizer.isGetThis(Token.T_IF)) {
2920            tokenizer.getThis(Token.T_EXISTS);
2921
2922            ifexists = true;
2923        }
2924
2925        cascade = tokenizer.isGetThis(Token.T_CASCADE);
2926
2927        if (!cascade) {
2928            tokenizer.isGetThis(Token.T_RESTRICT);
2929        }
2930
2931        if (ifexists && schema != null
2932                &&!database.schemaManager.schemaExists(schema)) {
2933            return;
2934        }
2935
2936        schema = session.getSchemaNameForWrite(schema);
2937
2938        database.schemaManager.dropTable(session, name, schema, ifexists,
2939                                         isView, cascade);
2940    }
2941
2942    private void processDropUser() throws HsqlException {
2943
2944        session.checkAdmin();
2945        session.checkDDLWrite();
2946
2947        String JavaDoc userName = getPassword();
2948
2949        if (database.getSessionManager().isUserActive(userName)) {
2950
2951            // todo - new error message "cannot drop a user that is currently connected." // NOI18N
2952
throw Trace.error(Trace.ACCESS_IS_DENIED);
2953        }
2954
2955        database.getUserManager().dropUser(userName);
2956    }
2957
2958    private void processDropSequence() throws HsqlException {
2959
2960        boolean ifexists = false;
2961
2962        session.checkAdmin();
2963        session.checkDDLWrite();
2964
2965        String JavaDoc name = tokenizer.getName();
2966        String JavaDoc schemaname =
2967            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
2968
2969        if (tokenizer.isGetThis(Token.T_IF)) {
2970            tokenizer.getThis(Token.T_EXISTS);
2971
2972            ifexists = true;
2973        }
2974
2975        boolean cascade = tokenizer.isGetThis(Token.T_CASCADE);
2976
2977        if (!cascade) {
2978            tokenizer.isGetThis(Token.T_RESTRICT);
2979        }
2980
2981        NumberSequence sequence = database.schemaManager.findSequence(name,
2982            schemaname);
2983
2984        if (sequence == null) {
2985            if (ifexists) {
2986                return;
2987            } else {
2988                throw Trace.error(Trace.SEQUENCE_NOT_FOUND);
2989            }
2990        }
2991
2992        database.schemaManager.checkCascadeDropViews(sequence, cascade);
2993        database.schemaManager.dropSequence(sequence);
2994    }
2995
2996    private void processDropTrigger() throws HsqlException {
2997
2998        session.checkAdmin();
2999        session.checkDDLWrite();
3000
3001        String JavaDoc triggername = tokenizer.getName();
3002        String JavaDoc schemaname =
3003            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
3004
3005        database.schemaManager.dropTrigger(session, triggername, schemaname);
3006    }
3007
3008    private void processDropIndex() throws HsqlException {
3009
3010        String JavaDoc name = tokenizer.getName();
3011        String JavaDoc schema =
3012            session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
3013        boolean ifexists = false;
3014
3015        // accept a table name - no check performed if it is the right table
3016
if (tokenizer.isGetThis(Token.T_ON)) {
3017            tokenizer.getName();
3018        }
3019
3020        if (tokenizer.isGetThis(Token.T_IF)) {
3021            tokenizer.getThis(Token.T_EXISTS);
3022
3023            ifexists = true;
3024        }
3025
3026        session.checkAdmin();
3027        session.checkDDLWrite();
3028        database.schemaManager.dropIndex(session, name, schema, ifexists);
3029    }
3030
3031    private void processDropSchema() throws HsqlException {
3032
3033        String JavaDoc name = tokenizer.getSimpleName();
3034        boolean cascade = tokenizer.isGetThis(Token.T_CASCADE);
3035
3036        if (!cascade) {
3037            tokenizer.isGetThis(Token.T_RESTRICT);
3038        }
3039
3040        processDropSchema(name, cascade);
3041    }
3042
3043    private void processDropSchema(String JavaDoc name,
3044                                   boolean cascade) throws HsqlException {
3045
3046        if (!database.schemaManager.schemaExists(name)) {
3047            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
3048        }
3049
3050        database.schemaManager.dropSchema(name, cascade);
3051
3052        if (name.equals(session.getSchemaName(null))) {
3053            session.setSchema(database.schemaManager.getDefaultSchemaName());
3054        }
3055    }
3056
3057    private Result processExplainPlan() throws IOException JavaDoc, HsqlException {
3058
3059        // PRE: we assume only one DML or DQL has been submitted
3060
// and simply ignore anything following the first
3061
// sucessfully compliled statement
3062
String JavaDoc token;
3063        Parser parser;
3064        int cmd;
3065        CompiledStatement cs;
3066        Result result;
3067        String JavaDoc line;
3068        LineNumberReader JavaDoc lnr;
3069
3070        tokenizer.getThis(Token.T_PLAN);
3071        tokenizer.getThis(Token.T_FOR);
3072
3073        parser = new Parser(session, database, tokenizer);
3074        token = tokenizer.getSimpleToken();
3075        cmd = Token.get(token);
3076        result = Result.newSingleColumnResult("OPERATION", Types.VARCHAR);
3077
3078        int brackets = 0;
3079
3080        switch (cmd) {
3081
3082            case Token.OPENBRACKET :
3083                brackets = parser.parseOpenBracketsSelect() + 1;
3084            case Token.SELECT :
3085                cs = parser.compileSelectStatement(brackets);
3086                break;
3087
3088            case Token.INSERT :
3089                cs = parser.compileInsertStatement();
3090                break;
3091
3092            case Token.UPDATE :
3093                cs = parser.compileUpdateStatement();
3094                break;
3095
3096            case Token.DELETE :
3097                cs = parser.compileDeleteStatement();
3098                break;
3099
3100            case Token.CALL :
3101                cs = parser.compileCallStatement();
3102                break;
3103
3104            default :
3105
3106                // - No real need to throw, so why bother?
3107
// - Just return result with no rows for now
3108
// - Later, maybe there will be plan desciptions
3109
// for other operations
3110
return result;
3111        }
3112
3113        lnr = new LineNumberReader JavaDoc(new StringReader JavaDoc(cs.describe(session)));
3114
3115        while (null != (line = lnr.readLine())) {
3116            result.add(new Object JavaDoc[]{ line });
3117        }
3118
3119        return result;
3120    }
3121
3122// fredt@users 20010701 - patch 1.6.1 by fredt - open <1.60 db files
3123
// convert org.hsql.Library aliases from versions < 1.60 to org.hsqldb
3124
// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - ABS function
3125
static final String JavaDoc oldLib = "org.hsql.Library.";
3126    static final int oldLibLen = oldLib.length();
3127    static final String JavaDoc newLib = "org.hsqldb.Library.";
3128
3129    private static String JavaDoc upgradeMethodFQN(String JavaDoc fqn) {
3130
3131        if (fqn.startsWith(oldLib)) {
3132            fqn = newLib + fqn.substring(oldLibLen);
3133        } else if (fqn.equals("java.lang.Math.abs")) {
3134            fqn = "org.hsqldb.Library.abs";
3135        }
3136
3137        return fqn;
3138    }
3139
3140    /**
3141     * Processes a SELECT INTO for a new table.
3142     */

3143    Result processSelectInto(Result result, HsqlName intoHsqlName,
3144                             int intoType) throws HsqlException {
3145
3146        // fredt@users 20020215 - patch 497872 by Nitin Chauhan
3147
// to require column labels in SELECT INTO TABLE
3148
int colCount = result.getColumnCount();
3149
3150        for (int i = 0; i < colCount; i++) {
3151            if (result.metaData.colLabels[i].length() == 0) {
3152                throw Trace.error(Trace.LABEL_REQUIRED);
3153            }
3154        }
3155
3156        // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
3157
Table t = (intoType == Table.TEXT_TABLE)
3158                  ? new TextTable(database, intoHsqlName, intoType)
3159                  : new Table(database, intoHsqlName, intoType);
3160
3161        t.addColumns(result.metaData, result.getColumnCount());
3162        t.createPrimaryKey();
3163        database.schemaManager.linkTable(t);
3164
3165        // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
3166
if (intoType == Table.TEXT_TABLE) {
3167            try {
3168
3169                // Use default lowercase name "<table>.csv" (with invalid
3170
// char's converted to underscores):
3171
String JavaDoc txtSrc =
3172                    StringUtil.toLowerSubset(intoHsqlName.name, '_') + ".csv";
3173
3174                t.setDataSource(session, txtSrc, false, true);
3175                logTableDDL(t);
3176                t.insertIntoTable(session, result);
3177            } catch (HsqlException e) {
3178                database.schemaManager.dropTable(session, intoHsqlName.name,
3179                                                 null, false, false, false);
3180
3181                throw (e);
3182            }
3183        } else {
3184            logTableDDL(t);
3185
3186            // SELECT .. INTO can't fail because of constraint violation
3187
t.insertIntoTable(session, result);
3188        }
3189
3190        Result uc = new Result(ResultConstants.UPDATECOUNT);
3191
3192        uc.updateCount = result.getSize();
3193
3194        return uc;
3195    }
3196
3197    /**
3198     * Logs the DDL for a table created with INTO.
3199     * Uses two dummy arguments for getTableDDL() as the new table has no
3200     * FK constraints.
3201     *
3202     *
3203     * @param t table
3204     * @throws HsqlException
3205     */

3206    private void logTableDDL(Table t) throws HsqlException {
3207
3208        StringBuffer JavaDoc tableDDL;
3209        String JavaDoc sourceDDL;
3210
3211        tableDDL = new StringBuffer JavaDoc();
3212
3213        DatabaseScript.getTableDDL(database, t, 0, null, true, tableDDL);
3214
3215        sourceDDL = DatabaseScript.getDataSource(t);
3216
3217        database.logger.writeToLog(session, tableDDL.toString());
3218
3219        if (sourceDDL != null) {
3220            database.logger.writeToLog(session, sourceDDL);
3221        }
3222    }
3223
3224    private void processAlterTableAddUniqueConstraint(Table t,
3225            HsqlName n) throws HsqlException {
3226
3227        int[] col;
3228
3229        col = processColumnList(t, false);
3230
3231        if (n == null) {
3232            n = database.nameManager.newAutoName("CT");
3233        }
3234
3235        session.commit();
3236
3237        TableWorks tableWorks = new TableWorks(session, t);
3238
3239        tableWorks.createUniqueConstraint(col, n);
3240    }
3241
3242    private void processAlterTableAddForeignKeyConstraint(Table t,
3243            HsqlName n) throws HsqlException {
3244
3245        Constraint tc;
3246
3247        if (n == null) {
3248            n = database.nameManager.newAutoName("FK");
3249        }
3250
3251        tc = processCreateFK(t, n);
3252
3253        checkFKColumnDefaults(t, tc);
3254        t.checkColumnsMatch(tc.core.mainColArray, tc.core.refTable,
3255                            tc.core.refColArray);
3256        session.commit();
3257
3258        TableWorks tableWorks = new TableWorks(session, t);
3259
3260        tableWorks.createForeignKey(tc.core.mainColArray,
3261                                    tc.core.refColArray, tc.constName,
3262                                    tc.core.refTable, tc.core.deleteAction,
3263                                    tc.core.updateAction);
3264    }
3265
3266    private void processAlterTableAddCheckConstraint(Table table,
3267            HsqlName name) throws HsqlException {
3268
3269        Constraint check;
3270
3271        if (name == null) {
3272            name = database.nameManager.newAutoName("CT");
3273        }
3274
3275        check = new Constraint(name, null, null, null, Constraint.CHECK,
3276                               Constraint.NO_ACTION, Constraint.NO_ACTION);
3277
3278        processCreateCheckConstraintCondition(check);
3279        session.commit();
3280
3281        TableWorks tableWorks = new TableWorks(session, table);
3282
3283        tableWorks.createCheckConstraint(check, name);
3284    }
3285
3286    private void processAlterTableAddPrimaryKey(Table t,
3287            HsqlName n) throws HsqlException {
3288
3289        int[] col;
3290
3291        col = processColumnList(t, false);
3292
3293        session.commit();
3294
3295        TableWorks tableWorks = new TableWorks(session, t);
3296
3297        tableWorks.addPrimaryKey(col, n);
3298    }
3299
3300    private void processReleaseSavepoint() throws HsqlException {
3301
3302        String JavaDoc token;
3303
3304        tokenizer.getThis(Token.T_SAVEPOINT);
3305
3306        token = tokenizer.getSimpleName();
3307
3308        session.releaseSavepoint(token);
3309    }
3310
3311    private void processAlterUser() throws HsqlException {
3312
3313        String JavaDoc userName;
3314        String JavaDoc password;
3315        User userObject;
3316
3317        userName = getUserIdentifier();
3318        userObject =
3319            (User) database.getUserManager().getUsers().get(userName);
3320
3321        Trace.check(userObject != null, Trace.USER_NOT_FOUND, userName);
3322        tokenizer.getThis(Token.T_SET);
3323        tokenizer.getThis(Token.T_PASSWORD);
3324
3325        password = getPassword();
3326
3327        userObject.setPassword(password);
3328        database.logger.writeToLog(session, userObject.getAlterUserDDL());
3329        session.setScripting(false);
3330    }
3331
3332    private String JavaDoc getUserIdentifier() throws HsqlException {
3333
3334        String JavaDoc token = tokenizer.getString();
3335        Tokenizer t = new Tokenizer(token);
3336
3337        return t.getSimpleName();
3338    }
3339
3340    private String JavaDoc getPassword() throws HsqlException {
3341
3342        String JavaDoc token = tokenizer.getString();
3343
3344        return token.toUpperCase(Locale.ENGLISH);
3345    }
3346
3347    /**
3348     * Responsible for handling the execution of GRANT/REVOKE role...
3349     * statements.
3350     *
3351     * @throws HsqlException
3352     */

3353    private void processRoleGrantOrRevoke(boolean grant)
3354    throws HsqlException {
3355
3356        String JavaDoc token;
3357        HsqlArrayList list = new HsqlArrayList();
3358        String JavaDoc role;
3359        GranteeManager granteeManager = database.getGranteeManager();
3360
3361        do {
3362            role = tokenizer.getSimpleToken();
3363
3364            Trace.check(granteeManager.isRole(role),
3365                        (grant ? Trace.NO_SUCH_ROLE_GRANT
3366                               : Trace.NO_SUCH_ROLE_REVOKE));
3367            list.add(role);
3368        } while (tokenizer.isGetThis(Token.T_COMMA));
3369
3370        tokenizer.getThis(grant ? Token.T_TO
3371                                : Token.T_FROM);
3372
3373        token = getUserIdentifier();
3374
3375        GranteeManager gm = database.getGranteeManager();
3376
3377        for (int i = 0; i < list.size(); i++) {
3378            if (grant) {
3379                gm.grant(token, (String JavaDoc) list.get(i));
3380            } else {
3381                gm.revoke(token, (String JavaDoc) list.get(i));
3382            }
3383        }
3384    }
3385}
3386
Popular Tags