2021SC@SDUSC
文章目录
Tokenizer功能介绍
当执行一个包含SQL语句的字符串时,接口程序要把这个字符串传递给Tokenizer。Tokenizer的任务是把原有字符串分成一个个标示符,并把这些标示符传递给剖析器。
当向SQLite提交SQL程序时,第一步是将源文本拆分为“tokens”。一个“token”可能是:
1.像“SELECT”或“UPDATE”这样的语言关键字。
2.表、列或变量的标识符。
3.像“,”或“==”或“;”这样的标点符号。
4.文字值:数值或字符串常量。
5.空白或评论。
空格和注释标记会被丢弃。所有其他令牌都被输入到LALR(1)解析器分析输入程序的结构,并生成一个抽象语法树(AST)输入程序。
代码分析
在fts3_Tokenizer.c文件中定义了下面的方法用于查找源文本中的“token”:
/* Find the start of the next token. */
int sqlite3Fts3IsIdChar(char c){
static const char isFtsIdChar[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
return (c&0x80 || isFtsIdChar[(int)(c)]);
}
const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
const char *z1;
const char *z2 = 0;
/* Find the start of the next token. */
z1 = zStr;
while( z2==0 ){
char c = *z1;
switch( c ){
case '\0': return 0; /* No more tokens here */
case '\'':
case '"':
case '`': {
z2 = z1;
while( *++z2 && (*z2!=c || *++z2==c) );
break;
}
case '[':
z2 = &z1[1];
while( *z2 && z2[0]!=']' ) z2++;
if( *z2 ) z2++;
break;
default:
if( sqlite3Fts3IsIdChar(*z1) ){
z2 = &z1[1];
while( sqlite3Fts3IsIdChar(*z2) ) z2++;
}else{
z1++;
}
}
}
*pn = (int)(z2-z1);
return z1;
}
从上面的代码中可以看出,所有被Tokenizer找出的“token”都被sqlite3Fts3IsIdChar(char c)方法储存起来,最后该表会被用于全文索引的创建;在其他组成文件中可以通过以下方法调用fts3_Tokenizer()函数:
SELECT fts3_tokenizer(<tokenizer-name>);
SELECT fts3_tokenizer(<tokenizer-name>, <sqlite3_tokenizer_module ptr>);
其中:
“tokenizer-name”是使用sqlite3_bind_text()绑定到的字符串的参数;“sqlite3_tokenizer_module ptr”是使用 sqlite3_bind_blob()绑定到的参数;BLOB的值是指向sqlite3_tokenizer_module结构的指针。如果存在第二个参数,它将注册为标记器“tokenizer-name”,并返回它的副本。如果只传递一个参数,则返回一个指向当前注册为“tokenizer-name”的标记器实现的指针,并编码为一个blob。或者,如果不存在这样的标记器,则会引发一个SQL异常(错误)。
自定义分词器
SQLite在fts3_tokenizer.h中提供了各种接口供用户自定义分词器:
#ifndef _FTS3_TOKENIZER_H_
#define _FTS3_TOKENIZER_H_
#include "sqlite3.h"
typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
typedef struct sqlite3_tokenizer sqlite3_tokenizer;
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
struct sqlite3_tokenizer_module {
int iVersion;
int (*xCreate)(
int argc, /* Size of argv array */
const char *const*argv, /* Tokenizer argument strings */
sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
);
int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
int (*xOpen)(
sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
const char *pInput, int nBytes, /* Input buffer */
sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */
);
int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
int (*xNext)(
sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */
const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
int *piStartOffset, /* OUT: Byte offset of token in input buffer */
int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
int *piPosition /* OUT: Number of tokens returned before this one */
);
int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
};
struct sqlite3_tokenizer {
const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
/* Tokenizer implementations will typically add additional fields */
};
struct sqlite3_tokenizer_cursor {
sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
/* Tokenizer implementations will typically add additional fields */
};
int fts3_global_term_cnt(int iTerm, int iCol);
int fts3_term_cnt(int iTerm, int iCol);
#endif /* _FTS3_TOKENIZER_H_ */