Mini SQL 总体设计(二):Token分割

之前那篇博文Mini SQL 总体设计(一) 中在提到Tokens分割的时候试图进行句法分析,这个问题就相当复杂了。

看了指针1 实现的Token分割之后,我发现我有个地方搞错了。我试图将SQL语句中充当不同成分的部分提取出来,就像分析主谓宾一样,这实际上是句法分析。对于正则表达式来说未免任务过重。

而且JS正则表达式不具有平衡组,也无法进行无限深度的括号平衡匹配。

应该把Tokens分割地更细,然后将逻辑复杂度转移到Token分割之后的Router里。


其实问题应该是很简单的:

/\w+|[^\s]/g

用这个正则去匹配SQL语句就可以了。
除了要匹配正常的字符串\w+,还要保留除了空白字符\s 之外的各种符号:如括号\( \)、逗号,、引号' "等号=、以及分号; 等等;
保留除了空白符的部分来提示之后的路由分配,保证信息无损传递。

tokenizer = (sql) => sql.match(/\w+|[^\s]/g);
tokenizer('create table t(a int, b varchar(20));');  // ["create", "table", "t", "(", "a", "int", ",", "b", "varchar", "(", "20", ")", ")", ";"]

本来事情是很简单的,Tokenizer(分解器)就应该只做分内之事,不要做一些多余的事情。

至于要不要去判断SQL语句是否完整,SQL语法判定,都交给其他组件去完成吧。


测试

var sql = `
create database aaa;
create table t(a int, b varchar(20) not null);
create index AU on t(a);
select a, b from t where 1;
insert into t(a, b) values(1, 2);
update t set b ='sd', c = 'ss' where b='ss';
delete from t where t.b = 'ss' and t.a = 2;
`
sql.match(/\w+|[^\s]/g)

结果

["create", "database", "aaa", ";", "create", "table", "t", "(", "a", "int", ",", "b", "varchar", "(", "20", ")", "not", "null", ")", ";", "create", "index", "AU", "on", "t", "(", "a", ")", ";", "select", "a", ",", "b", "from", "t", "where", "1", ";", "insert", "into", "t", "(", "a", ",", "b", ")", "values", "(", "1", ",", "2", ")", ";", "update", "t", "set", "b", "=", "'", "sd", "'", ",", "c", "=", "'", "ss", "'", "where", "b", "=", "'", "ss", "'", ";", "delete", "from", "t", "where", "t", ".", "b", "=", "'", "ss", "'", "and", "t", ".", "a", "=", "2", ";"]

  1. 指针:数据库课友孙明琦的昵称。 ↩

你可能感兴趣的:(产品)