1.在Halo数据库中
字符串:使用单引号(‘’)引用
select ‘halo’;
标识符:可以直接引用,也可使用双引号(“”)引用
select id from test;
select “id” from “test”;
其中,使用双引号引用的标识符可以包含一些特殊字符,可以是关键字,并且区分大小写
2.在Mysql数据库中
字符串:使用单引号(‘’)或双引号(“”)引用,两者功能相同
select ‘halo’;
或select “halo”;
标识符:可以直接引用,也可使用反引号(``)引用
select id from test;
select `id` from `test`;
其中,使用反引号引用的标识符可以包含一些特殊字符,可以是关键字,默认不区分大小写
3.具体实现
在Halo数据库的语法文件中,字符串、标识符的记号(Token)分别为Sconst、Ident,在词法文件中,具体修改如下:
第一步,添加反引号标识符识别规则,如下:
{xbtstart} {
SET_YYLLOC();
BEGIN(xbt);
startlit();
}
<xbt>{xbtstop} {
char *ident;
BEGIN(INITIAL);
if (yyextra->literallen == 0)
yyerror("zero-length delimited identifier");
// ident = litbufdup(yyscanner);
// if (yyextra->literallen >= NAMEDATALEN)
// truncate_identifier(ident, yyextra->literallen, true);
ident = downcase_truncate_identifier(yyextra->literalbuf, yyextra->literallen, true);
yylval->str = ident;
return IDENT;
}
<xbt>{xbtdouble} {
addlitchar('`', yyscanner);
}
<xbt>{xbtinside} {
addlit(yytext, yyleng, yyscanner);
}
<xbt><<EOF>> { yyerror("unterminated backtick identifier"); }
第二步,删除单引号字符串的部分规则(如对字符串中八进制,十六进制进行转义),如下:
<xe>{xeoctesc} {
unsigned char c = strtoul(yytext + 1, NULL, 8);
check_escape_warning(yyscanner);
addlitchar(c, yyscanner);
if (c == '\0' || IS_HIGHBIT_SET(c))
yyextra->saw_non_ascii = true;
}
<xe>{xehexesc} {
unsigned char c = strtoul(yytext + 2, NULL, 16);
check_escape_warning(yyscanner);
addlitchar(c, yyscanner);
if (c == '\0' || IS_HIGHBIT_SET(c))
yyextra->saw_non_ascii = true;
}
第三步,删除与双引号有关的标识符识别规则,添加双引号字符串识别规则,结果如下:
{xdqstart} {
yyextra->warn_on_first_escape = false;
yyextra->saw_non_ascii = false;
SET_YYLLOC();
// if (yyextra->standard_conforming_strings)
// BEGIN(xdq);
// else
// BEGIN(xde);
BEGIN(xde);
startlit();
}
<xdq,xde>{dquote} {
/*
* When we are scanning a quoted string and see an end
* quote, we must look ahead for a possible continuation.
* If we don't see one, we know the end quote was in fact
* the end of the string. To reduce the lexer table size,
* we use a single "xqs" state to do the lookahead for all
* types of strings.
*/
yyextra->state_before_str_stop = YYSTATE;
BEGIN(xdqs);
}
<xdqs>{dquotecontinue} {
/*
* Found a quote continuation, so return to the in-quote
* state and continue scanning the literal. Nothing is
* added to the literal's contents.
*/
BEGIN(yyextra->state_before_str_stop);
}
<xdqs>{dquotecontinuefail} |
<xdqs>{other} |
<xdqs><<EOF>> {
/*
* Failed to see a quote continuation. Throw back
* everything after the end quote, and handle the string
* according to the state we were in previously.
*/
yyless(0);
BEGIN(INITIAL);
switch (yyextra->state_before_str_stop)
{
case xdq:
case xde:
/*
* Check that the data remains valid, if it might
* have been made invalid by unescaping any chars.
*/
if (yyextra->saw_non_ascii)
pg_verifymbstr(yyextra->literalbuf,
yyextra->literallen,
false);
yylval->str = litbufdup(yyscanner);
return SCONST;
default:
yyerror("unhandled previous state in xdqs");
}
}
<xdq,xde>{xdqdouble} {
addlitchar('\"', yyscanner);
}
<xdq>{xdqinside} {
addlit(yytext, yyleng, yyscanner);
}
<xde>{xdeinside} {
addlit(yytext, yyleng, yyscanner);
}
<xde>{xdeescape} {
if (yytext[1] == '\"')
{
if (yyextra->backslash_quote == BACKSLASH_QUOTE_OFF ||
(yyextra->backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding())))
ereport(ERROR,
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
errmsg("unsafe use of \\\" in a string literal"),
errhint("Use \"\" to write double quotes in strings. \\\" is insecure in client-only encodings."),
lexer_errposition()));
}
if(yytext[1] == '0')
yytext[1] = '\0';
check_string_escape_warning(yytext[1], yyscanner);
addlitchar(unescape_single_char(yytext[1], yyscanner),
yyscanner);
}
<xde>. {
/* This is only needed for \ just before EOF */
addlitchar(yytext[0], yyscanner);
}
<xdq,xde><<EOF>> { yyerror("unterminated double quoted string"); }
4.结果展示
字符串:
标识符:




