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 + -
显示快捷键?