Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31022
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 91
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-19 20:11
文章分类

全部博文(6)

文章存档

2016年(1)

2014年(5)

我的朋友

分类: Java

2014-10-25 20:11:28

说完Scanner/Token的部分,我们再回头来看compilePart之前被我们忽略掉的100多行的代码。

点击(此处)折叠或打开

  1. switch (token.tokenType) {
  2.  
  3.             // DQL
  4.             case Tokens.WITH :
  5.             case Tokens.OPENBRACKET :
  6.             case Tokens.SELECT :
  7.             case Tokens.TABLE : {
  8.                 cs = compileCursorSpecification(RangeGroup.emptyArray, props,
  9.                                                 false);
  10.  
  11.                 break;
  12.             }
  13.             case Tokens.VALUES : {
  14.                 RangeGroup[] ranges =
  15.                     session.sessionContext.sessionVariableRangeGroups;
  16.  
  17.                 compileContext.setOuterRanges(ranges);
  18.  
  19.                 cs = compileShortCursorSpecification(props);
  20.  
  21.                 break;
  22.             }
  23.  
  24.             // DML
  25.             case Tokens.INSERT : {
  26.                 cs = compileInsertStatement(RangeGroup.emptyArray);
  27.  
  28.                 break;
  29.             }
  30.             case Tokens.UPDATE : {
  31.                 cs = compileUpdateStatement(RangeGroup.emptyArray);
  32.  
  33.                 break;
  34.             }
  35.             case Tokens.MERGE : {
  36.                 cs = compileMergeStatement(RangeGroup.emptyArray);
  37.  
  38.                 break;
  39.             }
  40.             case Tokens.DELETE : {
  41.                 cs = compileDeleteStatement(RangeGroup.emptyArray);
  42.  
  43.                 break;
  44.             }
  45.             case Tokens.TRUNCATE : {
  46.                 cs = compileTruncateStatement();
  47.  
  48.                 break;
  49.             }
  50.  
  51.             // PROCEDURE
  52.             case Tokens.CALL : {
  53.                 cs = compileCallStatement(
  54.                     session.sessionContext.sessionVariableRangeGroups, false);
  55.  
  56.                 break;
  57.             }
  58.  
  59.             // SQL SESSION
  60.             case Tokens.SET :
  61.                 cs = compileSet();
  62.                 break;
  63.  
  64.             // diagnostic
  65.             case Tokens.GET :
  66.                 cs = compileGetStatement(
  67.                     session.sessionContext.sessionVariableRangeGroups);
  68.                 break;
  69.  
  70.             case Tokens.START :
  71.                 cs = compileStartTransaction();
  72.                 break;
  73.  
  74.             case Tokens.COMMIT :
  75.                 cs = compileCommit();
  76.                 break;
  77.  
  78.             case Tokens.ROLLBACK :
  79.                 cs = compileRollback();
  80.                 break;
  81.  
  82.             case Tokens.SAVEPOINT :
  83.                 cs = compileSavepoint();
  84.                 break;
  85.  
  86.             case Tokens.RELEASE :
  87.                 cs = compileReleaseSavepoint();
  88.                 break;
  89.  
  90.             // DDL
  91.             case Tokens.CREATE :
  92.                 cs = compileCreate();
  93.                 break;
  94.  
  95.             case Tokens.ALTER :
  96.                 cs = compileAlter();
  97.                 break;
  98.  
  99.             case Tokens.DROP :
  100.                 cs = compileDrop();
  101.                 break;
  102.  
  103.             case Tokens.GRANT :
  104.             case Tokens.REVOKE :
  105.                 cs = compileGrantOrRevoke();
  106.                 break;
  107.  
  108.             case Tokens.COMMENT :
  109.                 cs = compileComment();
  110.                 break;
  111.  
  112.             // HSQL SESSION
  113.             case Tokens.LOCK :
  114.                 cs = compileLock();
  115.                 break;
  116.  
  117.             case Tokens.CONNECT :
  118.                 cs = compileConnect();
  119.                 break;
  120.  
  121.             case Tokens.DISCONNECT :
  122.                 cs = compileDisconnect();
  123.                 break;
  124.  
  125.             // HSQL COMMAND
  126.             case Tokens.SCRIPT :
  127.                 cs = compileScript();
  128.                 break;
  129.  
  130.             case Tokens.SHUTDOWN :
  131.                 cs = compileShutdown();
  132.                 break;
  133.  
  134.             case Tokens.BACKUP :
  135.                 cs = compileBackup();
  136.                 break;
  137.  
  138.             case Tokens.CHECKPOINT :
  139.                 cs = compileCheckpoint();
  140.                 break;
  141.  
  142.             case Tokens.EXPLAIN : {
  143.                 int position = getPosition();
  144.  
  145.                 cs = compileExplainPlan();
  146.  
  147.                 cs.setSQL(getLastPart(position));
  148.  
  149.                 break;
  150.             }
  151.             case Tokens.DECLARE :
  152.                 cs = compileDeclare();
  153.                 break;
  154.  
  155.             default :
  156.                 throw unexpectedToken();
  157.         }

 

 

