queryparser.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,704 行 · 第 1/5 页
JAVA
2,704 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.amber.query;import com.caucho.amber.AmberException;import com.caucho.amber.entity.AmberEntityHome;import com.caucho.amber.expr.*;import com.caucho.amber.expr.fun.*;import com.caucho.amber.manager.AmberPersistenceUnit;import com.caucho.amber.table.ForeignColumn;import com.caucho.amber.table.LinkColumns;import com.caucho.amber.table.AmberTable;import com.caucho.amber.type.EntityType;import com.caucho.amber.type.EntityType;import com.caucho.amber.type.AmberType;import com.caucho.jdbc.JdbcMetaData;import com.caucho.log.Log;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import com.caucho.util.L10N;import javax.sql.DataSource;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import java.util.logging.Level;import java.util.logging.Logger;/** * Contains the parser for EJB 3.0 style queries and stores * the parsed expressions. */public class QueryParser { static final Logger log = Log.open(QueryParser.class); static final L10N L = new L10N(QueryParser.class); public final static int IDENTIFIER = 128; public final static int INTEGER = IDENTIFIER + 1; public final static int LONG = INTEGER + 1; public final static int DOUBLE = LONG + 1; public final static int STRING = DOUBLE + 1; public final static int TRUE = STRING + 1; public final static int FALSE = TRUE + 1; public final static int UNKNOWN = FALSE + 1; public final static int MEMBER = UNKNOWN + 1; public final static int OF = MEMBER + 1; public final static int EMPTY = OF + 1; public final static int NULL = EMPTY + 1; public final static int FROM = NULL + 1; public final static int IN = FROM + 1; public final static int SELECT = IN + 1; public final static int UPDATE = SELECT + 1; public final static int DELETE = UPDATE + 1; public final static int DISTINCT = DELETE + 1; public final static int WHERE = DISTINCT + 1; public final static int AS = WHERE + 1; public final static int SET = AS + 1; public final static int ORDER = SET + 1; public final static int GROUP = ORDER + 1; public final static int BY = GROUP + 1; public final static int ASC = BY + 1; public final static int DESC = ASC + 1; public final static int LIMIT = DESC + 1; public final static int OFFSET = LIMIT + 1; public final static int JOIN = OFFSET + 1; public final static int INNER = JOIN + 1; public final static int LEFT = INNER + 1; public final static int OUTER = LEFT + 1; public final static int FETCH = OUTER + 1; public final static int BETWEEN = FETCH + 1; public final static int LIKE = BETWEEN + 1; public final static int ESCAPE = LIKE + 1; public final static int IS = ESCAPE + 1; public final static int CONCAT_OP = IS + 1; public final static int EQ = CONCAT_OP + 1; public final static int NE = EQ + 1; public final static int LT = NE + 1; public final static int LE = LT + 1; public final static int GT = LE + 1; public final static int GE = GT + 1; public final static int AND = GE + 1; public final static int OR = AND + 1; public final static int NOT = OR + 1; public final static int LENGTH = NOT + 1; public final static int LOCATE = LENGTH + 1; public final static int ABS = LOCATE + 1; public final static int SQRT = ABS + 1; public final static int MOD = SQRT + 1; public final static int SIZE = MOD + 1; public final static int MAX = SIZE + 1; public final static int MIN = MAX + 1; public final static int SUM = MIN + 1; public final static int CONCAT = SUM + 1; public final static int LOWER = CONCAT + 1; public final static int UPPER = LOWER + 1; public final static int SUBSTRING = UPPER + 1; public final static int TRIM = SUBSTRING + 1; public final static int BOTH = TRIM + 1; public final static int LEADING = BOTH + 1; public final static int TRAILING = LEADING + 1; public final static int CURRENT_DATE = TRAILING + 1; public final static int CURRENT_TIME = CURRENT_DATE + 1; public final static int CURRENT_TIMESTAMP = CURRENT_TIME + 1; public final static int EXTERNAL_DOT = CURRENT_TIMESTAMP + 1; public final static int ARG = EXTERNAL_DOT + 1; public final static int NAMED_ARG = ARG + 1; public final static int NEW = NAMED_ARG + 1; public final static int THIS = NEW + 1; public final static int NOT_NULL = THIS + 1; public final static int HAVING = NOT_NULL + 1; private static IntMap _reserved; private AmberPersistenceUnit _persistenceUnit; // The query private String _sql; /* // list of the relation links private ArrayList<LinkItem> _linkList; // select expression private Expr _selectExpr; // is distinct (set) private boolean _isDistinct; */ // True if entities should be lazily loaded private boolean _isLazyResult; // The select query private AbstractQuery _query; // list of relations private HashMap<PathExpr,PathExpr> _pathMap = new HashMap<PathExpr,PathExpr>(); // parse index private int _parseIndex; // current token private int _token; // unique private int _unique; // parameter count private int _parameterCount; // temp for parsing private String _lexeme; private ArrayList<ArgExpr> _argList = new ArrayList<ArgExpr>(); private HashMap<AmberExpr, String> _joinFetchMap; ArrayList<AmberExpr> _groupList = null; private int _sqlArgCount; private FromItem.JoinSemantics _joinSemantics = FromItem.JoinSemantics.UNKNOWN; private boolean _isJoinFetch = false; // Parsing control variable, jpa/0tp4 (TRIM FROM) // SELECT .._depth=0.. TRIM(.._depth=1.. 'a' FROM o.d1) .._depth=0 FROM ... private int _depth = 0; private boolean _parsingResult; private boolean _parsingFrom; private boolean _parsingHaving; // jpa/119l: WHERE SIZE(xxx) > 0 => GROUP BY ... HAVING COUNT(xxx) > 0 private boolean _isSizeFunExpr; private AmberExpr _havingExpr; // jpa/1199 ArrayList<AmberExpr> _appendResultList = null; private boolean _isDerbyDBMS; private boolean _isPostgresDBMS; /** * Creates the query parser. */ public QueryParser(String query) { _sql = query; } /** * Returns true for Derby-like DBMS. */ public boolean isDerbyDBMS() { return _isDerbyDBMS; } /** * Returns true for Postgres-like DBMS. */ public boolean isPostgresDBMS() { return _isPostgresDBMS; } /** * Sets the persistence unit. */ public void setPersistenceUnit(AmberPersistenceUnit persistenceUnit) { _persistenceUnit = persistenceUnit; _isDerbyDBMS = false; _isPostgresDBMS = false; if (persistenceUnit == null) return; _isDerbyDBMS = ! persistenceUnit.hasPositionFunction(); _isPostgresDBMS = persistenceUnit.getFalseLiteral().equalsIgnoreCase("false"); } /** * Sets true for lazy loading. */ public void setLazyResult(boolean isLazy) { _isLazyResult = isLazy; } /** * Returns the query string */ public String getQuery() { return _sql; } /** * Returns the query string */ public AbstractQuery getSelectQuery() { return _query; } /** * Initialize the parse. */ private void init() { _parseIndex = 0; _unique = 0; _token = -1; _depth = 0; _parsingResult = false; _parsingFrom = false; _parsingHaving = false; _havingExpr = null; _appendResultList = null; _groupList = null; _joinFetchMap = new HashMap<AmberExpr, String>(); } /** * Generates a new arg. */ public int generateSQLArg() { return _sqlArgCount++; } /** * Parses the query. */ public AbstractQuery parse() throws AmberException { /* _query = query; _fromList = new ArrayList<FromItem>(); _pathMap = new HashMap<Expr,Expr>(); _idMap = new HashMap<String,PathExpr>(); _argList = new ArrayList<Expr>(); _linkList = new ArrayList<LinkItem>(); */ init(); int token = scanToken(); if (token == UPDATE) return parseUpdate(); else if (token == DELETE) return parseDelete(); _token = token; return parseSelect(false); } private SelectQuery parseSelect(boolean innerSelect) throws QueryParseException { int oldParseIndex = _parseIndex; int oldToken = _token; FromItem.JoinSemantics oldJoinSemantics = _joinSemantics; boolean oldIsJoinFetch = _isJoinFetch; AbstractQuery oldQuery = _query; int oldDepth = _depth; AmberExpr oldHavingExpr = _havingExpr; ArrayList oldAppendResultList = _appendResultList; // Reset depth: subselect _depth = 0; _havingExpr = null; _appendResultList = null; SelectQuery query = new SelectQuery(_sql, getMetaData()); query.setParentQuery(_query); _query = query; int token; while ((token = scanToken()) >= 0 && ((token != FROM) || (_depth > 0))) { } // "SELECT CURRENT_DATE" does NOT have a FROM clause. boolean hasFrom = (token == FROM); _token = token; if (hasFrom) { _parsingFrom = true; do { scanToken(); _isJoinFetch = false; if (token == JOIN) { if ((token = peekToken()) == FETCH) { scanToken(); _isJoinFetch = true; } } FromItem from = parseFrom(); token = peekToken(); _joinSemantics = FromItem.JoinSemantics.UNKNOWN; if (token == INNER) { scanToken(); token = peekToken(); if (token != JOIN) { throw error(L.l("expected JOIN at {0}", tokenName(token))); } _joinSemantics = FromItem.JoinSemantics.INNER; } else if (token == LEFT) { scanToken(); token = peekToken(); if (token == OUTER) { scanToken(); token = peekToken(); } if (token != JOIN) throw error(L.l("expected JOIN at {0}", tokenName(token))); _joinSemantics = FromItem.JoinSemantics.OUTER; } else if (token == JOIN) { _joinSemantics = FromItem.JoinSemantics.INNER; } } while ((token == ',') || (token == JOIN)); _parsingFrom = false; } int fromParseIndex = _parseIndex; int fromToken = _token; _parseIndex = oldParseIndex; _token = oldToken; ArrayList<AmberExpr> resultList = new ArrayList<AmberExpr>(); _parsingResult = true; if (peekToken() == SELECT) { scanToken(); if (peekToken() == DISTINCT) { scanToken(); query.setDistinct(true); } String constructorName = null; if (peekToken() == NEW) { scanToken(); // Scans the fully qualified constructor String s = ""; boolean isDot = false; while ((token = scanToken()) != '(') { if (! isDot) { s += _lexeme; isDot = true; } else if (token == '.') { s += '.'; isDot = false; } else throw error(L.l("Constructor with SELECT NEW must be fully qualified. Expected '.' at {0}", tokenName(token))); } constructorName = s; } do { AmberExpr expr = parseExpr(); if (! hasFrom) { if (! (expr instanceof DateTimeFunExpr)) throw error(L.l("expected FROM clause when the select clause has not date/time functions only")); } else { // jpa/1199 if (expr == null) continue; expr = expr.bindSelect(this); if (_isLazyResult) { } else if (expr instanceof PathExpr) { PathExpr pathExpr = (PathExpr) expr; FromItem rootItem = null; AmberType targetType = pathExpr.getTargetType(); // jpa/0w24 if (targetType instanceof EntityType) { EntityType relatedType = (EntityType) targetType; EntityType parentType = relatedType; while (parentType.getParentType() != null) { if (parentType.getParentType() instanceof EntityType) parentType = parentType.getParentType(); else break; } // jpa/0l4b if (parentType != relatedType) { FromItem child = pathExpr.getChildFromItem(); AmberTable table = relatedType.getTable(); // parentType.getTable(); ArrayList<LinkColumns> outgoingLinks = table.getOutgoingLinks(); for (LinkColumns link : outgoingLinks) { if (link.getTargetTable().equals(parentType.getTable())) { rootItem = addFromItem((EntityType) parentType, parentType.getTable()); JoinExpr join = new ManyToOneJoinExpr(link, rootItem, child); rootItem.setJoinExpr(join); rootItem.setJoinSemantics(FromItem.JoinSemantics.INNER); break; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?