EMMA Coverage Report (generated Wed Jun 28 19:54:35 CEST 2006)
[all classes][smallsql.database]

COVERAGE SUMMARY FOR SOURCE FILE [SQLParser.java]

nameclass, %method, %block, %line, %
SQLParser.java100% (1/1)92%  (45/49)84%  (4076/4832)85%  (887,6/1044)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SQLParser100% (1/1)92%  (45/49)84%  (4076/4832)85%  (887,6/1044)
alter (): Command 0%   (0/1)0%   (0/4)0%   (0/1)
createIndex (): CommandCreateDatabase 0%   (0/1)0%   (0/4)0%   (0/1)
createProcedure (): CommandCreateDatabase 0%   (0/1)0%   (0/4)0%   (0/1)
execute (): Command 0%   (0/1)0%   (0/4)0%   (0/1)
create (): Command 100% (1/1)52%  (17/33)61%  (5,5/9)
checkValidIdentifer (String, SQLToken): void 100% (1/1)52%  (25/48)70%  (7/10)
parse (char []): Command 100% (1/1)54%  (41/76)59%  (13/22)
join (Command, DataSources, RowSource, int): Join 100% (1/1)57%  (39/68)48%  (6,3/13)
drop (): Command 100% (1/1)60%  (40/67)62%  (9,8/16)
delete (): Command 100% (1/1)64%  (21/33)67%  (6/9)
datatype (boolean): Column 100% (1/1)66%  (148/225)64%  (44/69)
expressionSingle (Command, SQLToken): Expression 100% (1/1)70%  (288/411)70%  (52,2/75)
set (): CommandSet 100% (1/1)71%  (10/14)75%  (3/4)
createDatabase (): CommandCreateDatabase 100% (1/1)76%  (16/21)83%  (2,5/3)
singleSelect (): CommandSelect 100% (1/1)79%  (118/150)87%  (37,6/43)
createTable (): CommandCreateTable 100% (1/1)81%  (224/277)83%  (59,8/72)
isKeyword (SQLToken): boolean 100% (1/1)82%  (9/11)88%  (3,5/4)
function (Command, SQLToken, boolean): Expression 100% (1/1)83%  (876/1059)89%  (226,8/255)
tableSource (Command, DataSources): RowSource 100% (1/1)83%  (89/107)81%  (21/26)
rowSource (Command, DataSources, int): RowSource 100% (1/1)84%  (140/167)95%  (39/41)
expressionDefList (Command, Expressions, Strings): void 100% (1/1)84%  (58/69)80%  (13,6/17)
setTransaction (): CommandSet 100% (1/1)87%  (54/62)89%  (17/19)
update (): Command 100% (1/1)87%  (68/78)94%  (18,7/20)
lastToken (): SQLToken 100% (1/1)88%  (15/17)67%  (2/3)
expressionParenthesisList (Command): Expressions 100% (1/1)89%  (34/38)92%  (11/12)
createSyntaxError (SQLToken, int []): SQLException 100% (1/1)90%  (53/59)96%  (10,5/11)
nextToken (int []): SQLToken 100% (1/1)90%  (45/50)90%  (9/10)
expressionTokenList (Command, int): Expressions 100% (1/1)91%  (48/53)94%  (17/18)
index (Command, int, String): IndexDescription 100% (1/1)93%  (50/54)92%  (12/13)
expression (Command, int): Expression 100% (1/1)95%  (196/207)92%  (51,7/56)
caseExpr (Command): ExpressionFunctionCase 100% (1/1)95%  (72/76)95%  (21/22)
insert (): Command 100% (1/1)96%  (104/108)97%  (28/29)
<static initializer> 100% (1/1)100% (771/771)100% (47/47)
SQLParser (): void 100% (1/1)100% (3/3)100% (1/1)
createSyntaxError (SQLToken, String): SQLException 100% (1/1)100% (11/11)100% (2/2)
createSyntaxError (StringBuffer, SQLToken): SQLException 100% (1/1)100% (62/62)100% (10/10)
createView (): CommandCreateView 100% (1/1)100% (49/49)100% (9/9)
from (CommandSelect): void 100% (1/1)100% (39/39)100% (14/14)
getSyntaxError (SQLToken): StringBuffer 100% (1/1)100% (32/32)100% (6/6)
group (CommandSelect): void 100% (1/1)100% (11/11)100% (3/3)
having (CommandSelect): void 100% (1/1)100% (7/7)100% (2/2)
nextToken (): SQLToken 100% (1/1)100% (26/26)100% (4/4)
order (CommandSelect): void 100% (1/1)100% (11/11)100% (3/3)
parse (SSConnection, String): Command 100% (1/1)100% (20/20)100% (6/6)
parseExpression (String): Expression 100% (1/1)100% (17/17)100% (4/4)
previousToken (): void 100% (1/1)100% (7/7)100% (2/2)
select (): CommandSelect 100% (1/1)100% (89/89)100% (21/21)
truncate (): Command 100% (1/1)100% (16/16)100% (4/4)
where (CommandSelect): void 100% (1/1)100% (7/7)100% (2/2)

1/* =============================================================
2 * SmallSQL : a free Java DBMS library for the Java(tm) platform
3 * =============================================================
4 *
5 * (C) Copyright 2004-2006, by Volker Berlin.
6 *
7 * Project Info:  http://www.smallsql.de/
8 *
9 * This library is free software; you can redistribute it and/or modify it 
10 * under the terms of the GNU Lesser General Public License as published by 
11 * the Free Software Foundation; either version 2.1 of the License, or 
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but 
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
22 * USA.  
23 *
24 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
25 * in the United States and other countries.]
26 *
27 * ---------------
28 * SQLParser.java
29 * ---------------
30 * Author: Volker Berlin
31 * 
32 */
33package smallsql.database;
34 
35import java.util.List;
36import java.sql.*;
37 
38 
39public class SQLParser {
40 
41        SSConnection con;
42        private char[] sql;
43    private List tokens;
44    private int tokenIdx;
45 
46    Command parse(SSConnection con, String sql) throws SQLException{
47            this.con = con;
48        Command cmd = parse( sql.toCharArray() );
49        SQLToken token = nextToken();
50        if(token != null){
51                        throw createSyntaxError( token, "Additional token after end of SQL statement");
52        }
53        return cmd;
54    }
55    
56    
57    final private Command parse(char[] sql) throws SQLException{
58        this.sql = sql;
59        this.tokens = SQLTokenizer.parseSQL( sql );
60        tokenIdx = 0;
61 
62        SQLToken token = nextToken(COMMANDS);
63        switch (token.value){
64            case SQLTokenizer.SELECT:
65                    return select();
66            case SQLTokenizer.DELETE:
67                    return delete();
68            case SQLTokenizer.INSERT:
69                    return insert();
70            case SQLTokenizer.UPDATE:
71                    return update();
72            case SQLTokenizer.CREATE:
73                    return create();
74            case SQLTokenizer.DROP:
75                    return drop();
76            case SQLTokenizer.ALTER:
77                    return alter();
78            case SQLTokenizer.SET:
79                    return set();
80                        case SQLTokenizer.USE:
81                                        token = nextToken(MISSING_EXPRESSION);
82                                        String name = token.getName( sql );
83                                        checkValidIdentifer( name, token );
84                                        CommandSet set = new CommandSet( con.log, SQLTokenizer.USE);
85                                        set.name = name;
86                                        return set;
87            case SQLTokenizer.EXECUTE:
88                    return execute();
89            case SQLTokenizer.TRUNCATE:
90                            return truncate();
91            default:
92                    throw new Error();
93        }
94    }
95    
96    
97    Expression parseExpression(String expr) throws SQLException{
98                this.sql = expr.toCharArray();
99                this.tokens = SQLTokenizer.parseSQL( sql );
100                tokenIdx = 0;
101            return expression( null, 0);
102    }
103 
104    private StringBuffer getSyntaxError( SQLToken token ){
105        StringBuffer msg = new StringBuffer(256);
106        if(token != null){
107            msg.append( "Syntax error at offset ").append( token.offset )
108               .append( " on '" ).append( sql, token.offset, token.length ).append("'. ");
109        }else{
110            msg.append( "Syntax error, unexpected end of SQL string. ");
111        }
112        return msg;
113    }
114 
115    private SQLException createSyntaxError(SQLToken token, int[] validValues){
116        StringBuffer msg = getSyntaxError( token );
117 
118        msg.append( "Requied keywords are: " );
119        for(int i=0; i<validValues.length; i++){
120            String name = SQLTokenizer.getKeyWord(validValues[i]);
121            if(name == null) name = String.valueOf( (char)validValues[i] );
122            msg.append( name );
123            if (i < validValues.length - 2)
124                msg.append( ", ");
125            else
126            if ( i == validValues.length - 2 )
127                msg.append( " or ");
128        }
129 
130        return createSyntaxError( msg, token );
131    }
132 
133    private SQLException createSyntaxError( StringBuffer msg, SQLToken token){
134        int offset = (token != null) ? token.offset : sql.length;
135        int begin = Math.max( 0, offset-40);
136        int end   = Math.min( offset+20, sql.length );
137        String lineSeparator = System.getProperty( "line.separator" );
138        msg.append( lineSeparator );
139        msg.append( sql, begin, end-begin);
140        msg.append( lineSeparator );
141        for(; begin<offset; begin++) msg.append(' ');
142        msg.append('^');
143        return new SQLException( msg.toString()/* , offset*/ );
144    }
145 
146    private SQLException createSyntaxError(SQLToken token, String errorMsg){
147        StringBuffer msg = getSyntaxError( token ).append(errorMsg);
148        return createSyntaxError( msg, token );
149    }
150    
151 
152    private void checkValidIdentifer(String name, SQLToken token) throws SQLException{
153        if(token.value == SQLTokenizer.ASTERISK) return;
154        if(token.value != SQLTokenizer.VALUE &&
155                   token.value != SQLTokenizer.IDENTIFER &&
156           token.value < 200){
157            throw createSyntaxError( token, "Identifer expected.");
158        }
159        if(name.length() == 0)
160            throw createSyntaxError( token, "Empty Identifer.");
161                if(name.charAt(0) < '@')
162            throw createSyntaxError( token, "Wrong Identifer '" + name + "'.");
163    }
164    
165    
166    final private boolean isKeyword(SQLToken token){
167            if(token == null) return false;
168            switch(token.value){
169                    case SQLTokenizer.SELECT:
170                    case SQLTokenizer.INSERT:
171                    case SQLTokenizer.UPDATE:
172                    case SQLTokenizer.UNION:
173                    case SQLTokenizer.FROM:
174                    case SQLTokenizer.WHERE:
175                    case SQLTokenizer.GROUP:
176                    case SQLTokenizer.HAVING:
177                        case SQLTokenizer.ORDER:
178                    case SQLTokenizer.COMMA:
179                        case SQLTokenizer.SET:
180                            return true;
181            }
182            return false;
183    }
184    
185        /** 
186         * Return the last token that the method nextToken has return
187         */
188        private SQLToken lastToken(){
189                if(tokenIdx > tokens.size()){
190                        return null;
191                }
192                return (SQLToken)tokens.get( tokenIdx-1 );
193        }
194    private void previousToken(){
195        tokenIdx--;
196    }
197 
198    private SQLToken nextToken(){
199        if(tokenIdx >= tokens.size()){
200            tokenIdx++; // erhöht werden, damit previousToken() funktioniert
201            return null;
202        }
203        return (SQLToken)tokens.get( tokenIdx++ );
204    }
205 
206    private SQLToken nextToken( int[] validValues) throws SQLException{
207        SQLToken token = nextToken();
208        if(token == null) throw createSyntaxError( token, validValues);
209        if(validValues == MISSING_EXPRESSION) return token; // eine Expression kann in jedem Token enthalten sein
210        if(validValues == MISSING_IDENTIFER){
211            // folgende Token sind keine gültigen Identifer
212            switch(token.value){
213                case SQLTokenizer.PARENTHESIS_L:
214                case SQLTokenizer.PARENTHESIS_R:
215                case SQLTokenizer.COMMA:
216                    throw createSyntaxError( token, validValues);
217            }
218            return token;
219        }
220        for(int i=validValues.length-1; i>=0; i--){
221            if(token.value == validValues[i]) return token;
222        }
223        throw createSyntaxError( token, validValues);
224    }
225    
226 
227    /**
228     * A single SELECT of a UNION or only a simple single SELECT.
229     * @return
230     * @throws SQLException
231     */
232    private CommandSelect singleSelect() throws SQLException{
233        CommandSelect selCmd = new CommandSelect(con.log);
234                SQLToken token;
235        // scan for prefixe like DISTINCT, ALL and the TOP clause; sample: SELECT TOP 15 ...
236Switch: while(true){
237                        token = nextToken(MISSING_EXPRESSION);
238                        switch(token.value){
239                                case SQLTokenizer.TOP:
240                                        token = nextToken(MISSING_EXPRESSION);
241                                        try{
242                                                int maxRows = Integer.parseInt(token.getName(sql));
243                                                selCmd.setMaxRows(maxRows);
244                                        }catch(Exception e){
245                                                throw createSyntaxError(token, e.getMessage());
246                                        }
247                                        break;
248                                case SQLTokenizer.ALL:
249                                        selCmd.setDistinct(false);
250                                        break;
251                                case SQLTokenizer.DISTINCT:
252                                        selCmd.setDistinct(true);
253                                        break;
254                                default:
255                                        previousToken();
256                                        break Switch;
257                        }
258                }
259 
260        while(true){
261            Expression column = expression(selCmd, 0);
262            selCmd.addColumnExpression( column );
263 
264            token = nextToken();
265            if(token == null) return selCmd; // SELECT ohne FROM
266 
267            boolean as = false;
268            if(token.value == SQLTokenizer.AS){
269                token = nextToken(MISSING_EXPRESSION);
270                as = true;
271            }
272 
273            if(as || (!isKeyword(token))){
274                    String alias = token.getName( sql );
275                    checkValidIdentifer( alias, token);
276                column.setAlias( alias );
277                token = nextToken();
278                if(token == null) return selCmd; // SELECT ohne FROM
279            }
280 
281            switch(token.value){
282                case SQLTokenizer.COMMA:
283                        if(column == null) throw createSyntaxError( token, MISSING_EXPRESSION );
284                        column = null;
285                        break;
286                case SQLTokenizer.FROM:
287                        if(column == null) throw createSyntaxError( token, MISSING_EXPRESSION );
288                        column = null;
289                        from(selCmd);
290                        return selCmd;
291 
292                default:
293                        if(!isKeyword(token))
294                                        throw createSyntaxError( token, new int[]{SQLTokenizer.COMMA, SQLTokenizer.FROM} );
295                        previousToken();
296                        return selCmd;
297            }
298        }
299    }
300    
301    
302    final private CommandSelect select() throws SQLException{
303                CommandSelect selCmd = singleSelect();
304                SQLToken token = nextToken();
305                                   
306            UnionAll union = null; 
307        
308                while(token != null && token.value == SQLTokenizer.UNION){
309                        if(union == null){
310                                union = new UnionAll();
311                                union.addDataSource(new ViewResult( con, selCmd ));
312                                selCmd = new CommandSelect(con.log);
313                                selCmd.setSource( union );
314                                DataSources from = new DataSources();
315                                from.add(union);
316                                selCmd.setFrom( from );
317                                selCmd.addColumnExpression( new ExpressionName("*") );
318                        }
319                        nextToken(MISSING_ALL);
320                        nextToken(MISSING_SELECT);
321                        union.addDataSource( new ViewResult( con, singleSelect() ) );
322                        token = nextToken();
323                }
324                if(token != null && token.value == SQLTokenizer.ORDER){
325                        order( selCmd );
326                }else{
327                        previousToken();
328                }
329                return selCmd;
330    }
331 
332 
333    private Command delete() throws SQLException{
334            CommandDelete cmd = new CommandDelete(con.log);
335            nextToken(MISSING_FROM);
336            from(cmd);
337                SQLToken token = nextToken();
338                if(token != null){
339                        if(token.value != SQLTokenizer.WHERE)
340                                throw this.createSyntaxError(token, MISSING_WHERE);
341                        where(cmd);
342                }
343                return cmd;
344    }
345 
346 
347        private Command truncate() throws SQLException{
348                CommandDelete cmd = new CommandDelete(con.log);
349                nextToken(MISSING_TABLE);
350                from(cmd);
351                return cmd;
352        }
353 
354 
355    private Command insert() throws SQLException{
356        SQLToken token = nextToken( MISSING_INTO );
357        token = nextToken( MISSING_IDENTIFER );
358        CommandInsert cmd = new CommandInsert( con.log, token.getName(sql) );
359 
360                int parthesisCount = 0;
361 
362                token = nextToken(MISSING_PARENTHESIS_VALUES_SELECT);
363        if(token.value == SQLTokenizer.PARENTHESIS_L){
364                token = nextToken(MISSING_EXPRESSION);
365                if(token.value == SQLTokenizer.SELECT){
366                                parthesisCount++;
367                                cmd.noColumns = true;
368                }else{
369                                previousToken();
370                    Expressions list = expressionParenthesisList(cmd);
371                    for(int i=0; i<list.size(); i++){
372                        cmd.addColumnExpression( list.get( i ) );
373                    }
374                    token = nextToken(MISSING_PARENTHESIS_VALUES_SELECT);
375                }
376        }else cmd.noColumns = true;
377        
378Switch: while(true)
379        switch(token.value){
380                case SQLTokenizer.VALUES:{
381                    token = nextToken(MISSING_PARENTHESIS_L);
382                    cmd.addValues( expressionParenthesisList(cmd) );
383                    return cmd;
384                }
385                case SQLTokenizer.SELECT:
386                        cmd.addValues( select() );
387                        while(parthesisCount-- > 0){
388                                nextToken(MISSING_PARENTHESIS_R);
389                        }
390                        return cmd;
391                case SQLTokenizer.PARENTHESIS_L:
392                        token = nextToken(MISSING_PARENTHESIS_VALUES_SELECT);
393                        parthesisCount++;
394                        continue Switch;
395                default:
396                        throw new Error();
397        }
398    }
399 
400 
401    private Command update() throws SQLException{
402                CommandUpdate cmd = new CommandUpdate(con.log);
403                // read table name
404                DataSources tables = new DataSources();
405                cmd.setFrom( tables );
406                cmd.setSource( rowSource( cmd, tables, 0 ) );
407                
408                SQLToken token = nextToken(MISSING_SET);
409                while(true){
410                        token = nextToken();
411                        Expression dest = expressionSingle( cmd, token);
412                        if(dest.getType() != Expression.NAME) throw createSyntaxError( token, MISSING_IDENTIFER );
413                        nextToken(MISSING_EQUALS);
414                        Expression src = expression(cmd, 0);
415                        cmd.addSetting( dest, src);
416                        token = nextToken();
417                        if(token == null) break;
418                        switch(token.value){
419                                case SQLTokenizer.WHERE:
420                                        where(cmd);
421                                        return cmd;                                
422                                case SQLTokenizer.COMMA:
423                                        continue;
424                                default: throw createSyntaxError( token, MISSING_WHERE_COMMA );
425                        }
426                }
427                return cmd;
428    }
429 
430 
431    private Command create() throws SQLException{
432        SQLToken token = nextToken();
433        if(token == null) throw createSyntaxError( token, COMMANDS_CREATE );
434        switch(token.value){
435            case SQLTokenizer.DATABASE:
436                return createDatabase();
437            case SQLTokenizer.TABLE:
438                return createTable();
439            case SQLTokenizer.VIEW:
440                return createView();
441            case SQLTokenizer.INDEX:
442                return createIndex();
443            case SQLTokenizer.PROCEDURE:
444                return createProcedure();
445            default:
446                throw createSyntaxError( token, COMMANDS_CREATE );
447        }
448    }
449        
450 
451    private CommandCreateDatabase createDatabase() throws SQLException{
452        SQLToken token = nextToken();
453        if(token == null) throw createSyntaxError( token, MISSING_EXPRESSION );
454        return new CommandCreateDatabase( con.log, token.getName(sql));
455    }
456        
457 
458    private CommandCreateTable createTable() throws SQLException{
459        SQLToken token = nextToken( MISSING_IDENTIFER ); // table name
460        String tableName = token.getName(sql);
461        CommandCreateTable cmdCreate = new CommandCreateTable( con.log, tableName);
462        token = nextToken( MISSING_PARENTHESIS_L );
463 
464        nextCol:
465        while(true){
466            token = nextToken( MISSING_EXPRESSION );
467                        
468                        String constraintName;
469            if(token.value == SQLTokenizer.CONSTRAINT){
470                    // reading a CONSTRAINT with name
471                                token = nextToken( MISSING_IDENTIFER );
472                            constraintName = token.getName(sql);
473                                checkValidIdentifer( constraintName, token );
474                                
475                                token = nextToken( MISSING_KEYTYPE );
476            }else{
477                                constraintName = null;
478            }
479                        switch(token.value){
480                                case SQLTokenizer.PRIMARY:
481                                case SQLTokenizer.UNIQUE:
482                                case SQLTokenizer.FOREIGN:
483                                        IndexDescription index = index(cmdCreate, token.value, null);
484                                        index.setName(constraintName);
485                    if(token.value == SQLTokenizer.FOREIGN){
486                        nextToken( MISSING_REFERENCES );
487                        token = nextToken( MISSING_IDENTIFER );
488                        String pk = token.getName(sql);
489                        Expressions expressions = new Expressions();
490                        Strings columns = new Strings();
491                        expressionDefList( cmdCreate, expressions, columns );
492                        IndexDescription pkIndex = new IndexDescription( SQLTokenizer.UNIQUE, expressions, columns);
493                        ForeignKey foreignKey = new ForeignKey(pk, pkIndex, tableName, index);
494                        cmdCreate.addForeingnKey(foreignKey);
495                    }else{
496                        cmdCreate.addIndex( index );
497                    }
498        
499                                        token = nextToken( MISSING_COMMA_PARENTHESIS );
500                                        switch(token.value){
501                                                case SQLTokenizer.PARENTHESIS_R:
502                                                        return cmdCreate;
503                                                case SQLTokenizer.COMMA:
504                                                        continue nextCol;
505                                        }
506            }
507            // the token is a column name
508            String colName = token.getName( sql );
509            
510            Column col = datatype(false);
511            col.setName( colName );
512 
513                        token = nextToken(MISSING_OPTIONS_DATATYPE);
514            boolean nullableWasSet = false;
515            boolean defaultWasSet = col.isAutoIncrement(); // with data type COUNTER allready this value is set
516            while(true){
517                switch(token.value){
518                    case SQLTokenizer.PARENTHESIS_R:
519                        cmdCreate.addColumn( col );
520                        return cmdCreate;
521                    case SQLTokenizer.COMMA:
522                        cmdCreate.addColumn( col );
523                        continue nextCol;
524                    case SQLTokenizer.DEFAULT:
525                        if(defaultWasSet) throw createSyntaxError( token, MISSING_COMMA_PARENTHESIS );
526                                                int offset = token.offset + token.length;
527                        token = nextToken();
528                        if(token != null) offset = token.offset;
529                                            previousToken();                    
530                                                Expression expr = expression(cmdCreate, 0);
531                                                SQLToken last = lastToken();
532                                                int length = last.offset + last.length - offset;
533                                                String def = new String( sql, offset, length );
534                        col.setDefaultValue( expr, def );
535                        defaultWasSet = true;
536                        break;
537                    case SQLTokenizer.IDENTITY:
538                        if(defaultWasSet) throw createSyntaxError( token, MISSING_COMMA_PARENTHESIS );
539                        col.setAutoIncrement(true);
540                        defaultWasSet = true;
541                        break;
542                    case SQLTokenizer.NULL:
543                        if(nullableWasSet) throw createSyntaxError( token, MISSING_COMMA_PARENTHESIS );
544                        //col.setNullable(true); ist bereits default
545                        nullableWasSet = true;
546                        break;
547                    case SQLTokenizer.NOT:
548                        if(nullableWasSet) throw createSyntaxError( token, MISSING_COMMA_PARENTHESIS );
549                        token = nextToken( MISSING_NULL );
550                        col.setNullable(false);
551                        nullableWasSet = true;
552                        break;
553                    case SQLTokenizer.PARENTHESIS_L:
554                        throw createSyntaxError(token, MISSING_COMMA_PARENTHESIS);
555                                        case SQLTokenizer.PRIMARY:
556                                        case SQLTokenizer.UNIQUE:
557                                                IndexDescription index = index(cmdCreate, token.value, colName);
558                                                cmdCreate.addIndex( index );
559                                                break;
560                    default:
561                        throw new Error();
562                }
563                token = nextToken( MISSING_OPTIONS_DATATYPE );
564            }
565        }
566    }
567        
568        /**
569         * Parse construct like:<br>
570         * <li>PRIMARY KEY (col1)
571         * <li>UNIQUE (col1, col2)
572         * <li>FOREIGN KEY REFERENCES ref_table(col1)
573         * @param cmd
574         * @param constraintType one of SQLTokenizer.PRIMARY, SQLTokenizer.UNIQUE or SQLTokenizer.FOREIGN.
575         * @param if it a constrain of the current column else null
576         * @return a new IndexDescription
577         */
578        private IndexDescription index(Command cmd, int constraintType, String columnName) throws SQLException{
579                if(constraintType != SQLTokenizer.UNIQUE) nextToken( MISSING_KEY );
580                SQLToken token = nextToken( MISSING_EXPRESSION );
581                switch(token.value){
582                        case SQLTokenizer.CLUSTERED:
583                        case SQLTokenizer.NONCLUSTERED:
584                                // skipping, this tokens form MS SQL Server are ignored
585                                token = nextToken( MISSING_EXPRESSION );
586                                break;
587                }
588                Strings columns = new Strings();
589                Expressions expressions = new Expressions();
590                if(columnName != null){
591                        //Constraint for a single column together with the column defination
592                        columns.add(columnName);
593                        expressions.add(new ExpressionName(columnName));
594                        previousToken();
595                }else{
596                        //Constraint as addition defination
597            previousToken();
598            expressionDefList( cmd, expressions, columns );
599                }
600 
601                return new IndexDescription( constraintType, expressions, columns);
602        }
603 
604 
605    /**
606     * Read a DataTpe description. This is used for CREATE TABLE and CONVERT function. 
607     * @param isEscape true then the datatypes start with SQL_
608     */
609    private Column datatype(boolean isEscape) throws SQLException{
610                SQLToken token;
611                int dataType;
612                if(isEscape){
613                        token = nextToken( MISSING_SQL_DATATYPE );
614                        switch(token.value){
615                                case SQLTokenizer.SQL_BIGINT:                         dataType = SQLTokenizer.BIGINT;                break;
616                                case SQLTokenizer.SQL_BINARY:                        dataType = SQLTokenizer.BINARY;         break;
617                                case SQLTokenizer.SQL_BIT:                                dataType = SQLTokenizer.BIT;                break;
618                                case SQLTokenizer.SQL_CHAR:                                dataType = SQLTokenizer.CHAR;                break;
619                                case SQLTokenizer.SQL_DATE:                                dataType = SQLTokenizer.DATE;                break;
620                                case SQLTokenizer.SQL_DECIMAL:                        dataType = SQLTokenizer.DECIMAL;        break;
621                                case SQLTokenizer.SQL_DOUBLE:                        dataType = SQLTokenizer.DOUBLE;                break;
622                                case SQLTokenizer.SQL_FLOAT:                        dataType = SQLTokenizer.FLOAT;                break;
623                                case SQLTokenizer.SQL_INTEGER:                        dataType = SQLTokenizer.INT;                break;
624                                case SQLTokenizer.SQL_LONGVARBINARY:        dataType = SQLTokenizer.LONGVARBINARY;break;
625                                case SQLTokenizer.SQL_LONGVARCHAR:                dataType = SQLTokenizer.LONGVARCHAR;break;
626                                case SQLTokenizer.SQL_REAL:                                dataType = SQLTokenizer.REAL;                break;
627                                case SQLTokenizer.SQL_SMALLINT:                        dataType = SQLTokenizer.SMALLINT;        break;
628                                case SQLTokenizer.SQL_TIME:                                dataType = SQLTokenizer.TIME;                break;
629                                case SQLTokenizer.SQL_TIMESTAMP:                dataType = SQLTokenizer.TIMESTAMP;        break;
630                                case SQLTokenizer.SQL_TINYINT:                        dataType = SQLTokenizer.TINYINT;        break;
631                                case SQLTokenizer.SQL_VARBINARY:                dataType = SQLTokenizer.VARBINARY;        break;
632                                case SQLTokenizer.SQL_VARCHAR:                        dataType = SQLTokenizer.VARCHAR;        break;
633                                default: throw new Error();
634                        }
635                }else{
636                        token = nextToken( MISSING_DATATYPE );
637                        dataType = token.value;
638                }
639                Column col = new Column();
640 
641                // zweiteiliger Datentyp
642                if(dataType == SQLTokenizer.LONG){
643                        token = nextToken();
644                        if(token != null && token.value == SQLTokenizer.RAW){
645                                dataType = SQLTokenizer.LONGVARBINARY;
646                        }else{
647                                dataType = SQLTokenizer.LONGVARCHAR;
648                                previousToken();
649                        }
650                }
651 
652                token = nextToken( MISSING_OPTIONS_DATATYPE );
653                switch(dataType){
654                        case SQLTokenizer.RAW:
655                                dataType = SQLTokenizer.VARBINARY;
656                                // no break;
657                        case SQLTokenizer.CHAR:
658                        case SQLTokenizer.VARCHAR:
659                        case SQLTokenizer.NCHAR:
660                        case SQLTokenizer.NVARCHAR:
661                        case SQLTokenizer.BINARY:
662                        case SQLTokenizer.VARBINARY:
663                        {
664                                // maximale Spaltengröße ermitteln
665                                int displaySize;
666                                if(token.value != SQLTokenizer.PARENTHESIS_L){
667                                        displaySize = 30;
668                                }else{
669                                        token = nextToken( MISSING_EXPRESSION );
670                                        try{
671                                                displaySize = Integer.parseInt(token.getName(sql) );
672                                        }catch(Exception e){
673                                                throw createSyntaxError(token, MISSING_NUMBERVALUE );
674                                        }
675                                        nextToken( MISSING_PARENTHESIS_R );
676                                        token = nextToken(MISSING_OPTIONS_DATATYPE);
677                                }
678                                col.setPrecision( displaySize );
679                                break;
680                        }
681                        case SQLTokenizer.SYSNAME:
682                                col.setPrecision(255);
683                                dataType = SQLTokenizer.VARCHAR;
684                                break;
685                        case SQLTokenizer.COUNTER:
686                                col.setAutoIncrement(true);
687                                dataType = SQLTokenizer.INT;
688                                break;
689                        case SQLTokenizer.NUMERIC:
690                        case SQLTokenizer.DECIMAL:
691                                if(token.value == SQLTokenizer.PARENTHESIS_L){
692                                        // read the precision of the data type
693                                        token = nextToken( MISSING_EXPRESSION );
694                                        int value;
695                                        try{
696                                                value = Integer.parseInt(token.getName(sql) );
697                                        }catch(Exception e){
698                                                throw createSyntaxError(token, MISSING_NUMBERVALUE );
699                                        }
700                                        col.setPrecision(value);
701                                        token = nextToken( MISSING_COMMA_PARENTHESIS );
702                                        if(token.value == SQLTokenizer.COMMA){
703                                                // read the scale of the data type
704                                                token = nextToken( MISSING_EXPRESSION );
705                                                try{
706                                                        value = Integer.parseInt(token.getName(sql) );
707                                                }catch(Exception e){
708                                                        throw createSyntaxError(token, MISSING_NUMBERVALUE );
709                                                }
710                                                col.setScale(value);
711                                                nextToken( MISSING_PARENTHESIS_R );
712                                        }
713                                        token = nextToken(MISSING_OPTIONS_DATATYPE);
714                                }else{
715                                        col.setPrecision(18); //default Precision for decimal and numeric
716                                }
717                                break;
718                }
719                col.setDataType( dataType );
720                this.previousToken();
721                return col;
722    }
723    
724    private CommandCreateView createView() throws SQLException{
725            SQLToken token = nextToken(MISSING_IDENTIFER );
726            String viewName = token.getName(sql);
727                checkValidIdentifer( viewName, token );
728 
729                nextToken(MISSING_AS);
730                token = nextToken(MISSING_SELECT);
731                CommandCreateView cmd = new CommandCreateView( con.log, viewName );
732                
733                cmd.sql = new String(sql, token.offset, sql.length-token.offset );
734                select(); //Parse to check for valid
735        return cmd;
736    }
737 
738 
739    private CommandCreateDatabase createIndex() throws SQLException{
740        throw new java.lang.UnsupportedOperationException();
741    }
742 
743    private CommandCreateDatabase createProcedure() throws SQLException{
744        throw new java.lang.UnsupportedOperationException();
745    }
746 
747    private Command drop() throws SQLException{
748        SQLToken tokenType = nextToken(COMMANDS_CREATE);
749        
750                SQLToken token = nextToken( MISSING_EXPRESSION );
751                String catalog = null;
752                String name = token.getName( sql );
753                checkValidIdentifer( name, token );
754                token = nextToken();
755                //check if the object name include a database name
756                if(token != null && token.value == SQLTokenizer.POINT){
757                        token = nextToken(MISSING_EXPRESSION);
758                        catalog = name;
759                        name = token.getName( sql );
760                        checkValidIdentifer( name, token );
761                        token = nextToken();
762                }
763                previousToken();
764 
765        switch(tokenType.value){
766            case SQLTokenizer.DATABASE:
767            case SQLTokenizer.TABLE:
768            case SQLTokenizer.VIEW:
769            case SQLTokenizer.INDEX:
770            case SQLTokenizer.PROCEDURE:
771                    return new CommandDrop( con.log, catalog, name, tokenType.value);
772            default:
773                throw createSyntaxError( tokenType, COMMANDS_CREATE );
774        }
775    }
776 
777 
778    private Command alter() throws SQLException{
779        throw new java.lang.UnsupportedOperationException();
780    }
781    
782 
783    private CommandSet set() throws SQLException{
784        SQLToken token = nextToken( COMMANDS_SET );
785        switch(token.value){
786            case SQLTokenizer.TRANSACTION:
787                return setTransaction();
788            default:
789                throw new Error();
790        }
791    }
792 
793    private CommandSet setTransaction() throws SQLException{
794        SQLToken token = nextToken( MISSING_ISOLATION );
795        token = nextToken( MISSING_LEVEL );
796        token = nextToken( COMMANDS_TRANS_LEVEL );
797        CommandSet cmd = new CommandSet( con.log, SQLTokenizer.LEVEL );
798        switch(token.value){
799            case SQLTokenizer.READ:
800                token = nextToken( MISSING_COMM_UNCOMM );
801                switch(token.value){
802                    case SQLTokenizer.COMMITTED:
803                        cmd.isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
804                        break;
805                    case SQLTokenizer.UNCOMMITTED:
806                        cmd.isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
807                        break;
808                    default:
809                        throw new Error();
810                }
811                return cmd;
812            case SQLTokenizer.REPEATABLE:
813                token = nextToken( MISSING_READ );
814                cmd.isolationLevel = Connection.TRANSACTION_REPEATABLE_READ;
815                return cmd;
816            case SQLTokenizer.SERIALIZABLE:
817                cmd.isolationLevel = Connection.TRANSACTION_SERIALIZABLE;
818                return cmd;
819            default:
820                throw new Error();
821        }
822 
823 
824    }
825 
826    private Command execute() throws SQLException{
827        throw new java.lang.UnsupportedOperationException();
828    }
829 
830    /**
831     * Read a Expression list in parenthesis like of VALUES() or functions. 
832     * The left parenthesis is already consumed.
833     * 
834     * @param cmd is needed to add parameters "?" with addParameter() 
835     * @see #expressionDefList
836     */ 
837    private Expressions expressionParenthesisList(Command cmd) throws SQLException{
838                Expressions list = new Expressions();
839                {
840                        SQLToken token = nextToken();
841                        if(token != null && token.value == SQLTokenizer.PARENTHESIS_R){
842                                // empty list like functions without params
843                                return list;
844                        }
845                        previousToken();
846                }
847        while(true){
848            list.add( expression(cmd, 0) );
849            SQLToken token = nextToken(MISSING_COMMA_PARENTHESIS);
850            switch(token.value){
851                case SQLTokenizer.PARENTHESIS_R:
852                    return list;
853                case SQLTokenizer.COMMA:
854                    continue;
855                default:
856                    throw new Error();
857            }
858        }
859    }
860 
861    
862    /**
863     * Read a list of expressions. The list is limit from specific SQL keywords like SELECT, GROUP BY, ORDER BY
864     */
865    private Expressions expressionTokenList(Command cmd, int listType) throws SQLException{
866                Expressions list = new Expressions();
867        while(true){
868                Expression expr = expression(cmd, 0);
869            list.add( expr );
870            SQLToken token = nextToken();
871            
872                        if(listType == SQLTokenizer.ORDER && token != null){
873                                switch(token.value){
874                                        case SQLTokenizer.DESC:
875                                                expr.setAlias(SQLTokenizer.DESC_STR);
876                                                //kein break;
877                                        case SQLTokenizer.ASC:
878                                                token = nextToken();
879                                }                                
880                        }
881                        
882                        if(token == null) {
883                                previousToken();
884                                return list;
885                        }
886 
887                        switch(token.value){
888                case SQLTokenizer.COMMA:
889                    continue;
890                default:
891                                        if(isKeyword(token) ){
892                                                previousToken();
893                                                return list;
894                                        }
895                    throw createSyntaxError( token, MISSING_TOKEN_LIST);
896            }
897        }
898    }
899    
900    
901    private void expressionDefList(Command cmd, Expressions expressions, Strings columns) throws SQLException{
902        SQLToken token = nextToken();
903        if(token.value != SQLTokenizer.PARENTHESIS_L) throw createSyntaxError(token, MISSING_PARENTHESIS_L );
904        Loop:
905        while(true){
906            int offset = token.offset + token.length;
907            token = nextToken();
908            if(token != null) offset = token.offset;
909            previousToken();  
910            
911            expressions.add( expression(cmd, 0) );
912            SQLToken last = lastToken();
913            int length = last.offset + last.length - offset;
914            columns.add( new String( sql, offset, length ) );
915 
916            token = nextToken(MISSING_COMMA_PARENTHESIS);
917            switch(token.value){
918                case SQLTokenizer.PARENTHESIS_R:
919                    break Loop;
920                case SQLTokenizer.COMMA:
921                    continue;
922                default:
923                    throw new Error();
924            }
925        }
926    }
927    
928 
929        /**
930         * Read a complex expression that can be build from multiple atomic expressions.
931     * @param cmd is needed to add parameters "?" with addParameter() 
932         * @param previousOperationLevel the level of the left operation.
933         */
934    private Expression expression(Command cmd, int previousOperationLevel) throws SQLException{
935        SQLToken token = nextToken();
936        if(token == null) return null;
937        Expression leftExpr;
938        switch(token.value){
939            case SQLTokenizer.NOT:
940                    leftExpr =  new ExpressionArithmetic( expression( cmd, ExpressionArithmetic.NOT      / 10), ExpressionArithmetic.NOT);
941                    break;
942            case SQLTokenizer.MINUS:
943                    leftExpr =  new ExpressionArithmetic( expression( cmd, ExpressionArithmetic.NEGATIVE / 10), ExpressionArithmetic.NEGATIVE);
944                    break;
945            case SQLTokenizer.TILDE:
946                    leftExpr =  new ExpressionArithmetic( expression( cmd, ExpressionArithmetic.BIT_NOT  / 10), ExpressionArithmetic.BIT_NOT);
947                    break;
948            case SQLTokenizer.PARENTHESIS_L:
949                leftExpr = expression( cmd, 0);
950                token = nextToken(MISSING_PARENTHESIS_R);
951                break;
952            default:
953                leftExpr = expressionSingle( cmd, token);
954        }
955        boolean isNot = false;
956        while((token = nextToken()) != null){
957            Expression rightExpr;
958            int operation = ExpressionArithmetic.getOperationFromToken(token.value);
959            int level = operation / 10;
960            if(previousOperationLevel >= level){
961                previousToken();
962                return leftExpr;
963            }
964            switch(token.value){
965                case SQLTokenizer.PLUS:
966                case SQLTokenizer.MINUS:
967                case SQLTokenizer.ASTERISK:
968                case SQLTokenizer.SLACH:
969                case SQLTokenizer.PERCENT:
970                case SQLTokenizer.EQUALS:
971                case SQLTokenizer.LESSER:
972                case SQLTokenizer.LESSER_EQU:
973                case SQLTokenizer.GREATER:
974                case SQLTokenizer.GREATER_EQU:
975                case SQLTokenizer.UNEQUALS:
976                case SQLTokenizer.LIKE:
977                case SQLTokenizer.OR:
978                case SQLTokenizer.AND:
979                case SQLTokenizer.BIT_AND:
980                case SQLTokenizer.BIT_OR:
981                case SQLTokenizer.BIT_XOR:
982                    rightExpr = expression( cmd, level );
983                    leftExpr = new ExpressionArithmetic( leftExpr, rightExpr, operation );
984                    break;
985                case SQLTokenizer.BETWEEN:
986                    rightExpr = expression( cmd, ExpressionArithmetic.AND );
987                    nextToken( MISSING_AND );
988                    Expression rightExpr2 = expression( cmd, level );
989                    leftExpr = new ExpressionArithmetic( leftExpr, rightExpr, rightExpr2, operation );
990                    break;
991                case SQLTokenizer.IN:
992                            nextToken(MISSING_PARENTHESIS_L);
993                        token = nextToken(MISSING_EXPRESSION);
994                        if(token.value == SQLTokenizer.SELECT){
995                                CommandSelect cmdSel = select();
996                                                leftExpr = new ExpressionInSelect( con, leftExpr, cmdSel, operation );
997                                                nextToken(MISSING_PARENTHESIS_R);
998                        }else{
999                                previousToken();
1000                                Expressions list = expressionParenthesisList( cmd );
1001                                leftExpr = new ExpressionArithmetic( leftExpr, list, operation );
1002                        }
1003                    break;
1004                case SQLTokenizer.IS:
1005                        token = nextToken(MISSING_NOT_NULL);
1006                        if(token.value == SQLTokenizer.NOT){
1007                                nextToken(MISSING_NULL);
1008                                                operation++;
1009                        }
1010                        leftExpr = new ExpressionArithmetic( leftExpr, operation );
1011                        break;
1012                case SQLTokenizer.NOT:
1013                        token = nextToken(MISSING_BETWEEN_IN);
1014                        previousToken();
1015                        isNot = true;
1016                        continue;
1017                default:
1018                        previousToken();
1019                        return leftExpr;
1020            }
1021            if(isNot){
1022                    isNot = false;
1023                                leftExpr =  new ExpressionArithmetic( leftExpr, ExpressionArithmetic.NOT);
1024            }
1025        }
1026        previousToken();
1027        return leftExpr;
1028    }
1029 
1030    /**
1031     * parst einen einzelne Expression, wie 12, 'qwert', 0x3F oder column name
1032     * 
1033     * @param cmd is needed to add parameters "?" with addParameter() 
1034     */
1035    private Expression expressionSingle(Command cmd, SQLToken token) throws SQLException{
1036        boolean isMinus = false;
1037        if(token != null){
1038            switch(token.value){
1039                case SQLTokenizer.NULL:
1040                        return new ExpressionValue( null, SQLTokenizer.NULL );
1041                case SQLTokenizer.STRING:
1042                        return new ExpressionValue( token.getName(null), SQLTokenizer.VARCHAR );
1043                case SQLTokenizer.IDENTIFER:
1044                        {
1045                        String name = token.getName(null);
1046                        checkValidIdentifer( name, token );
1047                        ExpressionName expr =  new ExpressionName( name );
1048                        SQLToken token2 = nextToken();
1049                        if(token2 != null && token2.value == SQLTokenizer.POINT){
1050                            token = nextToken(MISSING_EXPRESSION);
1051                            expr.setNameAfterTableAlias( token.getName( sql ) );
1052                        }else{
1053                            previousToken();
1054                        }
1055                        return expr;
1056                        }
1057                case SQLTokenizer.TRUE:
1058                        return new ExpressionValue( Boolean.TRUE, SQLTokenizer.BOOLEAN );
1059                case SQLTokenizer.FALSE:
1060                        return new ExpressionValue( Boolean.FALSE, SQLTokenizer.BOOLEAN );
1061                case SQLTokenizer.ESCAPE_L:{
1062                        token = nextToken(COMMANDS_ESCAPE);
1063                        SQLToken para = nextToken(MISSING_EXPRESSION);
1064                        Expression expr;
1065                        switch(token.value){
1066                            case SQLTokenizer.D: // date escape sequence
1067                                    expr = new ExpressionValue( DateTime.valueOf(para.getName(sql), SQLTokenizer.DATE), SQLTokenizer.DATE );
1068                                    break;
1069                            case SQLTokenizer.T: // time escape sequnce
1070                                expr = new ExpressionValue( DateTime.valueOf(para.getName(sql), SQLTokenizer.TIME), SQLTokenizer.TIME );
1071                                    break;
1072                            case SQLTokenizer.TS: // timestamp escape sequence
1073                                expr = new ExpressionValue( DateTime.valueOf(para.getName(sql), SQLTokenizer.TIMESTAMP), SQLTokenizer.TIMESTAMP );
1074                                    break;
1075                            case SQLTokenizer.FN: // function escape sequence
1076                                    nextToken(MISSING_PARENTHESIS_L);
1077                                    expr = function(cmd, para, true);
1078                                    break;
1079                            case SQLTokenizer.CALL: // call escape sequence
1080                                throw new java.lang.UnsupportedOperationException("call escape sequence");
1081                            default: throw new Error();
1082                        }
1083                        token = nextToken( ESCAPE_MISSING_CLOSE );
1084                        return expr;
1085                }
1086                case SQLTokenizer.QUESTION:
1087                        ExpressionValue param = new ExpressionValue();
1088                        cmd.addParameter( param );
1089                        return param;
1090                case SQLTokenizer.CASE:
1091                                return caseExpr(cmd);
1092                case SQLTokenizer.MINUS:
1093                case SQLTokenizer.PLUS:
1094                        // Vorzeichenerkennung
1095                        do{
1096                            if(token.value == SQLTokenizer.MINUS)
1097                                    isMinus = !isMinus;
1098                            token = nextToken();
1099                            if(token == null) throw createSyntaxError( token, MISSING_EXPRESSION );
1100                        }while(token.value == SQLTokenizer.MINUS || token.value == SQLTokenizer.PLUS);
1101                        // kein Break
1102                default:
1103                        SQLToken token2 = nextToken();
1104                        if(token2 != null && token2.value == SQLTokenizer.PARENTHESIS_L){
1105                            if(isMinus)
1106                                return new ExpressionArithmetic( function( cmd, token, false ),  ExpressionArithmetic.NEGATIVE );
1107                            return function( cmd, token, false );
1108                        }else{
1109                            // Konstanter Ausdruck oder Identifer
1110                            char chr1 = sql[ token.offset ];
1111                                                        if(chr1 == '$'){
1112                                                                previousToken();
1113                                    String tok = new String(sql, token.offset+1, token.length-1);
1114                                if(isMinus) tok = "-" + tok;
1115                                                                return new ExpressionValue( new Money(Double.parseDouble(tok)), SQLTokenizer.MONEY );
1116                                                        }
1117                            String tok = new String(sql, token.offset, token.length);
1118                            if((chr1 >= '0' && '9' >= chr1) || chr1 == '.'){
1119                                previousToken();
1120                                //erstes Zeichen ein digit
1121                                if(token.length>1 && (sql[ token.offset +1 ] | 0x20) == 'x'){
1122                                    // binär Daten als Hex
1123                                    if(isMinus) throw createSyntaxError( token, "Invalid operator binary for data type varbinary.");
1124                                    return new ExpressionValue( Utils.hex2bytes( sql, token.offset+2, token.length-2), SQLTokenizer.BINARY );
1125                                }
1126                                if(isMinus) tok = "-" + tok;
1127                                if(Utils.indexOf( '.', sql, token.offset, token.length ) >= 0 ||
1128                                   Utils.indexOf( 'e', sql, token.offset, token.length ) >= 0){
1129                                    return new ExpressionValue( new Double(tok), SQLTokenizer.DOUBLE );
1130                                }else{
1131                                    try{
1132                                        return new ExpressionValue( new Integer(tok), SQLTokenizer.INT );
1133                                    }catch(NumberFormatException e){
1134                                        return new ExpressionValue( new Long(tok), SQLTokenizer.BIGINT );
1135                                    }
1136                                }
1137                            }else{
1138                                // Bezeichner
1139                                checkValidIdentifer( tok, token );
1140                                ExpressionName expr = new ExpressionName(tok);
1141                                if(token2 != null && token2.value == SQLTokenizer.POINT){
1142                                    token = nextToken(MISSING_EXPRESSION);
1143                                    expr.setNameAfterTableAlias( token.getName( sql ) );
1144                                }else{
1145                                    previousToken();
1146                                }
1147                                if(isMinus)
1148                                    return new ExpressionArithmetic( expr,  ExpressionArithmetic.NEGATIVE );
1149                                return expr;
1150                            }
1151                        }
1152            }
1153        }
1154        return null;
1155    }
1156    
1157    
1158    ExpressionFunctionCase caseExpr(final Command cmd) throws SQLException{
1159                ExpressionFunctionCase expr = new ExpressionFunctionCase();
1160                SQLToken token = nextToken(MISSING_EXPRESSION);
1161                
1162                Expression input = null;
1163                if(token.value != SQLTokenizer.WHEN){
1164                        // simple CASE Syntax
1165                        previousToken();
1166                        input = expression(cmd, 0);
1167                        token = nextToken(MISSING_WHEN_ELSE_END);
1168                }                        
1169                        
1170                while(true){
1171                        switch(token.value){
1172                                case SQLTokenizer.WHEN:                                
1173                                        Expression condition = expression(cmd, 0);
1174                                        if(input != null){
1175                                                // simple CASE Syntax
1176                                                condition = new ExpressionArithmetic( input, condition, ExpressionArithmetic.EQUALS);
1177                                        }
1178                                        nextToken(MISSING_THEN);
1179                                        Expression result = expression(cmd, 0);
1180                                        expr.addCase(condition, result);
1181                                        break;
1182                                case SQLTokenizer.ELSE:
1183                                        expr.setElseResult(expression(cmd, 0));
1184                                        break;
1185                                case SQLTokenizer.END:
1186                                        expr.setEnd();
1187                                        return expr;
1188                                default:
1189                                        throw new Error();
1190                        }
1191                        token = nextToken(MISSING_WHEN_ELSE_END);
1192                }
1193    }
1194    
1195 
1196    /**
1197     * Parse any functions. The left parenthesis is allready consumed from token list.
1198     * @param token the SQLToken of the function
1199     * @param isEscape If the function is a FN ESCAPE sequence
1200     */ 
1201    private Expression function( Command cmd, SQLToken token, boolean isEscape ) throws SQLException{
1202        Expression expr;
1203        switch(token.value){
1204                case SQLTokenizer.CONVERT:{
1205                        Column col;
1206                        Expression style = null;
1207                        if(isEscape){
1208                                expr = expression( cmd, 0);
1209                                        nextToken(MISSING_COMMA);
1210                                        col = datatype(isEscape);
1211                        }else{
1212                                col = datatype(isEscape);
1213                                nextToken(MISSING_COMMA);
1214                                        expr = expression( cmd, 0);
1215                                        token = nextToken(MISSING_COMMA_PARENTHESIS);
1216                                        if(token.value == SQLTokenizer.COMMA){
1217                                                style = expression( cmd, 0);;
1218                                        }else
1219                                                previousToken();
1220                        }
1221                        nextToken(MISSING_PARENTHESIS_R);
1222                        return new ExpressionFunctionConvert( col, expr, style );
1223                }
1224                case SQLTokenizer.CAST:
1225                        expr = expression( cmd, 0);
1226                        nextToken(MISSING_AS);
1227                        Column col = datatype(false);
1228                        nextToken(MISSING_PARENTHESIS_R);
1229                        return new ExpressionFunctionConvert( col, expr, null );
1230                        case SQLTokenizer.TIMESTAMPDIFF:
1231                                token = nextToken(MISSING_INTERVALS);
1232                                nextToken(MISSING_COMMA);
1233                                expr = expression( cmd, 0);
1234                                nextToken(MISSING_COMMA);
1235                                expr = new ExpressionFunctionTimestampDiff( token.value, expr, expression( cmd, 0));
1236                                nextToken(MISSING_PARENTHESIS_R);
1237                                return expr;
1238                        case SQLTokenizer.TIMESTAMPADD:
1239                                token = nextToken(MISSING_INTERVALS);
1240                                nextToken(MISSING_COMMA);
1241                                expr = expression( cmd, 0);
1242                                nextToken(MISSING_COMMA);
1243                                expr = new ExpressionFunctionTimestampAdd( token.value, expr, expression( cmd, 0));
1244                                nextToken(MISSING_PARENTHESIS_R);
1245                                return expr;
1246        }
1247                Expressions paramList = expressionParenthesisList(cmd);
1248        int paramCount = paramList.size();
1249        Expression[] params = paramList.toArray();
1250        boolean invalidParamCount;
1251        switch(token.value){
1252        // numeric functions:
1253            case SQLTokenizer.ABS:
1254                invalidParamCount = (paramCount != 1);
1255                expr = new ExpressionFunctionAbs();
1256                break;
1257            case SQLTokenizer.ACOS:
1258                invalidParamCount = (paramCount != 1);
1259                expr = new ExpressionFunctionACos();
1260                break;
1261            case SQLTokenizer.ASIN:
1262                invalidParamCount = (paramCount != 1);
1263                expr = new ExpressionFunctionASin();
1264                break;
1265            case SQLTokenizer.ATAN:
1266                invalidParamCount = (paramCount != 1);
1267                expr = new ExpressionFunctionATan();
1268                break;
1269            case SQLTokenizer.ATAN2:
1270                invalidParamCount = (paramCount != 2);
1271                expr = new ExpressionFunctionATan2();
1272                break;
1273            case SQLTokenizer.CEILING:
1274                invalidParamCount = (paramCount != 1);
1275                expr = new ExpressionFunctionCeiling();
1276                break;
1277            case SQLTokenizer.COS:
1278                invalidParamCount = (paramCount != 1);
1279                expr = new ExpressionFunctionCos();
1280                break;
1281            case SQLTokenizer.COT:
1282                invalidParamCount = (paramCount != 1);
1283                expr = new ExpressionFunctionCot();
1284                break;
1285            case SQLTokenizer.DEGREES:
1286                invalidParamCount = (paramCount != 1);
1287                expr = new ExpressionFunctionDegrees();
1288                break;
1289            case SQLTokenizer.EXP:
1290                invalidParamCount = (paramCount != 1);
1291                expr = new ExpressionFunctionExp();
1292                break;
1293            case SQLTokenizer.FLOOR:
1294                invalidParamCount = (paramCount != 1);
1295                expr = new ExpressionFunctionFloor();
1296                break;
1297            case SQLTokenizer.LOG:
1298                invalidParamCount = (paramCount != 1);
1299                expr = new ExpressionFunctionLog();
1300                break;
1301            case SQLTokenizer.LOG10:
1302                invalidParamCount = (paramCount != 1);
1303                expr = new ExpressionFunctionLog10();
1304                break;
1305            case SQLTokenizer.MOD:
1306                invalidParamCount = (paramCount != 2);
1307                expr = new ExpressionFunctionMod();
1308                break;
1309            case SQLTokenizer.PI:
1310                invalidParamCount = (paramCount != 0);
1311                expr = new ExpressionFunctionPI();
1312                break;
1313            case SQLTokenizer.POWER:
1314                invalidParamCount = (paramCount != 2);
1315                expr = new ExpressionFunctionPower();
1316                break;
1317            case SQLTokenizer.RADIANS:
1318                invalidParamCount = (paramCount != 1);
1319                expr = new ExpressionFunctionRadians();
1320                break;
1321            case SQLTokenizer.RAND:
1322                invalidParamCount =  (paramCount != 0) && (paramCount != 1);
1323                expr = new ExpressionFunctionRand();
1324                break;
1325            case SQLTokenizer.ROUND:
1326                invalidParamCount =  (paramCount != 2);
1327                expr = new ExpressionFunctionRound();
1328                break;
1329            case SQLTokenizer.SIN:
1330                invalidParamCount = (paramCount != 1);
1331                expr = new ExpressionFunctionSin();
1332                break;
1333            case SQLTokenizer.SIGN:
1334                invalidParamCount = (paramCount != 1);
1335                expr = new ExpressionFunctionSign();
1336                break;
1337            case SQLTokenizer.SQRT:
1338                invalidParamCount = (paramCount != 1);
1339                expr = new ExpressionFunctionSqrt();
1340                break;
1341            case SQLTokenizer.TAN:
1342                invalidParamCount = (paramCount != 1);
1343                expr = new ExpressionFunctionTan();
1344                break;
1345            case SQLTokenizer.TRUNCATE:
1346                invalidParamCount =  (paramCount != 2);
1347                expr = new ExpressionFunctionTruncate();
1348                break;
1349         
1350        // string functions:
1351                        case SQLTokenizer.ASCII:
1352                                invalidParamCount = (paramCount != 1);
1353                                expr = new ExpressionFunctionAscii();
1354                                break;
1355                        case SQLTokenizer.CHAR:
1356                                invalidParamCount = (paramCount != 1);
1357                                expr = new ExpressionFunctionChar();
1358                                break;
1359            case SQLTokenizer.CONCAT:
1360                if(paramCount != 2){
1361                    invalidParamCount = true;
1362                    expr = null;//only for compiler
1363                    break;
1364                }
1365                invalidParamCount = false;
1366                expr = new ExpressionArithmetic( params[0], params[1], ExpressionArithmetic.ADD);
1367                break;
1368            case SQLTokenizer.DIFFERENCE:
1369                invalidParamCount = (paramCount != 2);
1370                expr = new ExpressionFunctionDifference();
1371                break;
1372            case SQLTokenizer.INSERT:
1373                invalidParamCount = (paramCount != 4);
1374                expr = new ExpressionFunctionInsert();
1375                break;
1376            case SQLTokenizer.LCASE:
1377                invalidParamCount = (paramCount != 1);
1378                expr = new ExpressionFunctionLCase();
1379                break;
1380            case SQLTokenizer.LEFT:
1381                invalidParamCount = (paramCount != 2);
1382                expr = new ExpressionFunctionLeft();
1383                break;
1384                        case SQLTokenizer.LENGTH:
1385                                invalidParamCount = (paramCount != 1);
1386                                expr = new ExpressionFunctionLength();
1387                                break;
1388            case SQLTokenizer.LOCATE:
1389                    invalidParamCount = (paramCount != 2) && (paramCount != 3);
1390                    expr = new ExpressionFunctionLocate();
1391                    break;
1392            case SQLTokenizer.LTRIM:
1393                invalidParamCount = (paramCount != 1);
1394                expr = new ExpressionFunctionLTrim();
1395                break;
1396            case SQLTokenizer.REPEAT:
1397                invalidParamCount = (paramCount != 2);
1398                expr = new ExpressionFunctionRepeat();
1399                break;
1400            case SQLTokenizer.REPLACE:
1401                invalidParamCount = (paramCount != 3);
1402                expr = new ExpressionFunctionReplace();
1403                break;
1404                        case SQLTokenizer.RIGHT:
1405                                invalidParamCount = (paramCount != 2);
1406                                expr = new ExpressionFunctionRight();
1407                                break;
1408            case SQLTokenizer.RTRIM:
1409                invalidParamCount = (paramCount != 1);
1410                expr = new ExpressionFunctionRTrim();
1411                break;
1412            case SQLTokenizer.SPACE:
1413                invalidParamCount = (paramCount != 1);
1414                expr = new ExpressionFunctionSpace();
1415                break;
1416            case SQLTokenizer.SOUNDEX:
1417                invalidParamCount = (paramCount != 1);
1418                expr = new ExpressionFunctionSoundex();
1419                break;
1420                        case SQLTokenizer.SUBSTRING:
1421                                invalidParamCount = (paramCount != 3);
1422                                expr = new ExpressionFunctionSubstring();
1423                                break;
1424            case SQLTokenizer.UCASE:
1425                invalidParamCount = (paramCount != 1);
1426                expr = new ExpressionFunctionUCase();
1427                break;
1428                
1429        // date time functions
1430            case SQLTokenizer.CURDATE:
1431                    invalidParamCount = (paramCount != 0);
1432                                expr = new ExpressionValue( new DateTime(DateTime.now(), SQLTokenizer.DATE), SQLTokenizer.DATE);
1433                                break;
1434            case SQLTokenizer.CURTIME:
1435                    invalidParamCount = (paramCount != 0);
1436                                expr = new ExpressionValue( new DateTime(DateTime.now(), SQLTokenizer.TIME), SQLTokenizer.TIME);
1437                                break;
1438            case SQLTokenizer.DAYOFMONTH:
1439                    invalidParamCount = (paramCount != 1);
1440                                expr = new ExpressionFunctionDayOfMonth();
1441                                break;
1442            case SQLTokenizer.DAYOFWEEK:
1443                    invalidParamCount = (paramCount != 1);
1444                                expr = new ExpressionFunctionDayOfWeek();
1445                                break;
1446            case SQLTokenizer.DAYOFYEAR:
1447                    invalidParamCount = (paramCount != 1);
1448                                expr = new ExpressionFunctionDayOfYear();
1449                                break;
1450            case SQLTokenizer.HOUR:
1451                    invalidParamCount = (paramCount != 1);
1452                                expr = new ExpressionFunctionHour();
1453                                break;
1454            case SQLTokenizer.MINUTE:
1455                    invalidParamCount = (paramCount != 1);
1456                                expr = new ExpressionFunctionMinute();
1457                                break;
1458            case SQLTokenizer.MONTH:
1459                    invalidParamCount = (paramCount != 1);
1460                                expr = new ExpressionFunctionMonth();
1461                                break;
1462            case SQLTokenizer.NOW:
1463                    invalidParamCount = (paramCount != 0);
1464                                expr = new ExpressionValue( new DateTime(DateTime.now(), SQLTokenizer.TIMESTAMP), SQLTokenizer.TIMESTAMP);
1465                                break;
1466                    
1467        // system functions:
1468            case SQLTokenizer.IIF:
1469                        invalidParamCount = (paramCount != 3);
1470                    expr = new ExpressionFunctionIIF();
1471                        break;
1472                case SQLTokenizer.SWITCH:
1473                        invalidParamCount = (paramCount % 2 != 0);
1474                        ExpressionFunctionCase exprCase = new ExpressionFunctionCase();
1475                        for(int i=0; i < paramCount-1; i +=2)
1476                                exprCase.addCase(params[i], params[i+1] );
1477                        exprCase.setEnd();
1478                        expr = exprCase;
1479                        break;
1480                case SQLTokenizer.IFNULL:
1481                        switch(paramCount){
1482                                case 1:
1483                                        return new ExpressionArithmetic( params[0], ExpressionArithmetic.ISNULL );
1484                                case 2:                                        
1485                                        invalidParamCount = false;
1486                                        expr = new ExpressionFunctionIIF();
1487                                        Expression[] newParams = new Expression[3];
1488                                        newParams[0] = new ExpressionArithmetic( params[0], ExpressionArithmetic.ISNULL );
1489                                        newParams[1] = params[1];
1490                                        newParams[2] = params[0];                                        
1491                                        params = newParams;
1492                                        paramCount = 3;
1493                                        break;
1494                                default:
1495                                        invalidParamCount = true;
1496                                        expr = null; // only for Compiler
1497                        }
1498                        break;
1499                    
1500        // now come the aggregate functions
1501            case SQLTokenizer.COUNT:
1502                                        invalidParamCount = (paramCount != 1);
1503                                        if(params[0].getType() == Expression.NAME){
1504                                                //detect special case COUNT(*)
1505                                                ExpressionName param = (ExpressionName)params[0];
1506                                                if("*".equals(param.getName()) && param.getTableAlias() == null){
1507                                                        params[0] = new ExpressionValue();
1508                                                }
1509                                        }
1510                                        expr = new ExpressionName( Expression.COUNT );
1511                                        break;
1512                        case SQLTokenizer.SUM:
1513                                        invalidParamCount = (paramCount != 1);
1514                                        expr = new ExpressionName( Expression.SUM );
1515                                        break;
1516                        case SQLTokenizer.MAX:
1517                                        invalidParamCount = (paramCount != 1);
1518                                        expr = new ExpressionName( Expression.MAX );
1519                                        break;
1520                        case SQLTokenizer.MIN:
1521                                        invalidParamCount = (paramCount != 1);
1522                                        expr = new ExpressionName( Expression.MIN );
1523                                        break;
1524                        case SQLTokenizer.FIRST:
1525                                        invalidParamCount = (paramCount != 1);
1526                                        expr = new ExpressionName( Expression.FIRST );
1527                                        break;
1528                        case SQLTokenizer.LAST:
1529                                        invalidParamCount = (paramCount != 1);
1530                                        expr = new ExpressionName( Expression.LAST );
1531                                        break;
1532                        case SQLTokenizer.AVG:
1533                                        if(paramCount != 1){
1534                        invalidParamCount = true;
1535                        expr = null;//Only for the compiler
1536                        break;
1537                    }
1538                                        expr = new ExpressionName( Expression.SUM );
1539                                        expr.setParams( params );
1540                                        Expression expr2 = new ExpressionName( Expression.COUNT );
1541                                        expr2.setParams( params );
1542                                        expr = new ExpressionArithmetic( expr, expr2, ExpressionArithmetic.DIV );
1543                                        return expr;
1544            default: throw createSyntaxError(token, "Unknown function.");
1545        }
1546        if(invalidParamCount) throw createSyntaxError( token, "Invalid parameter count." );
1547        expr.setParams( params );
1548        return expr;
1549    }
1550 
1551    /**
1552     * read a table or view name in a FROM clause. If the keyword AS exists then read it also the alias
1553     */
1554    private RowSource tableSource( Command cmd, DataSources tables) throws SQLException{
1555        SQLToken token = nextToken(MISSING_EXPRESSION);
1556        switch(token.value){
1557            case SQLTokenizer.PARENTHESIS_L: // (
1558                    return rowSource( cmd, tables, SQLTokenizer.PARENTHESIS_R );
1559            case SQLTokenizer.ESCAPE_L: // {
1560                    token = nextToken(MISSING_OJ);
1561                    return rowSource( cmd, tables, SQLTokenizer.ESCAPE_R );
1562            case SQLTokenizer.SELECT:
1563                            // inner select
1564                            ViewResult viewResult = new ViewResult( con, select() );
1565                            tables.add(viewResult);
1566                            return viewResult;
1567        }
1568        String catalog = null;
1569        String name = token.getName( sql );
1570        checkValidIdentifer( name, token );
1571                token = nextToken();
1572                //check if the table name include a database name
1573                if(token != null && token.value == SQLTokenizer.POINT){
1574                        token = nextToken(MISSING_EXPRESSION);
1575                        catalog = name;
1576                        name = token.getName( sql );
1577                        checkValidIdentifer( name, token );
1578                        token = nextToken();
1579                }
1580                //TableResult table = new TableResult();
1581                //table.setName( catalog, name );
1582                TableView tableView = Database.getTableView( con, catalog, name);
1583                TableViewResult table = TableViewResult.createResult(tableView);
1584        tables.add( table );
1585 
1586        if(token != null && token.value == SQLTokenizer.AS){
1587            // skip AS keyword, if exists
1588            token = nextToken(MISSING_EXPRESSION);
1589            table.setAlias( token.getName( sql ) );
1590        }else{
1591            previousToken();
1592        }
1593        return table;
1594    }
1595 
1596    /**
1597     * read a join in a from clause.
1598     */
1599    private Join join(Command cmd, DataSources tables, RowSource left, int type) throws SQLException{
1600        RowSource right = rowSource(cmd, tables, 0);
1601        SQLToken token = nextToken();
1602 
1603        while(true){
1604            if(token == null) throw createSyntaxError(null, "Invalid Join Syntax");
1605 
1606            switch(token.value){
1607                    case SQLTokenizer.ON:
1608                            if(type == Join.RIGHT_JOIN)
1609                                                return new Join( Join.LEFT_JOIN, right, left, expression( cmd, 0 ) );
1610                        return new Join( type, left, right, expression( cmd, 0 ) );
1611                    default:
1612                        if(!right.hasAlias()){
1613                            right.setAlias( token.getName( sql ) );
1614                            token = nextToken();
1615                            continue;
1616                        }
1617                        throw createSyntaxError( token, new int[]{SQLTokenizer.ON} );                        
1618            }
1619        }
1620    }
1621 
1622    /**
1623     * returns a row source. A row source is a Table, Join, View or a row function.
1624     *
1625     */
1626    private RowSource rowSource(Command cmd, DataSources tables, int parenthesis) throws SQLException{
1627        RowSource fromSource = null;
1628        fromSource = tableSource(cmd, tables);
1629 
1630        while(true){
1631            SQLToken token = nextToken();
1632            if(token == null) return fromSource;
1633            switch(token.value){
1634                case SQLTokenizer.ON:
1635                    previousToken();
1636                    return fromSource;
1637                case SQLTokenizer.CROSS:
1638                    nextToken(MISSING_JOIN);
1639                    // kein break
1640                case SQLTokenizer.COMMA:
1641                    fromSource = new Join( Join.CROSS_JOIN, fromSource, tableSource(cmd, tables), null);
1642                    break;
1643                case SQLTokenizer.INNER:
1644                    nextToken(MISSING_JOIN);
1645                    fromSource = join( cmd, tables, fromSource, Join.INNER_JOIN );
1646                    break;
1647                case SQLTokenizer.LEFT:
1648                    token = nextToken(MISSING_OUTER_JOIN);
1649                        if(token.value == SQLTokenizer.OUTER)
1650                                token = nextToken(MISSING_JOIN);
1651                    fromSource = join( cmd, tables, fromSource, Join.LEFT_JOIN );
1652                    break;
1653                case SQLTokenizer.RIGHT:
1654                        token = nextToken(MISSING_OUTER_JOIN);
1655                        if(token.value == SQLTokenizer.OUTER)
1656                                token = nextToken(MISSING_JOIN);
1657                                        fromSource = join( cmd, tables, fromSource, Join.RIGHT_JOIN );
1658                                        break;                        
1659                                case SQLTokenizer.FULL:
1660                                        token = nextToken(MISSING_OUTER_JOIN);
1661                                        if(token.value == SQLTokenizer.OUTER)
1662                                                token = nextToken(MISSING_JOIN);
1663                                        fromSource = join( cmd, tables, fromSource, Join.FULL_JOIN );
1664                                        break;                        
1665                case SQLTokenizer.PARENTHESIS_R:
1666                case SQLTokenizer.ESCAPE_R:
1667                    if(parenthesis == token.value) return fromSource;
1668                    if(parenthesis == 0){
1669                            previousToken();
1670                                                return fromSource;
1671                    }
1672                    throw createSyntaxError( token, "Unexpexted closing parethesis in from clause." );
1673                default:
1674                        if(isKeyword(token)){
1675                                                previousToken();
1676                                                return fromSource;
1677                        }
1678                    if(!fromSource.hasAlias()){
1679                        fromSource.setAlias( token.getName( sql ) );
1680                        break;
1681                    }
1682                    throw createSyntaxError( token, new int[]{SQLTokenizer.COMMA, SQLTokenizer.GROUP, SQLTokenizer.ORDER, SQLTokenizer.HAVING} );
1683            }
1684        }
1685    }
1686 
1687    private void from(CommandSelect cmd) throws SQLException{
1688                DataSources tables = new DataSources();
1689        cmd.setFrom(tables);
1690        cmd.setSource( rowSource( cmd, tables, 0 ) );
1691 
1692                SQLToken token;
1693        while(null != (token = nextToken())){
1694            switch(token.value){
1695                case SQLTokenizer.WHERE:
1696                    where( cmd );
1697                    break;
1698                case SQLTokenizer.GROUP:
1699                    group( cmd );
1700                    break;
1701                case SQLTokenizer.HAVING:
1702                    having( cmd );
1703                    break;
1704                default:
1705                        previousToken();
1706                    return;
1707            }
1708        }
1709    }
1710 
1711    private void order(CommandSelect cmd) throws SQLException{
1712        nextToken(MISSING_BY);
1713        cmd.setOrder( expressionTokenList(cmd, SQLTokenizer.ORDER) );
1714    }
1715 
1716    private void group(CommandSelect cmd) throws SQLException{
1717        nextToken(MISSING_BY);
1718        cmd.setGroup( expressionTokenList(cmd, SQLTokenizer.GROUP) );
1719    }
1720 
1721    private void where(CommandSelect cmd) throws SQLException{
1722        cmd.setWhere( expression(cmd, 0) );
1723    }
1724 
1725    private void having(CommandSelect cmd) throws SQLException{
1726        cmd.setHaving( expression(cmd, 0) );
1727    }
1728 
1729 
1730    private static final int[] COMMANDS = {SQLTokenizer.SELECT, SQLTokenizer.DELETE, SQLTokenizer.INSERT, SQLTokenizer.UPDATE, SQLTokenizer.CREATE, SQLTokenizer.DROP, SQLTokenizer.ALTER, SQLTokenizer.SET, SQLTokenizer.USE, SQLTokenizer.EXECUTE, SQLTokenizer.TRUNCATE};
1731    private static final int[] COMMANDS_ESCAPE = {SQLTokenizer.D, SQLTokenizer.T, SQLTokenizer.TS, SQLTokenizer.FN, SQLTokenizer.CALL};
1732    private static final int[] COMMANDS_CREATE = {SQLTokenizer.DATABASE, SQLTokenizer.TABLE, SQLTokenizer.VIEW, SQLTokenizer.INDEX, SQLTokenizer.PROCEDURE};
1733    private static final int[] COMMANDS_SET = {SQLTokenizer.TRANSACTION};
1734        private static final int[] MISSING_TABLE = {SQLTokenizer.TABLE};
1735    private static final int[] ESCAPE_MISSING_CLOSE = {SQLTokenizer.ESCAPE_R};
1736    private static final int[] MISSING_EXPRESSION = {SQLTokenizer.VALUE};
1737    private static final int[] MISSING_IDENTIFER = {SQLTokenizer.IDENTIFER};
1738    private static final int[] MISSING_BY = {SQLTokenizer.BY};
1739    private static final int[] MISSING_PARENTHESIS_L = {SQLTokenizer.PARENTHESIS_L};
1740    private static final int[] MISSING_PARENTHESIS_R = {SQLTokenizer.PARENTHESIS_R};
1741    private static final int[] MISSING_DATATYPE  = {SQLTokenizer.BIT, SQLTokenizer.BOOLEAN, SQLTokenizer.BINARY, SQLTokenizer.VARBINARY, SQLTokenizer.RAW, SQLTokenizer.LONGVARBINARY, SQLTokenizer.BLOB, SQLTokenizer.TINYINT, SQLTokenizer.SMALLINT, SQLTokenizer.INT, SQLTokenizer.COUNTER, SQLTokenizer. BIGINT, SQLTokenizer.SMALLMONEY, SQLTokenizer.MONEY, SQLTokenizer.DECIMAL, SQLTokenizer.NUMERIC, SQLTokenizer.REAL, SQLTokenizer.FLOAT, SQLTokenizer.DOUBLE, SQLTokenizer.DATE, SQLTokenizer.TIME, SQLTokenizer.TIMESTAMP, SQLTokenizer.SMALLDATETIME, SQLTokenizer.CHAR, SQLTokenizer.NCHAR, SQLTokenizer.VARCHAR, SQLTokenizer.NVARCHAR, SQLTokenizer.LONG, SQLTokenizer.LONGNVARCHAR, SQLTokenizer.LONGVARCHAR, SQLTokenizer.CLOB, SQLTokenizer.NCLOB, SQLTokenizer.UNIQUEIDENTIFIER, SQLTokenizer.JAVA_OBJECT, SQLTokenizer.SYSNAME};
1742        private static final int[] MISSING_SQL_DATATYPE = { SQLTokenizer.SQL_BIGINT , SQLTokenizer.SQL_BINARY , SQLTokenizer.SQL_BIT , SQLTokenizer.SQL_CHAR , SQLTokenizer.SQL_DATE , SQLTokenizer.SQL_DECIMAL , SQLTokenizer.SQL_DOUBLE , SQLTokenizer.SQL_FLOAT , SQLTokenizer.SQL_INTEGER , SQLTokenizer.SQL_LONGVARBINARY , SQLTokenizer.SQL_LONGVARCHAR , SQLTokenizer.SQL_REAL , SQLTokenizer.SQL_SMALLINT , SQLTokenizer.SQL_TIME , SQLTokenizer.SQL_TIMESTAMP , SQLTokenizer.SQL_TINYINT , SQLTokenizer.SQL_VARBINARY , SQLTokenizer.SQL_VARCHAR };
1743    private static final int[] MISSING_INTO = {SQLTokenizer.INTO};
1744        private static final int[] MISSING_BETWEEN_IN = {SQLTokenizer.BETWEEN, SQLTokenizer.IN};
1745        private static final int[] MISSING_NOT_NULL = {SQLTokenizer.NOT, SQLTokenizer.NULL};
1746    private static final int[] MISSING_NULL = {SQLTokenizer.NULL};
1747        private static final int[] MISSING_COMMA = {SQLTokenizer.COMMA};
1748    private static final int[] MISSING_COMMA_PARENTHESIS = {SQLTokenizer.COMMA, SQLTokenizer.PARENTHESIS_R};
1749    private static final int[] MISSING_PARENTHESIS_VALUES_SELECT = {SQLTokenizer.PARENTHESIS_L, SQLTokenizer.VALUES, SQLTokenizer.SELECT};
1750    private static final int[] MISSING_TOKEN_LIST = {SQLTokenizer.COMMA, SQLTokenizer.FROM, SQLTokenizer.GROUP, SQLTokenizer.HAVING, SQLTokenizer.ORDER};
1751        private static final int[] MISSING_FROM = {SQLTokenizer.FROM};
1752        private static final int[] MISSING_SET = {SQLTokenizer.SET};
1753        private static final int[] MISSING_EQUALS = {SQLTokenizer.EQUALS};
1754        private static final int[] MISSING_WHERE = {SQLTokenizer.WHERE};
1755        private static final int[] MISSING_WHERE_COMMA = {SQLTokenizer.WHERE, SQLTokenizer.COMMA};
1756    private static final int[] MISSING_ISOLATION = {SQLTokenizer.ISOLATION};
1757    private static final int[] MISSING_LEVEL = {SQLTokenizer.LEVEL};
1758    private static final int[] COMMANDS_TRANS_LEVEL = {SQLTokenizer.READ, SQLTokenizer.REPEATABLE, SQLTokenizer.SERIALIZABLE};
1759    private static final int[] MISSING_READ = {SQLTokenizer.READ};
1760    private static final int[] MISSING_COMM_UNCOMM = {SQLTokenizer.COMMITTED, SQLTokenizer.UNCOMMITTED};
1761    private static final int[] MISSING_OPTIONS_DATATYPE = { SQLTokenizer.DEFAULT, SQLTokenizer.IDENTITY, SQLTokenizer.NOT, SQLTokenizer.NULL, SQLTokenizer.PRIMARY, SQLTokenizer.UNIQUE, SQLTokenizer.COMMA, SQLTokenizer.PARENTHESIS_R, SQLTokenizer.PARENTHESIS_L};
1762    private static final int[] MISSING_NUMBERVALUE = {SQLTokenizer.NUMBERVALUE};
1763    private static final int[] MISSING_AND = {SQLTokenizer.AND};
1764    private static final int[] MISSING_JOIN = {SQLTokenizer.JOIN};
1765    private static final int[] MISSING_OUTER_JOIN = {SQLTokenizer.OUTER, SQLTokenizer.JOIN};
1766    private static final int[] MISSING_OJ = {SQLTokenizer.OJ};
1767        private static final int[] MISSING_KEYTYPE = {SQLTokenizer.PRIMARY, SQLTokenizer.UNIQUE, SQLTokenizer.FOREIGN};
1768        private static final int[] MISSING_KEY = {SQLTokenizer.KEY};
1769    private static final int[] MISSING_REFERENCES = {SQLTokenizer.REFERENCES};
1770        private static final int[] MISSING_AS = {SQLTokenizer.AS};
1771        private static final int[] MISSING_SELECT = {SQLTokenizer.SELECT};
1772        private static final int[] MISSING_INTERVALS = {SQLTokenizer.SQL_TSI_FRAC_SECOND, SQLTokenizer.SQL_TSI_SECOND, SQLTokenizer.SQL_TSI_MINUTE, SQLTokenizer.SQL_TSI_HOUR, SQLTokenizer.SQL_TSI_DAY, SQLTokenizer.SQL_TSI_WEEK, SQLTokenizer.SQL_TSI_MONTH, SQLTokenizer.SQL_TSI_QUARTER, SQLTokenizer.SQL_TSI_YEAR, SQLTokenizer.MILLISECOND, SQLTokenizer.SECOND, SQLTokenizer.MINUTE, SQLTokenizer.HOUR, SQLTokenizer.DAY, SQLTokenizer.WEEK, SQLTokenizer.MONTH, SQLTokenizer.QUARTER, SQLTokenizer.YEAR, SQLTokenizer.D};
1773        private static final int[] MISSING_ALL = {SQLTokenizer.ALL};
1774        private static final int[] MISSING_THEN = {SQLTokenizer.THEN};
1775        private static final int[] MISSING_WHEN_ELSE_END = {SQLTokenizer.WHEN, SQLTokenizer.ELSE, SQLTokenizer.END};
1776        
1777        
1778}

[all classes][smallsql.database]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov