sqlite3ParserInit函数
主要目的就是初始化一个解析器
SQLITE_PRIVATEvoid sqlite3ParserInit(void *yypParser){ yyParser *pParser = (yyParser*)yypParser;//解析器对象 #ifdef YYTRACKMAXSTACKDEPTH pParser->yyhwm = 0; #endif #ifYYSTACKDEPTH<=0 pParser->yytos = NULL; pParser->yystack = NULL; pParser->yystksz = 0; if( yyGrowStack(pParser) ){ pParser->yystack = &pParser->yystk0; pParser->yystksz = 1; } #endif #ifndefYYNOERRORRECOVERY pParser->yyerrcnt = -1; #endif pParser->yytos = pParser->yystack; pParser->yystack[0].stateno = 0; pParser->yystack[0].major = 0; #ifYYSTACKDEPTH>0 pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; #endif } |
sqlite3GetToken函数
这个函数说起来有点复杂,我尽量说清楚。
我先分步解析,再总体说明。
我用select id,name from stu;这个sql语句来解析Token的解析过程。
1:aiClass[*z]数组确定case,
例如第一个词select ,通过s的ASCII码115 ,找到aiClass[115]这个数,
找到的这个数为1
通过这个1我们找到了一个case
这里面CC_KYWD==1。
在这个case里面要做这么几件事情:
1:通过一个for循环确定i的大小及select的长度。这里为6。
它是如何确定i的大小呢?
答案是:z[ i]数组放的是select这个词,然后依次遍历这个词只要满足条件就使i++,这样就可以确定i的大小。
2:执行这两个东西
keywordCode函数是一个查找关键字的函数。
i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;
确定了i的值,charMap(z[0])中z[0]代表select中的s,z[n-1]代表select中的t。
charMap()这个宏就是找到相应字符的小写ASCII码。
下面就是字符间的转换。
最后一步就是确定*pType的值
现在,我总体说一下这个函数
在sqlite3GetToken()函数中,实现了aiClass [c]上的switch()使用查找表,而直接在上的switch()使用二进制搜索。查找表要快得多。
观察 下面的查找表,上面定义的宏与下面的表是相互对应的。
#defineCC_X 0 /* The letter 'x', or start of BLOB literal (字母“x”或BLOB文字的开始)*/ #defineCC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword(字母或'_'。可用于关键字) */ #defineCC_ID 2 /* unicode characters usable in IDs(可用于ID的unicode字符) */ #defineCC_DIGIT 3 /* Digits(数字) */ #defineCC_DOLLAR 4 /* '$' */ #defineCC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ #defineCC_VARNUM 6 /* '?'. SQL variables */ #defineCC_SPACE 7 /* Space characters */ #defineCC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ #defineCC_QUOTE2 9 /* '['. [...] style quoted ids */ #defineCC_PIPE 10 /* '|'. Bitwise OR or concatenate */ #defineCC_MINUS 11 /* '-'. Minus or SQL-style comment */ #defineCC_LT 12 /* '<'. Part of < or <= or <> */ #defineCC_GT 13 /* '>'. Part of > or >= */ #defineCC_EQ 14 /* '='. Part of = or == */ #defineCC_BANG 15 /* '!'. Part of != */ #defineCC_SLASH 16 /* '/'. / or c-style comment */ #defineCC_LP 17 /* '(' */ #defineCC_RP 18 /* ')' */ #defineCC_SEMI 19 /* ';' */ #defineCC_PLUS 20 /* '+' */ #defineCC_STAR 21 /* '*' */ #defineCC_PERCENT 22 /* '%' */ #defineCC_COMMA 23 /* ',' */ #defineCC_AND 24 /* '&' */ #defineCC_TILDA 25 /* '~' */ #defineCC_DOT 26 /* '.' */ #defineCC_ILLEGAL 27 /* Illegal character */
staticconstunsignedchar aiClass[] = { #ifdefSQLITE_ASCII /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ /* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, /* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, /* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, /* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
关键字查询的函数实现(keywordCode函数)
(检查看z[0..n-1]是否是关键字,如果是的话就将该关键字的解析器符号代码写入*pType)。 返回token的长度 */ staticint keywordCode(constchar *z, intn, int *pType){ int i, j; constchar *zKW; if( n>=2 ){ i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;//确定i的值 i值得确定是通过sql语句的第一个词的首尾字符确定的(比如select 是由s ,t确定) for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){//aKWHash[]数组中对应的是第i个keyword的哈希值(比如18对应的是116 t的ASCII码) if( aKWLen[i]!=n ) continue; j = 0; zKW = &zKWText[aKWOffset[i]];//S #ifdefSQLITE_ASCII while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; }//小写转换为大写 #endif #ifdef SQLITE_EBCDIC while( j<n && toupper(z[j])==zKW[j] ){ j++; } #endif if( j<n ) continue; 。。。。。。 *pType = aKWCode[i]; break; } } returnn; } |
*pType = aKWCode[i]对应的表,*pType就是传给sqlite3Parser函数的第二个参数
在测试时select对应的i==18, 找到aKWCode[18]中的 TK_SELECT,
staticconstunsignedchar aKWCode[124] = { TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, }; |