我们知道SQL,全称是Structured Query Language, 既然是语言,就满足一定的约定。比如陈述一件事情,一般是主谓宾。SQL也需要满足约定。比如这个SQL语句:

select id from t1;

这个约定就是 select xx from yy,其先后顺序不能颠倒(不能是from yy select xx——虽然看起来好像也能表达),有些内容不可被替换(from不能被换成join)。

在这里代码也是以这样的逻辑来处理的,就是如果出现了一个TokenA,那么接下来的Tokens就必须满足TokenA开始的句式。

我们以其中的Tokens.Select为例,进入到compileCursorSpecification方法中:

StatementQuery compileCursorSpecification(RangeGroup[] rangeGroups, int props, boolean isRoutine) 

首先,我们看这个方法的签名,它的返回值是一个StatementQuery对象,而不是之前的Statement这个抽象类型了,这就表明了根据不同的SQL语句,实际上返回了不同的Statement的实现类。

点击(此处)折叠或打开

  1. StatementQuery compileCursorSpecification(RangeGroup[] rangeGroups,
  2.             int props, boolean isRoutine) {
  3.         OrderedHashSet colNames = null;
  4.         QueryExpression queryExpression = XreadQueryExpression();
  5.         if (token.tokenType == Tokens.FOR) {
  6.             read();
  7.             if (token.tokenType == Tokens.READ
  8.                     || token.tokenType == Tokens.FETCH) {
  9.                 read();
  10.                 readThis(Tokens.ONLY);
  11.                 props = ResultProperties.addUpdatable(props, false);
  12.             } else {
  13.                 readThis(Tokens.UPDATE);
  14.                 props = ResultProperties.addUpdatable(props, true);
  15.                 if (token.tokenType == Tokens.OF) {
  16.                     readThis(Tokens.OF);
  17.                     colNames = new OrderedHashSet();
  18.                     readColumnNameList(colNames, null, false);
  19.                 }
  20.             }
  21.         }
  22.         if (ResultProperties.isUpdatable(props)) {
  23.             queryExpression.isUpdatable = true;
  24.         }
  25.         queryExpression.setReturningResult();
  26.         queryExpression.resolve(session, rangeGroups, null);
  27.         StatementQuery cs = isRoutine
  28.                             ? new StatementCursor(session, queryExpression,
  29.                                 compileContext)
  30.                             : new StatementQuery(session, queryExpression,
  31.                                 compileContext);
  32.         return cs;
  33.     }

在这段代码中,被一句带过的

QueryExpression queryExpression = XreadQueryExpression();

这里有一个QueryExpression,就是一个查询表达式的意思。

一个表达式Expression,可以表达一个最基本的单元:如表式一个字段,一个数值,一个操作符;

一个表达式Expression:也可以由一个或多个子表达式组成,比如一个表达了“select col1 as c1, col2 from t1 where id=5”含义的QueryExpression ,下面这个图大概表示了QueryExpression是个什么内容:

graph1

(注:QuerySpecification继承QueryExpression)

1、通过XreadSelect方法,构建一个基本的QuerySpecification对象

2、循环调用XreadValueExpression,将列add到exprColumnList(QuerySpecification的属性/字段)

3、调用XreadFromClause,将读取的表,添加的rangeVariableList中

4、调用XreadBooleanValueExpression,将查询条件添加到queryCondtion中

当然,如果更复杂的语句,这个图无疑将是更复杂的。

总之,ParserDQL(以及其它ParserXXX) 调用scanner.scanNext,将SQL字符串先变成一个个token,然后再将token变成这样一棵逻辑树状的对象()。

回到前面,我们知道返回的可是一个Statement对象啊,




点击(此处)折叠或打开

  1.         StatementQuery cs = isRoutine
  2.                             ? new StatementCursor(session, queryExpression,
  3.                                 compileContext)
  4.                             : new StatementQuery(session, queryExpression,
  5.                                 compileContext);
  6.  
  7.         return cs;

在最后步骤,就new一个具体类型的Statement对象(StatementQuery, StatementCursor都继承自Statement)。

 

那么返回了Statement,有什么用?

比如对于一个查询语句来说(如StatementQuery),我们知道可以查询出一些数据啊;而对于一个指令语句(如StatementCommand)来说,我们知道可以增删改库里的数据。

那么Statement返回之后,HSQLDB里是怎么使用的?我们下篇再分析。

总结:

本文分析了HSQLDB从token到语法树的创建过程——也就是编译原理中的词法分析到语法分析的过程。

 

[相关源码文件]

ParserDQL.java(ParserXXX)

阅读(1392) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~