Source Code Cross Referenced for Parser.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » db » sql » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » resin » com.caucho.db.sql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *   Free SoftwareFoundation, Inc.
0023:         *   59 Temple Place, Suite 330
0024:         *   Boston, MA 02111-1307  USA
0025:         *
0026:         * @author Scott Ferguson
0027:         */
0028:
0029:        package com.caucho.db.sql;
0030:
0031:        import com.caucho.db.Database;
0032:        import com.caucho.db.table.Column;
0033:        import com.caucho.db.table.Table;
0034:        import com.caucho.db.table.TableFactory;
0035:        import com.caucho.log.Log;
0036:        import com.caucho.util.CharBuffer;
0037:        import com.caucho.util.IntMap;
0038:        import com.caucho.util.L10N;
0039:
0040:        import java.sql.SQLException;
0041:        import java.util.ArrayList;
0042:        import java.util.HashSet;
0043:        import java.util.logging.Level;
0044:        import java.util.logging.Logger;
0045:
0046:        public class Parser {
0047:            private static final Logger log = Log.open(Parser.class);
0048:            private static final L10N L = new L10N(Parser.class);
0049:
0050:            final static int IDENTIFIER = 128;
0051:            final static int INTEGER = IDENTIFIER + 1;
0052:            final static int LONG = INTEGER + 1;
0053:            final static int DOUBLE = LONG + 1;
0054:            final static int STRING = DOUBLE + 1;
0055:            final static int TRUE = STRING + 1;
0056:            final static int FALSE = TRUE + 1;
0057:            final static int UNKNOWN = FALSE + 1;
0058:            final static int NULL = UNKNOWN + 1;
0059:            final static int EXISTS = NULL + 1;
0060:
0061:            final static int FROM = EXISTS + 1;
0062:            final static int IN = FROM + 1;
0063:            final static int SELECT = IN + 1;
0064:            final static int DISTINCT = SELECT + 1;
0065:            final static int WHERE = SELECT + 1;
0066:            final static int AS = WHERE + 1;
0067:            final static int ORDER = AS + 1;
0068:            final static int GROUP = ORDER + 1;
0069:            final static int BY = GROUP + 1;
0070:            final static int ASC = BY + 1;
0071:            final static int DESC = ASC + 1;
0072:            final static int LIMIT = DESC + 1;
0073:            final static int OFFSET = LIMIT + 1;
0074:
0075:            final static int BETWEEN = OFFSET + 1;
0076:            final static int LIKE = BETWEEN + 1;
0077:            final static int ESCAPE = LIKE + 1;
0078:            final static int IS = ESCAPE + 1;
0079:            final static int CONCAT = IS + 1;
0080:
0081:            final static int EQ = CONCAT + 1;
0082:            final static int NE = EQ + 1;
0083:            final static int LT = NE + 1;
0084:            final static int LE = LT + 1;
0085:            final static int GT = LE + 1;
0086:            final static int GE = GT + 1;
0087:
0088:            final static int AND = GE + 1;
0089:            final static int OR = AND + 1;
0090:            final static int NOT = OR + 1;
0091:
0092:            final static int ARG = NOT + 1;
0093:
0094:            final static int CREATE = ARG + 1;
0095:            final static int TABLE = CREATE + 1;
0096:            final static int INSERT = TABLE + 1;
0097:            final static int INTO = INSERT + 1;
0098:            final static int VALUES = INTO + 1;
0099:            final static int DROP = VALUES + 1;
0100:            final static int UPDATE = DROP + 1;
0101:            final static int SET = UPDATE + 1;
0102:            final static int DELETE = SET + 1;
0103:
0104:            final static int CONSTRAINT = DELETE + 1;
0105:            final static int UNIQUE = CONSTRAINT + 1;
0106:            final static int PRIMARY = UNIQUE + 1;
0107:            final static int CHECK = PRIMARY + 1;
0108:            final static int FOREIGN = CHECK + 1;
0109:            final static int KEY = FOREIGN + 1;
0110:
0111:            private final static IntMap _reserved;
0112:
0113:            private Database _database;
0114:
0115:            private final String _sql;
0116:            private final char[] _sqlChars;
0117:            private final int _sqlLength;
0118:
0119:            private int _parseIndex;
0120:
0121:            private final CharBuffer _cb = new CharBuffer();
0122:
0123:            private String _lexeme;
0124:            private int _token;
0125:
0126:            private ArrayList<ParamExpr> _params = new ArrayList<ParamExpr>();
0127:
0128:            private Query _query;
0129:            private AndExpr _andExpr;
0130:
0131:            private Parser(Database database, String sql) {
0132:                _database = database;
0133:                _sql = sql;
0134:                _sqlLength = _sql.length();
0135:                _sqlChars = new char[_sqlLength];
0136:                _sql.getChars(0, _sqlLength, _sqlChars, 0);
0137:            }
0138:
0139:            public static Query parse(Database database, String sql)
0140:                    throws SQLException {
0141:                Parser parser = new Parser(database, sql);
0142:
0143:                Query query = parser.parse();
0144:
0145:                query.bind();
0146:
0147:                return query;
0148:            }
0149:
0150:            public static Expr parseExpr(Database database, String sql)
0151:                    throws SQLException {
0152:                Parser parser = new Parser(database, sql);
0153:
0154:                Expr expr = parser.parseExpr();
0155:
0156:                return expr.bind(null);
0157:            }
0158:
0159:            /**
0160:             * Parses the query.
0161:             */
0162:            private Query parse() throws SQLException {
0163:                int token = scanToken();
0164:
0165:                switch (token) {
0166:                case SELECT:
0167:                    return parseSelect();
0168:
0169:                case CREATE:
0170:                    return parseCreate();
0171:
0172:                case INSERT:
0173:                    return parseInsert();
0174:
0175:                case DELETE:
0176:                    return parseDelete();
0177:
0178:                case DROP:
0179:                    return parseDrop();
0180:
0181:                case UPDATE:
0182:                    return parseUpdate();
0183:
0184:                default:
0185:                    throw new SQLParseException(L.l("unknown query at `{0}'",
0186:                            tokenName(token)));
0187:                }
0188:            }
0189:
0190:            /**
0191:             * Parses the select.
0192:             */
0193:            private SelectQuery parseSelect() throws SQLException {
0194:                return parseSelect(new SelectQuery(_database, _sql));
0195:            }
0196:
0197:            /**
0198:             * Parses the select.
0199:             */
0200:            private SelectQuery parseSelect(SelectQuery query)
0201:                    throws SQLException {
0202:                boolean distinct = false;
0203:
0204:                int token = scanToken();
0205:
0206:                if (token == DISTINCT)
0207:                    distinct = true;
0208:                else
0209:                    _token = token;
0210:
0211:                ArrayList<Expr> resultItems = new ArrayList<Expr>();
0212:
0213:                int startToken = scanToken();
0214:                String startLexeme = _lexeme;
0215:                int startOffset = _parseIndex;
0216:
0217:                while ((token = scanToken()) >= 0 && token != FROM) {
0218:                }
0219:
0220:                if (token != FROM)
0221:                    throw error(L.l("expected FROM at `{0}'", tokenName(token)));
0222:
0223:                query.setParent(_query);
0224:                _query = query;
0225:
0226:                AndExpr oldAnd = _andExpr;
0227:                _andExpr = new AndExpr();
0228:
0229:                ArrayList<FromItem> fromItems = parseFromItems();
0230:
0231:                query.setFromItems(fromItems);
0232:
0233:                token = scanToken();
0234:
0235:                int tailToken = token;
0236:                int tailOffset = _parseIndex;
0237:
0238:                _token = startToken;
0239:                _parseIndex = startOffset;
0240:                _lexeme = startLexeme;
0241:
0242:                Expr expr = parseSelectExpr();
0243:
0244:                resultItems.add(expr);
0245:
0246:                while ((token = scanToken()) == ',') {
0247:                    expr = parseSelectExpr();
0248:
0249:                    resultItems.add(expr);
0250:                }
0251:
0252:                _token = tailToken;
0253:                _parseIndex = tailOffset;
0254:
0255:                token = scanToken();
0256:
0257:                if (token == WHERE)
0258:                    _andExpr.add(parseExpr());
0259:                else
0260:                    _token = token;
0261:
0262:                ParamExpr[] params = _params.toArray(new ParamExpr[_params
0263:                        .size()]);
0264:
0265:                Expr whereExpr = _andExpr.getSingleExpr();
0266:                _andExpr = null;
0267:                query.setWhereExpr(whereExpr);
0268:                query.setParams(params);
0269:
0270:                for (int i = resultItems.size() - 1; i >= 0; i--) {
0271:                    Expr subExpr = resultItems.get(i);
0272:
0273:                    if (subExpr instanceof  UnboundStarExpr) {
0274:                        UnboundStarExpr unboundExpr = (UnboundStarExpr) subExpr;
0275:                        ArrayList<Expr> exprList = unboundExpr.expand(query
0276:                                .getFromItems());
0277:
0278:                        resultItems.remove(i);
0279:                        resultItems.addAll(i, exprList);
0280:                    }
0281:                }
0282:
0283:                ArrayList<Expr> groupItems = null;
0284:                token = scanToken();
0285:                if (token == GROUP) {
0286:                    token = scanToken();
0287:
0288:                    if (token != BY)
0289:                        throw error(L.l("expected BY at `{0}'",
0290:                                tokenName(token)));
0291:
0292:                    groupItems = parseGroup(query);
0293:                } else
0294:                    _token = token;
0295:
0296:                token = scanToken();
0297:                if (token == ORDER) {
0298:                    token = scanToken();
0299:
0300:                    if (token != BY)
0301:                        throw error(L.l("expected BY at `{0}'",
0302:                                tokenName(token)));
0303:
0304:                    Order order = parseOrder(query, resultItems);
0305:                } else
0306:                    _token = token;
0307:
0308:                Expr[] resultArray = resultItems.toArray(new Expr[resultItems
0309:                        .size()]);
0310:
0311:                query.setResults(resultArray);
0312:
0313:                if (query.isGroup()) {
0314:                    Expr[] resultList = query.getResults();
0315:
0316:                    bindGroup(query, groupItems);
0317:
0318:                    for (int i = 0; i < resultList.length; i++) {
0319:                        Expr subExpr = resultList[i];
0320:
0321:                        if (!(subExpr instanceof  GroupExpr)) {
0322:                            resultList[i] = new GroupResultExpr(i, subExpr);
0323:                        }
0324:                    }
0325:                }
0326:
0327:                token = scanToken();
0328:                if (token == LIMIT) {
0329:                    parseLimit(query);
0330:                } else
0331:                    _token = token;
0332:
0333:                if (query.getParent() == null && token >= 0 && token != LIMIT
0334:                        && token != OFFSET)
0335:                    throw error(L.l("unexpected token at end '{0}'",
0336:                            tokenName(token)));
0337:
0338:                _query = query.getParent();
0339:                _andExpr = oldAnd;
0340:
0341:                return query;
0342:            }
0343:
0344:            private ArrayList<FromItem> parseFromItems() throws SQLException {
0345:                ArrayList<FromItem> fromItems = new ArrayList<FromItem>();
0346:
0347:                int token;
0348:
0349:                // XXX: somewhat hacked syntax
0350:                while ((token = scanToken()) == '(') {
0351:                }
0352:                _token = token;
0353:
0354:                FromItem fromItem = parseFromItem();
0355:
0356:                if (fromItem != null)
0357:                    fromItems.add(fromItem);
0358:
0359:                while (true) {
0360:                    token = scanToken();
0361:
0362:                    boolean isNatural = false;
0363:                    boolean isOuter = false;
0364:                    boolean isLeft = true;
0365:                    boolean isRight = true;
0366:
0367:                    if (token == ',') {
0368:                        fromItem = parseFromItem();
0369:                        fromItems.add(fromItem);
0370:                        continue;
0371:                    } else if (token == '(' || token == ')')
0372:                        continue;
0373:                    else if (token != IDENTIFIER) {
0374:                        _token = token;
0375:                        break;
0376:                    } else if ("join".equalsIgnoreCase(_lexeme)) {
0377:                    } else if ("inner".equalsIgnoreCase(_lexeme)) {
0378:                        String join = parseIdentifier();
0379:
0380:                        if (!"join".equalsIgnoreCase(join))
0381:                            throw error(L.l("expected JOIN at '{0}'", join));
0382:                    } else if ("left".equalsIgnoreCase(_lexeme)) {
0383:                        String name = parseIdentifier();
0384:
0385:                        if ("outer".equalsIgnoreCase(name))
0386:                            name = parseIdentifier();
0387:
0388:                        if (!"join".equalsIgnoreCase(name))
0389:                            throw error(L.l("expected JOIN at '{0}'", name));
0390:
0391:                        isOuter = true;
0392:                    } else if ("right".equalsIgnoreCase(_lexeme)) {
0393:                        String name = parseIdentifier();
0394:
0395:                        if ("outer".equalsIgnoreCase(name))
0396:                            name = parseIdentifier();
0397:
0398:                        if (!"join".equalsIgnoreCase(name))
0399:                            throw error(L.l("expected JOIN at '{0}'", name));
0400:
0401:                        isRight = true;
0402:                        isOuter = true;
0403:
0404:                        throw error(L.l("right outer joins are not supported"));
0405:                    } else if ("natural".equalsIgnoreCase(_lexeme)) {
0406:                        String name = parseIdentifier();
0407:
0408:                        isNatural = true;
0409:
0410:                        if ("left".equalsIgnoreCase(name)) {
0411:                            name = parseIdentifier();
0412:
0413:                            if ("outer".equalsIgnoreCase(name))
0414:                                name = parseIdentifier();
0415:
0416:                            isOuter = true;
0417:                        } else if ("right".equalsIgnoreCase(name)) {
0418:                            name = parseIdentifier();
0419:
0420:                            if ("outer".equalsIgnoreCase(name))
0421:                                name = parseIdentifier();
0422:
0423:                            isRight = true;
0424:                            isOuter = true;
0425:
0426:                            throw error(L
0427:                                    .l("right outer joins are not supported"));
0428:                        }
0429:
0430:                        if (!"join".equalsIgnoreCase(name))
0431:                            throw error(L.l("expected JOIN at '{0}'", name));
0432:                    } else {
0433:                        _token = token;
0434:                        break;
0435:                    }
0436:
0437:                    fromItem = parseFromItem();
0438:                    fromItems.add(fromItem);
0439:
0440:                    _query.setFromItems(fromItems);
0441:
0442:                    token = scanToken();
0443:                    if (token == IDENTIFIER && "on".equalsIgnoreCase(_lexeme)) {
0444:                        Expr onExpr = parseExpr();
0445:
0446:                        if (isOuter) {
0447:                            FromItem leftItem = fromItems
0448:                                    .get(fromItems.size() - 2);
0449:                            FromItem rightItem = fromItems
0450:                                    .get(fromItems.size() - 1);
0451:
0452:                            onExpr = new LeftOuterJoinExpr(rightItem, onExpr);
0453:
0454:                            rightItem.setDependTable(leftItem);
0455:                        }
0456:
0457:                        _andExpr.add(onExpr);
0458:                    } else
0459:                        _token = token;
0460:                }
0461:
0462:                return fromItems;
0463:            }
0464:
0465:            /**
0466:             * Parses a select expression.
0467:             */
0468:            private Expr parseSelectExpr() throws SQLException {
0469:                int token = scanToken();
0470:
0471:                if (token == '*')
0472:                    return new UnboundStarExpr();
0473:                else {
0474:                    _token = token;
0475:
0476:                    return parseExpr();
0477:                }
0478:            }
0479:
0480:            /**
0481:             * Parses a from item
0482:             */
0483:            private FromItem parseFromItem() throws SQLException {
0484:                String tableName = parseIdentifier();
0485:
0486:                if (tableName.equalsIgnoreCase("DUAL"))
0487:                    return null;
0488:
0489:                Table table = _database.getTable(tableName);
0490:
0491:                if (table == null)
0492:                    throw error(L
0493:                            .l(
0494:                                    "'{0}' is an unknown table.  'FROM table' requires an existing table.",
0495:                                    tableName));
0496:
0497:                String name = table.getName();
0498:
0499:                int token = scanToken();
0500:                if (token == AS)
0501:                    name = parseIdentifier();
0502:                else if (token == IDENTIFIER)
0503:                    name = _lexeme;
0504:                else
0505:                    _token = token;
0506:
0507:                return new FromItem(table, name);
0508:            }
0509:
0510:            /**
0511:             * Parses the ORDER BY
0512:             */
0513:            private Order parseOrder(SelectQuery query,
0514:                    ArrayList<Expr> resultList) throws SQLException {
0515:                int token;
0516:
0517:                Order order = null;
0518:
0519:                do {
0520:                    Expr expr = parseExpr();
0521:
0522:                    expr = expr.bind(query);
0523:
0524:                    token = scanToken();
0525:                    boolean isAsc = true;
0526:                    if (token == ASC)
0527:                        isAsc = true;
0528:                    else if (token == DESC)
0529:                        isAsc = false;
0530:                    else
0531:                        _token = token;
0532:
0533:                    int index;
0534:                    for (index = 0; index < resultList.size(); index++) {
0535:                        Expr resultExpr = resultList.get(index);
0536:
0537:                        if (expr.equals(resultExpr))
0538:                            break;
0539:                    }
0540:
0541:                    if (resultList.size() <= index) {
0542:                        resultList.add(expr);
0543:                    }
0544:
0545:                    Order tailOrder = expr.createOrder(index);
0546:                    tailOrder.setAscending(isAsc);
0547:
0548:                    order = Order.append(order, tailOrder);
0549:
0550:                    // ascList.add(isAsc ? Boolean.TRUE : Boolean.FALSE);
0551:                } while ((token = scanToken()) == ',');
0552:
0553:                query.setOrder(order);
0554:
0555:                _token = token;
0556:
0557:                return order;
0558:            }
0559:
0560:            /**
0561:             * Parses the GROUP BY
0562:             */
0563:            private ArrayList<Expr> parseGroup(SelectQuery query)
0564:                    throws SQLException {
0565:                query.setGroup(true);
0566:                int token;
0567:
0568:                ArrayList<Expr> groupList = new ArrayList<Expr>();
0569:
0570:                do {
0571:                    groupList.add(parseExpr());
0572:                } while ((token = scanToken()) == ',');
0573:
0574:                _token = token;
0575:
0576:                return groupList;
0577:            }
0578:
0579:            /**
0580:             * Parses the GROUP BY
0581:             */
0582:            private void bindGroup(SelectQuery query, ArrayList<Expr> groupList)
0583:                    throws SQLException {
0584:                query.setGroup(true);
0585:
0586:                Expr[] resultList = query.getResults();
0587:
0588:                for (int i = 0; i < groupList.size(); i++) {
0589:                    Expr expr = groupList.get(i);
0590:
0591:                    expr = expr.bind(query);
0592:
0593:                    int index;
0594:                    for (index = 0; index < resultList.length; index++) {
0595:                        Expr resultExpr = resultList[index];
0596:
0597:                        if (expr.equals(resultExpr)) {
0598:                            resultList[index] = new GroupResultExpr(index,
0599:                                    resultExpr);
0600:
0601:                            break;
0602:                        }
0603:                    }
0604:
0605:                    if (resultList.length <= index) {
0606:                        throw error(L
0607:                                .l(
0608:                                        "GROUP BY field '{0}' must refer to a result field.",
0609:                                        expr));
0610:                    }
0611:
0612:                    query.setGroupResult(index);
0613:                }
0614:            }
0615:
0616:            /**
0617:             * Parses the LIMIT
0618:             */
0619:            private void parseLimit(SelectQuery query) throws SQLException {
0620:                int token = scanToken();
0621:
0622:                if (token == INTEGER) {
0623:                    query.setLimit(Integer.valueOf(_lexeme));
0624:                    _token = scanToken();
0625:                } else
0626:                    throw error(L.l("LIMIT expected LIMIT int"));
0627:            }
0628:
0629:            /**
0630:             * Parses the create.
0631:             */
0632:            private Query parseCreate() throws SQLException {
0633:                int token;
0634:
0635:                TableFactory factory = _database.createTableFactory();
0636:
0637:                if ((token = scanToken()) != TABLE)
0638:                    throw error(L
0639:                            .l("expected TABLE at `{0}'", tokenName(token)));
0640:
0641:                if ((token = scanToken()) != IDENTIFIER)
0642:                    throw error(L.l("expected identifier at `{0}'",
0643:                            tokenName(token)));
0644:
0645:                factory.startTable(_lexeme);
0646:
0647:                if ((token = scanToken()) != '(')
0648:                    throw error(L.l("expected '(' at `{0}'", tokenName(token)));
0649:
0650:                do {
0651:                    token = scanToken();
0652:
0653:                    switch (token) {
0654:                    case IDENTIFIER:
0655:                        parseCreateColumn(factory, _lexeme);
0656:                        break;
0657:
0658:                    case UNIQUE:
0659:                        factory.addUnique(parseColumnNames());
0660:                        break;
0661:
0662:                    case PRIMARY:
0663:                        token = scanToken();
0664:                        if (token != KEY)
0665:                            throw error(L.l("expected 'key' at {0}",
0666:                                    tokenName(token)));
0667:
0668:                        factory.addPrimaryKey(parseColumnNames());
0669:                        break;
0670:
0671:                    case KEY:
0672:                        String key = parseIdentifier();
0673:
0674:                        parseColumnNames(); // factory.addPrimaryKey(parseColumnNames());
0675:                        break;
0676:
0677:                    case CHECK:
0678:                        if ((token = scanToken()) != '(')
0679:                            throw error(L.l("Expected '(' at '{0}'",
0680:                                    tokenName(token)));
0681:
0682:                        parseExpr();
0683:
0684:                        if ((token = scanToken()) != ')')
0685:                            throw error(L.l("Expected ')' at '{0}'",
0686:                                    tokenName(token)));
0687:                        break;
0688:
0689:                    default:
0690:                        throw error(L.l("unexpected token `{0}'",
0691:                                tokenName(token)));
0692:                    }
0693:
0694:                    token = scanToken();
0695:                } while (token == ',');
0696:
0697:                if (token != ')')
0698:                    throw error(L.l("expected ')' at `{0}'", tokenName(token)));
0699:
0700:                return new CreateQuery(_database, _sql, factory);
0701:            }
0702:
0703:            /**
0704:             * Parses a column declaration.
0705:             */
0706:            private void parseCreateColumn(TableFactory factory, String name)
0707:                    throws SQLException {
0708:                int token;
0709:
0710:                if ((token = scanToken()) != IDENTIFIER)
0711:                    throw error(L.l("expected column type at {0}",
0712:                            tokenName(token)));
0713:
0714:                String type = _lexeme;
0715:                int length = -1;
0716:                int scale = -1;
0717:
0718:                if (type.equalsIgnoreCase("double")) {
0719:                    if ((token = scanToken()) == IDENTIFIER) {
0720:                        if (_lexeme.equalsIgnoreCase("precision")) {
0721:                        } else
0722:                            throw error(L.l("unexpected double type at {0}",
0723:                                    _lexeme));
0724:                    } else
0725:                        _token = token;
0726:                }
0727:
0728:                if ((token = scanToken()) == '(') {
0729:                    if ((token = scanToken()) != INTEGER)
0730:                        throw error(L.l("expected column width at `{0}'",
0731:                                tokenName(token)));
0732:
0733:                    length = Integer.parseInt(_lexeme);
0734:
0735:                    if ((token = scanToken()) == ',') {
0736:                        if ((token = scanToken()) != INTEGER)
0737:                            throw error(L.l("expected column scale at `{0}'",
0738:                                    tokenName(token)));
0739:
0740:                        scale = Integer.parseInt(_lexeme);
0741:
0742:                        token = scanToken();
0743:                    }
0744:
0745:                    if (token != ')')
0746:                        throw error(L.l("expected ')' at '{0}'",
0747:                                tokenName(token)));
0748:                } else
0749:                    _token = token;
0750:
0751:                if (type.equalsIgnoreCase("varchar")) {
0752:                    if (length < 0)
0753:                        throw error(L.l("VARCHAR needs a defined length"));
0754:
0755:                    factory.addVarchar(name, length);
0756:                } else if (type.equalsIgnoreCase("char")) {
0757:                    if (length < 0)
0758:                        length = 1;
0759:
0760:                    factory.addVarchar(name, length);
0761:                } else if (type.equalsIgnoreCase("varbinary")) {
0762:                    if (length < 0)
0763:                        throw error(L.l("VARBINARY needs a defined length"));
0764:
0765:                    factory.addVarbinary(name, length);
0766:                } else if (type.equalsIgnoreCase("blob")) {
0767:                    factory.addBlob(name);
0768:                } else if (type.equalsIgnoreCase("integer")
0769:                        || type.equalsIgnoreCase("int")
0770:                        || type.equalsIgnoreCase("smallint")
0771:                        || type.equalsIgnoreCase("tinyint")
0772:                        || type.equalsIgnoreCase("mediumint")
0773:                        || type.equalsIgnoreCase("bit")) {
0774:                    factory.addInteger(name);
0775:                } else if (type.equalsIgnoreCase("bigint")) {
0776:                    factory.addLong(name);
0777:                } else if (type.equalsIgnoreCase("double")
0778:                        || type.equalsIgnoreCase("float")
0779:                        || type.equalsIgnoreCase("real")) {
0780:                    factory.addDouble(name);
0781:                } else if (type.equalsIgnoreCase("datetime")
0782:                        || type.equalsIgnoreCase("timestamp")) {
0783:                    factory.addDateTime(name);
0784:                } else if (type.equalsIgnoreCase("text")
0785:                        || type.equalsIgnoreCase("clob")) {
0786:                    factory.addVarchar(name, 255);
0787:                } else if (type.equalsIgnoreCase("decimal")
0788:                        || type.equalsIgnoreCase("numeric")) {
0789:                    factory.addNumeric(name, length, scale);
0790:                } else
0791:                    throw error(L.l("Unknown type {0}", type));
0792:
0793:                token = scanToken();
0794:                if (token == IDENTIFIER && _lexeme.equalsIgnoreCase("default")) {
0795:                    Expr defaultExpr = parseExpr();
0796:
0797:                    factory.setDefault(name, defaultExpr);
0798:                } else
0799:                    _token = token;
0800:
0801:                while (true) {
0802:                    token = scanToken();
0803:
0804:                    // XXX: stuff like NOT NULL
0805:
0806:                    switch (token) {
0807:                    case ')':
0808:                    case ',':
0809:                        _token = token;
0810:                        return;
0811:
0812:                    case UNIQUE:
0813:                        factory.setUnique(name);
0814:                        break;
0815:
0816:                    case PRIMARY:
0817:                        token = scanToken();
0818:                        if (token != KEY)
0819:                            throw error(L.l("expected key at {0}",
0820:                                    tokenName(token)));
0821:
0822:                        factory.setPrimaryKey(name);
0823:                        break;
0824:
0825:                    case CHECK:
0826:                        if ((token = scanToken()) != '(')
0827:                            throw error(L.l("Expected '(' at '{0}'",
0828:                                    tokenName(token)));
0829:
0830:                        parseExpr();
0831:
0832:                        if ((token = scanToken()) != ')')
0833:                            throw error(L.l("Expected ')' at '{0}'",
0834:                                    tokenName(token)));
0835:                        break;
0836:
0837:                    case IDENTIFIER:
0838:                        String id = _lexeme;
0839:                        if (id.equalsIgnoreCase("references")) {
0840:                            ArrayList<String> foreignKey = new ArrayList<String>();
0841:                            foreignKey.add(name);
0842:                            parseReferences(foreignKey);
0843:                        } else if (id.equalsIgnoreCase("default")) {
0844:                            Expr expr = parseExpr();
0845:                        } else if (id.equalsIgnoreCase("auto_increment")) {
0846:                            factory.setAutoIncrement(name, 1);
0847:                        } else if (id.equalsIgnoreCase("unsigned")) {
0848:                        } else if (id.equalsIgnoreCase("binary")) {
0849:                        } else
0850:                            throw error(L.l("unexpected token '{0}'",
0851:                                    tokenName(token)));
0852:                        break;
0853:
0854:                    case NULL:
0855:                        break;
0856:
0857:                    case NOT:
0858:                        if ((token = scanToken()) == NULL)
0859:                            factory.setNotNull(name);
0860:                        else
0861:                            throw error(L.l("unexpected token '{0}'",
0862:                                    tokenName(token)));
0863:                        break;
0864:
0865:                    default:
0866:                        throw error(L.l("unexpected token '{0}'",
0867:                                tokenName(token)));
0868:                    }
0869:                }
0870:            }
0871:
0872:            /**
0873:             * Parses a key constraint declaration.
0874:             */
0875:            private void parseKeyConstraint(TableFactory factory)
0876:                    throws SQLException {
0877:                String key = parseIdentifier();
0878:
0879:                int token = scanToken();
0880:
0881:                if (token == '(') {
0882:                    parseIdentifier();
0883:
0884:                    token = scanToken();
0885:                    if (token != ')')
0886:                        throw error("expected ')'");
0887:                } else
0888:                    _token = token;
0889:            }
0890:
0891:            /**
0892:             * Parses the references clause.
0893:             */
0894:            public void parseReferences(ArrayList<String> name)
0895:                    throws SQLException {
0896:                String foreignTable = parseIdentifier();
0897:
0898:                int token = scanToken();
0899:
0900:                ArrayList<String> foreignColumns = new ArrayList<String>();
0901:
0902:                if (token == '(') {
0903:                    _token = token;
0904:
0905:                    foreignColumns = parseColumnNames();
0906:                } else
0907:                    _token = token;
0908:            }
0909:
0910:            /**
0911:             * Parses a list of column names
0912:             */
0913:            public ArrayList<String> parseColumnNames() throws SQLException {
0914:                ArrayList<String> columns = new ArrayList<String>();
0915:
0916:                int token = scanToken();
0917:                if (token == '(') {
0918:                    do {
0919:                        columns.add(parseIdentifier());
0920:
0921:                        token = scanToken();
0922:                    } while (token == ',');
0923:
0924:                    if (token != ')')
0925:                        throw error(L.l("expected ')' at '{0}'",
0926:                                tokenName(token)));
0927:                } else if (token == IDENTIFIER) {
0928:                    columns.add(_lexeme);
0929:
0930:                    _token = token;
0931:                } else
0932:                    throw error(L.l("expected '(' at '{0}'", tokenName(token)));
0933:
0934:                return columns;
0935:            }
0936:
0937:            /**
0938:             * Parses the insert.
0939:             */
0940:            private Query parseInsert() throws SQLException {
0941:                int token;
0942:
0943:                if ((token = scanToken()) != INTO)
0944:                    throw error(L.l("expected INTO at `{0}'", tokenName(token)));
0945:
0946:                if ((token = scanToken()) != IDENTIFIER)
0947:                    throw error(L.l("expected identifier at `{0}'",
0948:                            tokenName(token)));
0949:
0950:                Table table = _database.getTable(_lexeme);
0951:
0952:                if (table == null)
0953:                    throw error(L.l("unknown table `{0}'", tokenName(token)));
0954:
0955:                FromItem fromItem = new FromItem(table, table.getName());
0956:                FromItem[] fromList = new FromItem[] { fromItem };
0957:
0958:                ArrayList<Column> columns = new ArrayList<Column>();
0959:
0960:                if ((token = scanToken()) == '(') {
0961:                    do {
0962:                        String columnName = parseIdentifier();
0963:
0964:                        Column column = table.getColumn(columnName);
0965:
0966:                        if (column == null)
0967:                            throw new SQLException(L.l(
0968:                                    "`{0}' is not a valid column in {1}",
0969:                                    columnName, table.getName()));
0970:                        columns.add(column);
0971:                    } while ((token = scanToken()) == ',');
0972:
0973:                    if (token != ')')
0974:                        throw error(L.l("expected ')' at `{0}'",
0975:                                tokenName(token)));
0976:
0977:                    token = scanToken();
0978:                } else {
0979:                    Column[] columnArray = table.getColumns();
0980:
0981:                    for (int i = 0; i < columnArray.length; i++)
0982:                        columns.add(columnArray[i]);
0983:                }
0984:
0985:                if (token != VALUES)
0986:                    throw error(L.l("expected VALUES at `{0}'",
0987:                            tokenName(token)));
0988:
0989:                if ((token = scanToken()) != '(')
0990:                    throw error(L.l("expected '(' at `{0}'", tokenName(token)));
0991:
0992:                ArrayList<Expr> values = new ArrayList<Expr>();
0993:
0994:                InsertQuery query = new InsertQuery(_database, _sql, table,
0995:                        columns);
0996:                _query = query;
0997:
0998:                int i = 0;
0999:                do {
1000:                    Expr expr = parseExpr();
1001:
1002:                    expr = expr.bind(new TempQuery(fromList));
1003:
1004:                    values.add(expr);
1005:
1006:                    i++;
1007:                } while ((token = scanToken()) == ',');
1008:
1009:                if (token != ')')
1010:                    throw error(L.l("expected ')' at {0}", tokenName(token)));
1011:
1012:                if (columns.size() != values.size())
1013:                    throw error(L
1014:                            .l("number of columns does not match number of values"));
1015:
1016:                ParamExpr[] params = _params.toArray(new ParamExpr[_params
1017:                        .size()]);
1018:
1019:                query.setParams(params);
1020:                query.setValues(values);
1021:                query.init();
1022:
1023:                return query;
1024:            }
1025:
1026:            /**
1027:             * Parses the delete.
1028:             */
1029:            private Query parseDelete() throws SQLException {
1030:                int token;
1031:
1032:                if ((token = scanToken()) != FROM)
1033:                    throw error(L.l("expected FROM at `{0}'", tokenName(token)));
1034:
1035:                if ((token = scanToken()) != IDENTIFIER)
1036:                    throw error(L.l("expected identifier at `{0}'",
1037:                            tokenName(token)));
1038:
1039:                Table table = _database.getTable(_lexeme);
1040:
1041:                if (table == null)
1042:                    throw error(L.l("unknown table `{0}'", tokenName(token)));
1043:
1044:                DeleteQuery query = new DeleteQuery(_database, _sql, table);
1045:                _query = query;
1046:
1047:                Expr whereExpr = null;
1048:
1049:                token = scanToken();
1050:                if (token == WHERE)
1051:                    whereExpr = parseExpr();
1052:                else if (token >= 0)
1053:                    throw error(L
1054:                            .l("expected WHERE at `{0}'", tokenName(token)));
1055:
1056:                ParamExpr[] params = _params.toArray(new ParamExpr[_params
1057:                        .size()]);
1058:
1059:                query.setParams(params);
1060:                query.setWhereExpr(whereExpr);
1061:
1062:                return query;
1063:            }
1064:
1065:            /**
1066:             * Parses the insert.
1067:             */
1068:            private Query parseDrop() throws SQLException {
1069:                int token;
1070:
1071:                if ((token = scanToken()) != TABLE)
1072:                    throw error(L
1073:                            .l("expected TABLE at `{0}'", tokenName(token)));
1074:
1075:                if ((token = scanToken()) != IDENTIFIER)
1076:                    throw error(L.l("expected identifier at `{0}'",
1077:                            tokenName(token)));
1078:
1079:                String table = _lexeme;
1080:
1081:                if ((token = scanToken()) >= 0)
1082:                    throw error(L.l("expected end of query at `{0}'",
1083:                            tokenName(token)));
1084:
1085:                return new DropQuery(_sql, _database, table);
1086:            }
1087:
1088:            /**
1089:             * Parses the select.
1090:             */
1091:            private Query parseUpdate() throws SQLException {
1092:                int token;
1093:
1094:                if ((token = scanToken()) != IDENTIFIER)
1095:                    throw error(L.l("expected identifier at `{0}'",
1096:                            tokenName(token)));
1097:
1098:                String name = _lexeme;
1099:
1100:                Table table = _database.getTable(name);
1101:
1102:                if (table == null)
1103:                    throw error(L.l("`{0}' is an unknown table in INSERT.",
1104:                            name));
1105:
1106:                if ((token = scanToken()) != SET)
1107:                    throw error(L.l("expected SET at {0}", tokenName(token)));
1108:
1109:                UpdateQuery query = new UpdateQuery(_database, _sql, table);
1110:                _query = query;
1111:
1112:                ArrayList<SetItem> setItemList = new ArrayList<SetItem>();
1113:
1114:                do {
1115:                    SetItem item = parseSetItem(table);
1116:
1117:                    setItemList.add(item);
1118:                } while ((token = scanToken()) == ',');
1119:
1120:                Expr whereExpr = null;
1121:
1122:                if (token == WHERE)
1123:                    whereExpr = parseExpr();
1124:
1125:                SetItem[] setItems = new SetItem[setItemList.size()];
1126:                setItemList.toArray(setItems);
1127:
1128:                ParamExpr[] params = _params.toArray(new ParamExpr[_params
1129:                        .size()]);
1130:
1131:                query.setSetItems(setItems);
1132:                query.setParams(params);
1133:                query.setWhereExpr(whereExpr);
1134:
1135:                return query;
1136:            }
1137:
1138:            /**
1139:             * Parses a set item.
1140:             */
1141:            private SetItem parseSetItem(Table table) throws SQLException {
1142:                int token;
1143:
1144:                if ((token = scanToken()) != IDENTIFIER)
1145:                    throw error(L.l("expected identifier at `{0}'",
1146:                            tokenName(token)));
1147:
1148:                Column column = table.getColumn(_lexeme);
1149:
1150:                if (column == null)
1151:                    throw error(L.l("`{0}' is an unknown column in table {1}.",
1152:                            _lexeme, table.getName()));
1153:
1154:                if ((token = scanToken()) != EQ)
1155:                    throw error(L.l("expected `=' at {0}", tokenName(token)));
1156:
1157:                Expr expr = parseExpr();
1158:
1159:                return new SetItem(table, column, expr);
1160:            }
1161:
1162:            /**
1163:             * Parses an expression.
1164:             */
1165:            private Expr parseExpr() throws SQLException {
1166:                int token = scanToken();
1167:
1168:                if (token == SELECT)
1169:                    return parseSubSelect();
1170:                else {
1171:                    _token = token;
1172:                    return parseOrExpr();
1173:                }
1174:            }
1175:
1176:            /**
1177:             * Parses a sub-select expression.
1178:             */
1179:            private Expr parseSubSelect() throws SQLException {
1180:                return parseSubSelect(new SelectQuery(_database, _sql));
1181:            }
1182:
1183:            /**
1184:             * Parses a sub-select expression.
1185:             */
1186:            private Expr parseSubSelect(SelectQuery query) throws SQLException {
1187:                parseSelect(query);
1188:
1189:                SubSelectExpr expr = new SubSelectExpr(query);
1190:
1191:                query.setSubSelect(expr);
1192:
1193:                _andExpr.add(new SubSelectEvalExpr(expr));
1194:
1195:                return expr;
1196:            }
1197:
1198:            /**
1199:             * Parses an OR expression.
1200:             */
1201:            private Expr parseOrExpr() throws SQLException {
1202:                Expr left = parseAndExpr();
1203:
1204:                while (true) {
1205:                    int token = scanToken();
1206:
1207:                    switch (token) {
1208:                    case OR:
1209:                        left = new OrExpr(left, parseAndExpr());
1210:                        break;
1211:
1212:                    default:
1213:                        _token = token;
1214:                        return left;
1215:                    }
1216:                }
1217:            }
1218:
1219:            /**
1220:             * Parses an AND expression.
1221:             */
1222:            private Expr parseAndExpr() throws SQLException {
1223:                AndExpr oldAndExpr = _andExpr;
1224:                AndExpr andExpr = new AndExpr();
1225:                _andExpr = andExpr;
1226:
1227:                andExpr.add(parseNotExpr());
1228:
1229:                while (true) {
1230:                    int token = scanToken();
1231:
1232:                    switch (token) {
1233:                    case AND:
1234:                        andExpr.add(parseNotExpr());
1235:                        break;
1236:
1237:                    default:
1238:                        _token = token;
1239:
1240:                        _andExpr = oldAndExpr;
1241:
1242:                        return andExpr.getSingleExpr();
1243:                    }
1244:                }
1245:            }
1246:
1247:            /**
1248:             * Parses a term.
1249:             */
1250:            private Expr parseNotExpr() throws SQLException {
1251:                int token = scanToken();
1252:
1253:                switch (token) {
1254:                case NOT:
1255:                    return new NotExpr(parseNotExpr());
1256:
1257:                default:
1258:                    _token = token;
1259:                    return parseCmpExpr();
1260:                }
1261:            }
1262:
1263:            /**
1264:             * Parses a CMP expression.
1265:             */
1266:            private Expr parseCmpExpr() throws SQLException {
1267:                Expr left = parseConcatExpr();
1268:
1269:                int token = scanToken();
1270:                boolean isNot = false;
1271:
1272:                if (token == NOT) {
1273:                    isNot = true;
1274:
1275:                    token = scanToken();
1276:
1277:                    if (token != BETWEEN && token != LIKE && token != IN) {
1278:                        _token = token;
1279:
1280:                        return left;
1281:                    }
1282:                }
1283:
1284:                switch (token) {
1285:                case EQ:
1286:                    return new EqExpr(left, parseConcatExpr());
1287:
1288:                case LT:
1289:                case LE:
1290:                case GT:
1291:                case GE:
1292:                case NE:
1293:                    return new CmpExpr(left, parseConcatExpr(), token);
1294:
1295:                case BETWEEN: {
1296:                    Expr min = parseConcatExpr();
1297:
1298:                    token = scanToken();
1299:                    if (token != AND)
1300:                        throw error(L.l("expected AND at '{0}'",
1301:                                tokenName(token)));
1302:
1303:                    Expr max = parseConcatExpr();
1304:
1305:                    return new BetweenExpr(left, min, max, isNot);
1306:                }
1307:
1308:                case IS: {
1309:                    token = scanToken();
1310:                    isNot = false;
1311:                    if (token == NOT) {
1312:                        token = scanToken();
1313:                        isNot = true;
1314:                    }
1315:
1316:                    if (token == NULL)
1317:                        return new IsNullExpr(left, isNot);
1318:                    else
1319:                        throw error(L.l("expected NULL at '{0}'",
1320:                                tokenName(token)));
1321:                }
1322:
1323:                case LIKE: {
1324:                    token = scanToken();
1325:
1326:                    if (token == STRING)
1327:                        return new LikeExpr(left, _lexeme, isNot);
1328:                    else
1329:                        throw error(L.l("expected string at '{0}'",
1330:                                tokenName(token)));
1331:                }
1332:
1333:                case IN: {
1334:                    HashSet<String> values = parseInValues();
1335:
1336:                    return new InExpr(left, values, isNot);
1337:                }
1338:
1339:                default:
1340:                    _token = token;
1341:                    return left;
1342:                }
1343:            }
1344:
1345:            /**
1346:             * Parses the IN values.
1347:             */
1348:            private HashSet<String> parseInValues() throws SQLException {
1349:                int token = scanToken();
1350:
1351:                if (token != '(')
1352:                    throw error(L.l("Expected '('"));
1353:
1354:                HashSet<String> values = new HashSet<String>();
1355:
1356:                while ((token = scanToken()) != ')') {
1357:                    if (token == STRING) {
1358:                        values.add(_lexeme);
1359:                    } else
1360:                        throw error(L.l("expected STRING at {0}",
1361:                                tokenName(token)));
1362:
1363:                    if ((token = scanToken()) != ',')
1364:                        break;
1365:                }
1366:
1367:                if (token != ')')
1368:                    throw error(L.l("expected ')' at {0}", tokenName(token)));
1369:
1370:                return values;
1371:            }
1372:
1373:            /**
1374:             * Parses a concat expression.
1375:             */
1376:            private Expr parseConcatExpr() throws SQLException {
1377:                Expr left = parseAddExpr();
1378:
1379:                while (true) {
1380:                    int token = scanToken();
1381:
1382:                    switch (token) {
1383:                    case CONCAT:
1384:                        left = new ConcatExpr(left, parseAddExpr());
1385:                        break;
1386:
1387:                    default:
1388:                        _token = token;
1389:                        return left;
1390:                    }
1391:                }
1392:            }
1393:
1394:            /**
1395:             * Parses a +/- expression.
1396:             */
1397:            private Expr parseAddExpr() throws SQLException {
1398:                Expr left = parseMulExpr();
1399:
1400:                while (true) {
1401:                    int token = scanToken();
1402:
1403:                    switch (token) {
1404:                    case '+':
1405:                    case '-':
1406:                        left = new BinaryExpr(left, parseMulExpr(), token);
1407:                        break;
1408:
1409:                    default:
1410:                        _token = token;
1411:                        return left;
1412:                    }
1413:                }
1414:            }
1415:
1416:            /**
1417:             * Parses a mul/div expression
1418:             */
1419:            private Expr parseMulExpr() throws SQLException {
1420:                Expr left = parseTerm();
1421:
1422:                while (true) {
1423:                    int token = scanToken();
1424:
1425:                    switch (token) {
1426:                    case '*':
1427:                    case '/':
1428:                    case '%':
1429:                        left = new BinaryExpr(left, parseTerm(), token);
1430:                        break;
1431:
1432:                    default:
1433:                        _token = token;
1434:                        return left;
1435:                    }
1436:                }
1437:            }
1438:
1439:            /**
1440:             * Parses a term.
1441:             */
1442:            private Expr parseTerm() throws SQLException {
1443:                int token = scanToken();
1444:
1445:                switch (token) {
1446:                case '+':
1447:                    return parseTerm();
1448:
1449:                case '-':
1450:                    return new UnaryExpr(parseTerm(), token);
1451:
1452:                case '(':
1453:                    Expr expr = parseExpr();
1454:                    int peekToken;
1455:                    if ((peekToken = scanToken()) != ')')
1456:                        throw error(L.l("expected ')' at {0}",
1457:                                tokenName(peekToken)));
1458:                    return expr;
1459:
1460:                default:
1461:                    _token = token;
1462:                    return parseSimpleTerm();
1463:                }
1464:            }
1465:
1466:            /**
1467:             * Parses a simple term.
1468:             */
1469:            private Expr parseSimpleTerm() throws SQLException {
1470:                int token = scanToken();
1471:
1472:                switch (token) {
1473:                case IDENTIFIER: {
1474:                    String name = _lexeme;
1475:
1476:                    token = scanToken();
1477:                    if (token == '.') {
1478:                        token = scanToken();
1479:
1480:                        if (token == IDENTIFIER) {
1481:                            String column = _lexeme;
1482:                            return _query.bind(name, column);
1483:                        } else if (token == '*') {
1484:                            return new UnboundStarExpr(name);
1485:                        } else
1486:                            throw error("expected IDENTIFIER");
1487:                    } else if (token == '(') {
1488:                        FunExpr fun = null;
1489:                        if (name.equalsIgnoreCase("max"))
1490:                            fun = new MaxExpr();
1491:                        else if (name.equalsIgnoreCase("min"))
1492:                            fun = new MinExpr();
1493:                        else if (name.equalsIgnoreCase("sum"))
1494:                            fun = new SumExpr();
1495:                        else if (name.equalsIgnoreCase("avg"))
1496:                            fun = new AvgExpr();
1497:                        else if (name.equalsIgnoreCase("count")) {
1498:                            fun = new CountExpr();
1499:
1500:                            token = scanToken();
1501:                            if (token == '*') {
1502:                                fun.addArg(new UnboundStarExpr());
1503:                            } else
1504:                                _token = token;
1505:                        } else if (name.equalsIgnoreCase("exists")) {
1506:                            token = scanToken();
1507:
1508:                            if (token != SELECT)
1509:                                throw error(L.l(
1510:                                        "exists requires SELECT at '{0}'",
1511:                                        tokenName(token)));
1512:
1513:                            ExistsQuery query = new ExistsQuery(_database, _sql);
1514:
1515:                            parseSelect(query);
1516:
1517:                            ExistsExpr expr = new ExistsExpr(query);
1518:
1519:                            query.setSubSelect(expr);
1520:
1521:                            _andExpr.add(new ExistsEvalExpr(expr));
1522:
1523:                            token = scanToken();
1524:
1525:                            if (token != ')')
1526:                                throw error(L.l("exists requires ')' at '{0}'",
1527:                                        tokenName(token)));
1528:
1529:                            return expr;
1530:                        } else {
1531:                            String funName = (Character.toUpperCase(name
1532:                                    .charAt(0)) + name.substring(1)
1533:                                    .toLowerCase());
1534:
1535:                            funName = "com.caucho.db.fun." + funName + "Expr";
1536:
1537:                            try {
1538:                                Class cl = Class.forName(funName);
1539:
1540:                                fun = (FunExpr) cl.newInstance();
1541:                            } catch (ClassNotFoundException e) {
1542:                                log.finer(e.toString());
1543:                            } catch (Throwable e) {
1544:                                log.log(Level.FINER, e.toString(), e);
1545:                            }
1546:
1547:                            if (fun == null)
1548:                                throw error(L.l(
1549:                                        "`{0}' is an unknown function.", name));
1550:                        }
1551:
1552:                        token = scanToken();
1553:                        while (token > 0 && token != ')') {
1554:                            _token = token;
1555:
1556:                            Expr arg = parseExpr();
1557:
1558:                            fun.addArg(arg);
1559:
1560:                            token = scanToken();
1561:
1562:                            if (token == ',')
1563:                                token = scanToken();
1564:                        }
1565:
1566:                        return fun;
1567:                    } else {
1568:                        _token = token;
1569:                        return _query.bind(null, name);
1570:                    }
1571:                }
1572:
1573:                case STRING:
1574:                    return new StringExpr(_lexeme);
1575:
1576:                case DOUBLE:
1577:                case INTEGER:
1578:                case LONG:
1579:                    return NumberExpr.create(_lexeme);
1580:
1581:                case NULL:
1582:                    return new NullExpr();
1583:
1584:                case TRUE:
1585:                    return BooleanLiteralExpr.create(true);
1586:
1587:                case FALSE:
1588:                    return BooleanLiteralExpr.create(false);
1589:
1590:                case '?':
1591:                    ParamExpr param = new ParamExpr(_params.size());
1592:                    _params.add(param);
1593:                    return param;
1594:
1595:                default:
1596:                    throw error(L.l("unexpected term {0}", tokenName(token)));
1597:                }
1598:            }
1599:
1600:            /**
1601:             * Parses an identifier.
1602:             */
1603:            private String parseIdentifier() throws SQLException {
1604:                int token = scanToken();
1605:
1606:                if (token != IDENTIFIER)
1607:                    throw error(L.l("expected identifier at {0}",
1608:                            tokenName(token)));
1609:
1610:                return _lexeme;
1611:            }
1612:
1613:            /**
1614:             * Scan the next token.  If the lexeme is a string, its string
1615:             * representation is in "lexeme".
1616:             *
1617:             * @return integer code for the token
1618:             */
1619:            private int scanToken() throws SQLException {
1620:                if (_token > 0) {
1621:                    int value = _token;
1622:                    _token = -1;
1623:                    return value;
1624:                }
1625:
1626:                int sign = 1;
1627:                int ch;
1628:
1629:                for (ch = read(); Character.isWhitespace((char) ch); ch = read()) {
1630:                }
1631:
1632:                switch (ch) {
1633:                case -1:
1634:                case '(':
1635:                case ')':
1636:                case '.':
1637:                case '*':
1638:                case '/':
1639:                case '%':
1640:                case ',':
1641:                case '?':
1642:                    return ch;
1643:
1644:                case '+':
1645:                    if ((ch = read()) >= '0' && ch <= '9')
1646:                        break;
1647:                    else {
1648:                        unread(ch);
1649:                        return '+';
1650:                    }
1651:
1652:                case '-':
1653:                    if ((ch = read()) >= '0' && ch <= '9') {
1654:                        sign = -1;
1655:                        break;
1656:                    } else {
1657:                        unread(ch);
1658:                        return '-';
1659:                    }
1660:
1661:                case '=':
1662:                    return EQ;
1663:
1664:                case '<':
1665:                    if ((ch = read()) == '=')
1666:                        return LE;
1667:                    else if (ch == '>')
1668:                        return NE;
1669:                    else {
1670:                        unread(ch);
1671:                        return LT;
1672:                    }
1673:
1674:                case '>':
1675:                    if ((ch = read()) == '=')
1676:                        return GE;
1677:                    else {
1678:                        unread(ch);
1679:                        return GT;
1680:                    }
1681:
1682:                case '|':
1683:                    if ((ch = read()) == '|')
1684:                        return CONCAT;
1685:                    else {
1686:                        throw error(L.l("'|' expected at {0}", charName(ch)));
1687:                    }
1688:
1689:                    // @@ is useless?
1690:                case '@':
1691:                    if ((ch = read()) != '@')
1692:                        throw error(L.l("`@' expected at {0}", charName(ch)));
1693:                    return scanToken();
1694:                }
1695:
1696:                if (Character.isJavaIdentifierStart((char) ch)) {
1697:                    CharBuffer cb = _cb;
1698:                    cb.clear();
1699:
1700:                    for (; ch > 0 && Character.isJavaIdentifierPart((char) ch); ch = read())
1701:                        cb.append((char) ch);
1702:
1703:                    unread(ch);
1704:
1705:                    _lexeme = cb.toString();
1706:                    String lower = _lexeme.toLowerCase();
1707:
1708:                    int token = _reserved.get(lower);
1709:
1710:                    if (token > 0)
1711:                        return token;
1712:                    else
1713:                        return IDENTIFIER;
1714:                } else if (ch >= '0' && ch <= '9') {
1715:                    CharBuffer cb = _cb;
1716:                    cb.clear();
1717:
1718:                    int type = INTEGER;
1719:
1720:                    if (sign < 0)
1721:                        cb.append('-');
1722:
1723:                    for (; ch >= '0' && ch <= '9'; ch = read())
1724:                        cb.append((char) ch);
1725:
1726:                    if (ch == '.') {
1727:                        type = DOUBLE;
1728:
1729:                        cb.append('.');
1730:                        for (ch = read(); ch >= '0' && ch <= '9'; ch = read())
1731:                            cb.append((char) ch);
1732:                    }
1733:
1734:                    if (ch == 'e' || ch == 'E') {
1735:                        type = DOUBLE;
1736:
1737:                        cb.append('e');
1738:                        if ((ch = read()) == '+' || ch == '-') {
1739:                            cb.append((char) ch);
1740:                            ch = read();
1741:                        }
1742:
1743:                        if (!(ch >= '0' && ch <= '9'))
1744:                            throw error(L.l("exponent needs digits at {0}",
1745:                                    charName(ch)));
1746:
1747:                        for (; ch >= '0' && ch <= '9'; ch = read())
1748:                            cb.append((char) ch);
1749:                    }
1750:
1751:                    if (ch == 'F' || ch == 'D')
1752:                        type = DOUBLE;
1753:                    else if (ch == 'L') {
1754:                        type = LONG;
1755:                    } else
1756:                        unread(ch);
1757:
1758:                    _lexeme = cb.toString();
1759:
1760:                    return type;
1761:                } else if (ch == '\'') {
1762:                    CharBuffer cb = _cb;
1763:                    cb.clear();
1764:
1765:                    for (ch = read(); ch >= 0; ch = read()) {
1766:                        if (ch == '\'') {
1767:                            if ((ch = read()) == '\'')
1768:                                cb.append('\'');
1769:                            else {
1770:                                unread(ch);
1771:                                break;
1772:                            }
1773:                        } else if (ch == '\\') {
1774:                            ch = read();
1775:
1776:                            if (ch >= 0)
1777:                                cb.append(ch);
1778:                        } else
1779:                            cb.append((char) ch);
1780:                    }
1781:
1782:                    _lexeme = cb.toString();
1783:
1784:                    return STRING;
1785:                } else if (ch == '#') {
1786:                    // skip comment
1787:                    while ((ch = read()) >= 0 && ch != '\n' && ch != '\r') {
1788:                    }
1789:
1790:                    // XXX: cleanup to avoid recursion
1791:                    return scanToken();
1792:                }
1793:
1794:                throw error(L.l("unexpected char at {0} ({1})", "" + (char) ch,
1795:                        String.valueOf(ch)));
1796:            }
1797:
1798:            /**
1799:             * Returns the next character.
1800:             */
1801:            private int read() {
1802:                if (_parseIndex < _sqlLength)
1803:                    return _sqlChars[_parseIndex++];
1804:                else
1805:                    return -1;
1806:            }
1807:
1808:            /**
1809:             * Unread the last character.
1810:             */
1811:            private void unread(int ch) {
1812:                if (ch >= 0)
1813:                    _parseIndex--;
1814:            }
1815:
1816:            /**
1817:             * Returns the name for a character
1818:             */
1819:            private String charName(int ch) {
1820:                if (ch < 0)
1821:                    return L.l("end of query");
1822:                else
1823:                    return String.valueOf((char) ch);
1824:            }
1825:
1826:            /**
1827:             * Returns the name of a token
1828:             */
1829:            private String tokenName(int token) {
1830:                switch (token) {
1831:                case AS:
1832:                    return "AS";
1833:                case ARG:
1834:                    return "?";
1835:                case FROM:
1836:                    return "FROM";
1837:                case IN:
1838:                    return "IN";
1839:                case SELECT:
1840:                    return "SELECT";
1841:                case WHERE:
1842:                    return "WHERE";
1843:                case OR:
1844:                    return "OR";
1845:                case AND:
1846:                    return "AND";
1847:                case NOT:
1848:                    return "NOT";
1849:                case BETWEEN:
1850:                    return "BETWEEN";
1851:                case TRUE:
1852:                    return "TRUE";
1853:                case FALSE:
1854:                    return "FALSE";
1855:                case NULL:
1856:                    return "NULL";
1857:                case GROUP:
1858:                    return "GROUP";
1859:                case ORDER:
1860:                    return "ORDER";
1861:                case BY:
1862:                    return "BY";
1863:                case ASC:
1864:                    return "ASC";
1865:                case DESC:
1866:                    return "DESC";
1867:                case LIMIT:
1868:                    return "LIMIT";
1869:
1870:                case -1:
1871:                    return L.l("end of query");
1872:
1873:                default:
1874:                    if (token < 128)
1875:                        return "'" + String.valueOf((char) token) + "'";
1876:                    else
1877:                        return "'" + _lexeme + "'";
1878:                }
1879:            }
1880:
1881:            private SQLException error(String msg) {
1882:                return new SQLParseException(msg + "\n" + _sql);
1883:            }
1884:
1885:            static {
1886:                _reserved = new IntMap();
1887:                _reserved.put("as", AS);
1888:                _reserved.put("from", FROM);
1889:                _reserved.put("in", IN);
1890:                _reserved.put("select", SELECT);
1891:                _reserved.put("distinct", DISTINCT);
1892:                _reserved.put("where", WHERE);
1893:                _reserved.put("order", ORDER);
1894:                _reserved.put("group", GROUP);
1895:                _reserved.put("by", BY);
1896:                _reserved.put("asc", ASC);
1897:                _reserved.put("desc", DESC);
1898:                _reserved.put("limit", LIMIT);
1899:                _reserved.put("offset", OFFSET);
1900:
1901:                _reserved.put("or", OR);
1902:                _reserved.put("and", AND);
1903:                _reserved.put("not", NOT);
1904:
1905:                _reserved.put("between", BETWEEN);
1906:                _reserved.put("like", LIKE);
1907:                _reserved.put("escape", ESCAPE);
1908:                _reserved.put("is", IS);
1909:
1910:                _reserved.put("true", TRUE);
1911:                _reserved.put("false", FALSE);
1912:                _reserved.put("unknown", UNKNOWN);
1913:                _reserved.put("null", NULL);
1914:
1915:                _reserved.put("create", CREATE);
1916:                _reserved.put("table", TABLE);
1917:                _reserved.put("insert", INSERT);
1918:                _reserved.put("into", INTO);
1919:                _reserved.put("values", VALUES);
1920:                _reserved.put("drop", DROP);
1921:                _reserved.put("update", UPDATE);
1922:                _reserved.put("set", SET);
1923:                _reserved.put("delete", DELETE);
1924:
1925:                _reserved.put("constraint", CONSTRAINT);
1926:                _reserved.put("unique", UNIQUE);
1927:                _reserved.put("check", CHECK);
1928:                _reserved.put("primary", PRIMARY);
1929:                _reserved.put("key", KEY);
1930:                _reserved.put("foreign", FOREIGN);
1931:            }
1932:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.