⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.java

📁 Java写的含有一个jdbc驱动的小型数据库数据库引擎
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Parser.java
 *
 * Copyright (c) 2001, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This package is based on HypersonicSQL, originally developed by Thomas Mueller.
 *
 */
package org.hsqldb;

import java.util.*;
import java.sql.*;

/**
 * Class declaration
 *
 *
 * @version 1.0.0.1
 */
class Parser {
    private Database  dDatabase;
    private Tokenizer tTokenizer;
    private Channel   cChannel;
    private String    sTable;
    private String    sToken;
    private Object    oData;
    private int       iType;
    private int       iToken;

    /**
     * Constructor declaration
     *
     *
     * @param db
     * @param t
     * @param channel
     */
    Parser(Database db, Tokenizer t, Channel channel) {
	dDatabase = db;
	tTokenizer = t;
	cChannel = channel;
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    Result processSelect() throws SQLException {
	Select select = parseSelect();

	if (select.sIntoTable == null) {
// fredt@users.sourceforge.net begin changes from 1.50
//	   return select.getResult(cChannel.getMaxRows());
      return select.getResult( select.limitStart, select.limitCount );
// fredt@users.sourceforge.net end changes from 1.50
	} else {
	    Result r = select.getResult(0);
	    Table  t = new Table(dDatabase, true, select.sIntoTable, false);

	    t.addColumns(r);
	    t.createPrimaryKey();

	    // SELECT .. INTO can't fail because of violation of primary key
	    t.insert(r, cChannel);
	    dDatabase.linkTable(t);

	    int i = r.getSize();

	    r = new Result();
	    r.iUpdateCount = i;

	    return r;
	}
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    Result processCall() throws SQLException {
	Expression e = parseExpression();

	e.resolve(null);

	int    type = e.getDataType();
	Object o = e.getValue();
	Result r = new Result(1);

	r.sTable[0] = "";
	r.iType[0] = type;
	r.sLabel[0] = "";
	r.sName[0] = "";

	Object row[] = new Object[1];

	row[0] = o;

	r.add(row);

	return r;
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    Result processUpdate() throws SQLException {
	String token = tTokenizer.getString();

	cChannel.checkReadWrite();
	cChannel.check(token, Access.UPDATE);

	Table       table = dDatabase.getTable(token, cChannel);
	TableFilter filter = new TableFilter(table, null, false);

	tTokenizer.getThis("SET");

	Vector vColumn = new Vector();
	Vector eColumn = new Vector();
	int    len = 0;

	token = null;

	do {
	    len++;

	    int i = table.getColumnNr(tTokenizer.getString());

	    vColumn.addElement(new Integer(i));
	    tTokenizer.getThis("=");

	    Expression e = parseExpression();

	    e.resolve(filter);
	    eColumn.addElement(e);

	    token = tTokenizer.getString();
	} while (token.equals(","));

	Expression eCondition = null;

	if (token.equals("WHERE")) {
	    eCondition = parseExpression();

	    eCondition.resolve(filter);
	    filter.setCondition(eCondition);
	} else {
	    tTokenizer.back();
	}

	// do the update
	table.fireAll(TriggerDef.UPDATE_BEFORE);

	Expression exp[] = new Expression[len];

	eColumn.copyInto(exp);

	int col[] = new int[len];
	int type[] = new int[len];

	for (int i = 0; i < len; i++) {
	    col[i] = ((Integer) vColumn.elementAt(i)).intValue();
	    type[i] = table.getType(col[i]);
	}

	int count = 0;

	if (filter.findFirst()) {
	    Result del = new Result();    // don't need column count and so on
	    Result ins = new Result();
	    int    size = table.getColumnCount();

	    do {
		if (eCondition == null || eCondition.test()) {
		    Object nd[] = filter.oCurrentData;

		    del.add(nd);

		    Object ni[] = table.getNewRow();

		    for (int i = 0; i < size; i++) {
			ni[i] = nd[i];
		    }

		    for (int i = 0; i < len; i++) {
			ni[col[i]] = exp[i].getValue(type[i]);
		    }

		    ins.add(ni);
		}
	    } while (filter.next());

	    cChannel.beginNestedTransaction();

	    try {
		Record nd = del.rRoot;

		while (nd != null) {
		    table.fireAll(TriggerDef.UPDATE_BEFORE_ROW, nd.data);
		    table.deleteNoCheck(nd.data, cChannel);

		    nd = nd.next;
		}

		Record ni = ins.rRoot;

		while (ni != null) {
		    table.insertNoCheck(ni.data, cChannel);

		    ni = ni.next;
		    count++;
		}

		table.checkUpdate(col, del, ins);

		ni = ins.rRoot;

		while (ni
		       != null) {    // fire triggers now that update has been checked
		    table.fireAll(TriggerDef.UPDATE_AFTER_ROW, ni.data);

		    ni = ni.next;
		}

		cChannel.endNestedTransaction(false);
	    } catch (SQLException e) {

		// update failed (violation of primary key / referential integrity)
		cChannel.endNestedTransaction(true);

		throw e;
	    }
	}

	table.fireAll(TriggerDef.UPDATE_AFTER);

	Result r = new Result();

	r.iUpdateCount = count;

	return r;
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    Result processDelete() throws SQLException {
	tTokenizer.getThis("FROM");

	String token = tTokenizer.getString();

	cChannel.checkReadWrite();
	cChannel.check(token, Access.DELETE);

	Table       table = dDatabase.getTable(token, cChannel);
	TableFilter filter = new TableFilter(table, null, false);

	token = tTokenizer.getString();

	Expression eCondition = null;

	if (token.equals("WHERE")) {
	    eCondition = parseExpression();

	    eCondition.resolve(filter);
	    filter.setCondition(eCondition);
	} else {
	    tTokenizer.back();
	}

	table.fireAll(TriggerDef.DELETE_BEFORE);

	int count = 0;

	if (filter.findFirst()) {
	    Result del = new Result();    // don't need column count and so on

	    do {
		if (eCondition == null || eCondition.test()) {
		    del.add(filter.oCurrentData);
		}
	    } while (filter.next());

	    Record n = del.rRoot;

	    while (n != null) {
		table.delete(n.data, cChannel);

		count++;
		n = n.next;
	    }
	}

	table.fireAll(TriggerDef.DELETE_AFTER);

	Result r = new Result();

	r.iUpdateCount = count;

	return r;
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    Result processInsert() throws SQLException {
	tTokenizer.getThis("INTO");

	String token = tTokenizer.getString();

	cChannel.checkReadWrite();
	cChannel.check(token, Access.INSERT);

	Table t = dDatabase.getTable(token, cChannel);

	token = tTokenizer.getString();

	Vector vcolumns = null;

	if (token.equals("(")) {
	    vcolumns = new Vector();

	    int i = 0;

	    while (true) {
		vcolumns.addElement(tTokenizer.getString());

		i++;
		token = tTokenizer.getString();

		if (token.equals(")")) {
		    break;
		}

		if (!token.equals(",")) {
		    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
		}
	    }

	    token = tTokenizer.getString();
	}

	int count = 0;
	int len;

	if (vcolumns == null) {
	    len = t.getColumnCount();
	} else {
	    len = vcolumns.size();
	}

	if (token.equals("VALUES")) {
	    tTokenizer.getThis("(");

	    Object row[] = t.getNewRow();
	    int    i = 0;

	    while (true) {
		int column;

		if (vcolumns == null) {
		    column = i;

		    if (i > len) {
			throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH);
		    }
		} else {
		    column = t.getColumnNr((String) vcolumns.elementAt(i));
		}

		row[column] = getValue(t.getType(column));
		i++;
		token = tTokenizer.getString();

		if (token.equals(")")) {
		    break;
		}

		if (!token.equals(",")) {
		    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
		}
	    }

	    t.insert(row, cChannel);

	    count = 1;
	} else if (token.equals("SELECT")) {
	    Result result = processSelect();
	    Record r = result.rRoot;

	    Trace.check(len == result.getColumnCount(),
			Trace.COLUMN_COUNT_DOES_NOT_MATCH);

	    int col[] = new int[len];
	    int type[] = new int[len];

	    for (int i = 0; i < len; i++) {
		int j;

		if (vcolumns == null) {
		    j = i;
		} else {
		    j = t.getColumnNr((String) vcolumns.elementAt(i));
		}

		col[i] = j;
		type[i] = t.getType(j);
	    }

	    cChannel.beginNestedTransaction();

	    try {
		while (r != null) {
		    Object row[] = t.getNewRow();

		    for (int i = 0; i < len; i++) {
			row[col[i]] = Column.convertObject(r.data[i],
							   type[i]);
		    }

		    t.insert(row, cChannel);

		    count++;
		    r = r.next;
		}

		cChannel.endNestedTransaction(false);
	    } catch (SQLException e) {

		// insert failed (violation of primary key)
		cChannel.endNestedTransaction(true);

		throw e;
	    }
	} else {
	    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
	}

	Result r = new Result();

	r.iUpdateCount = count;

	return r;
    }

    /**
     * Method declaration
     *
     *
     * @return
     *
     * @throws SQLException
     */
    private Select parseSelect() throws SQLException {
	Select select = new Select();
// fredt@users.sourceforge.net begin changes from 1.50
   select.limitStart = 0;
   select.limitCount = cChannel.getMaxRows();
// fredt@users.sourceforge.net end changes from 1.50
	String token = tTokenizer.getString();

	if (token.equals("DISTINCT")) {
	    select.bDistinct = true;
// fredt@users.sourceforge.net begin changes from 1.50
 	} else if( token.equals("LIMIT")) {
 		String limStart = tTokenizer.getString();
 		String limEnd = tTokenizer.getString();
 		//System.out.println( "LIMIT used from "+limStart+","+limEnd);
 		select.limitStart = new Integer(limStart).intValue();
 		select.limitCount = new Integer(limEnd).intValue();
// fredt@users.sourceforge.net end changes from 1.50
	} else {
	    tTokenizer.back();
	}

	// parse column list
	Vector vcolumn = new Vector();

	do {
	    Expression e = parseExpression();

	    token = tTokenizer.getString();

	    if (token.equals("AS")) {
		e.setAlias(tTokenizer.getName());

		token = tTokenizer.getString();
	    } else if (tTokenizer.wasName()) {
		e.setAlias(token);

		token = tTokenizer.getString();
	    }

	    vcolumn.addElement(e);
	} while (token.equals(","));

	if (token.equals("INTO")) {
	    select.sIntoTable = tTokenizer.getString();
	    token = tTokenizer.getString();
	}

	if (!token.equals("FROM")) {
	    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
	}

	Expression condition = null;

	// parse table list
	Vector     vfilter = new Vector();

	vfilter.addElement(parseTableFilter(false));

	while (true) {
	    token = tTokenizer.getString();

	    if (token.equals("LEFT")) {
		token = tTokenizer.getString();

		if (token.equals("OUTER")) {
		    token = tTokenizer.getString();
		}

		Trace.check(token.equals("JOIN"), Trace.UNEXPECTED_TOKEN,
			    token);
		vfilter.addElement(parseTableFilter(true));
		tTokenizer.getThis("ON");

		condition = addCondition(condition, parseExpression());
	    } else if (token.equals("INNER")) {
		tTokenizer.getThis("JOIN");
		vfilter.addElement(parseTableFilter(false));
		tTokenizer.getThis("ON");

		condition = addCondition(condition, parseExpression());
	    } else if (token.equals(",")) {
		vfilter.addElement(parseTableFilter(false));
	    } else {
		break;
	    }
	}

	tTokenizer.back();

	int	    len = vfilter.size();
	TableFilter filter[] = new TableFilter[len];

	vfilter.copyInto(filter);

	select.tFilter = filter;

	// expand [table.]* columns
	len = vcolumn.size();

	for (int i = 0; i < len; i++) {
	    Expression e = (Expression) (vcolumn.elementAt(i));

	    if (e.getType() == Expression.ASTERIX) {
		int    current = i;
		Table  table = null;
		String n = e.getTableName();

		for (int t = 0; t < filter.length; t++) {
		    TableFilter f = filter[t];

		    e.resolve(f);

		    if (n != null &&!n.equals(f.getName())) {
			continue;
		    }

		    table = f.getTable();

		    int col = table.getColumnCount();

		    for (int c = 0; c < col; c++) {
			Expression ins =
			    new Expression(f.getName(),
					   table.getColumnName(c));

			vcolumn.insertElementAt(ins, current++);

			// now there is one element more to parse
			len++;
		    }
		}

		Trace.check(table != null, Trace.TABLE_NOT_FOUND, n);

		// minus the asterix element
		len--;

		vcolumn.removeElementAt(current);
	    }
	  	else if (e.getType()==Expression.COLUMN){
			if (e.getTableName() == null) {
				for (int filterIndex=0; filterIndex < filter.length; filterIndex++) {
					e.resolve(filter[filterIndex]);
				}
			}
		}
	}

	select.iResultLen = len;

	// where
	token = tTokenizer.getString();

	if (token.equals("WHERE")) {
	    condition = addCondition(condition, parseExpression());
	    token = tTokenizer.getString();
	}

	select.eCondition = condition;

	if (token.equals("GROUP")) {
	    tTokenizer.getThis("BY");

	    len = 0;

	    do {
		vcolumn.addElement(parseExpression());

		token = tTokenizer.getString();
		len++;
	    } while (token.equals(","));

	    select.iGroupLen = len;
	}

	if (token.equals("ORDER")) {
	    tTokenizer.getThis("BY");

	    len = 0;

	    do {
		Expression e = parseExpression();

		if (e.getType() == Expression.VALUE) {

		    // order by 1,2,3
		    if (e.getDataType() == Column.INTEGER) {
			int i = ((Integer) e.getValue()).intValue();

			e = (Expression) vcolumn.elementAt(i - 1);
		    }
		} else if (e.getType() == Expression.COLUMN
			   && e.getTableName() == null) {

		    // this could be an alias column
		    String s = e.getColumnName();

		    for (int i = 0; i < vcolumn.size(); i++) {
			Expression ec = (Expression) vcolumn.elementAt(i);

			if (s.equals(ec.getAlias())) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -