From 8736ca4925b83433fc723333b7a11f98e306e4cc Mon Sep 17 00:00:00 2001 From: Shenhao Wang Date: Fri, 6 Nov 2020 11:08:35 +0800 Subject: [PATCH] Fix error when handle bit string diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer index 6ccc8ab916..14ad27c359 100644 --- a/src/interfaces/ecpg/preproc/ecpg.trailer +++ b/src/interfaces/ecpg/preproc/ecpg.trailer @@ -1715,13 +1715,13 @@ cvariable: CVARIABLE ecpg_param: PARAM { $$ = make_name(); } ; -ecpg_bconst: BCONST { $$ = make_name(); } ; +ecpg_bconst: BCONST { $$ = $1; } ; ecpg_fconst: FCONST { $$ = make_name(); } ; ecpg_sconst: SCONST { $$ = $1; } ; -ecpg_xconst: XCONST { $$ = make_name(); } ; +ecpg_xconst: XCONST { $$ = $1; } ; ecpg_ident: IDENT { $$ = $1; } | CSTRING { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type index ffafa82af9..eca298bdb8 100644 --- a/src/interfaces/ecpg/preproc/ecpg.type +++ b/src/interfaces/ecpg/preproc/ecpg.type @@ -122,7 +122,9 @@ %type CSTRING %type CPP_LINE %type CVARIABLE +%type BCONST %type SCONST +%type XCONST %type IDENT %type s_struct_union_symbol diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl index 1a76b2d326..52ba7dfa0c 100644 --- a/src/interfaces/ecpg/preproc/parse.pl +++ b/src/interfaces/ecpg/preproc/parse.pl @@ -38,6 +38,7 @@ my %replace_token = ( 'BCONST' => 'ecpg_bconst', 'FCONST' => 'ecpg_fconst', 'Sconst' => 'ecpg_sconst', + 'XCONST' => 'ecpg_xconst', 'IDENT' => 'ecpg_ident', 'PARAM' => 'ecpg_param',); diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 91d8b63578..1aebac89cd 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -505,9 +505,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { {xbstart} { token_start = yytext; + state_before_str_start = YYSTATE; BEGIN(xb); startlit(); - addlitchar('b'); } } /* */ @@ -519,9 +519,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ {xhstart} { token_start = yytext; + state_before_str_start = YYSTATE; BEGIN(xh); startlit(); - addlitchar('x'); } <> { mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); } @@ -597,12 +597,14 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ switch (state_before_str_stop) { case xb: - if (literalbuf[strspn(literalbuf, "01") + 1] != '\0') + if (literalbuf[strspn(literalbuf, "01")] != '\0') mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string literal"); - base_yylval.str = mm_strdup(literalbuf); + base_yylval.str = psprintf("b'%s'", literalbuf); return BCONST; case xh: - base_yylval.str = mm_strdup(literalbuf); + if (literalbuf[strspn(literalbuf, "0123456789abcdefABCDEF")] != '\0') + mmerror(PARSE_ERROR, ET_ERROR, "invalid hex string literal"); + base_yylval.str = psprintf("x'%s'", literalbuf); return XCONST; case xq: /* fallthrough */ diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule index 1e67d2b162..68016e32de 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule +++ b/src/interfaces/ecpg/test/ecpg_schedule @@ -34,6 +34,7 @@ test: sql/array test: sql/binary test: sql/bytea test: sql/code100 +test: sql/const test: sql/copystdout test: sql/createtableas test: sql/define diff --git a/src/interfaces/ecpg/test/expected/sql-const.c b/src/interfaces/ecpg/test/expected/sql-const.c new file mode 100644 index 0000000000..d2591d3d52 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-const.c @@ -0,0 +1,193 @@ +/* Processed by ecpg (regression mode) */ +/* These include files are added by the preprocessor */ +#include +#include +#include +/* End of automatic include section */ +#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y)) + +#line 1 "const.pgc" +#include + +/* exec sql whenever sqlerror sqlprint ; */ +#line 3 "const.pgc" + + + +#line 1 "sqlca.h" +#ifndef POSTGRES_SQLCA_H +#define POSTGRES_SQLCA_H + +#ifndef PGDLLIMPORT +#if defined(WIN32) || defined(__CYGWIN__) +#define PGDLLIMPORT __declspec (dllimport) +#else +#define PGDLLIMPORT +#endif /* __CYGWIN__ */ +#endif /* PGDLLIMPORT */ + +#define SQLERRMC_LEN 150 + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sqlca_t +{ + char sqlcaid[8]; + long sqlabc; + long sqlcode; + struct + { + int sqlerrml; + char sqlerrmc[SQLERRMC_LEN]; + } sqlerrm; + char sqlerrp[8]; + long sqlerrd[6]; + /* Element 0: empty */ + /* 1: OID of processed tuple if applicable */ + /* 2: number of rows processed */ + /* after an INSERT, UPDATE or */ + /* DELETE statement */ + /* 3: empty */ + /* 4: empty */ + /* 5: empty */ + char sqlwarn[8]; + /* Element 0: set to 'W' if at least one other is 'W' */ + /* 1: if 'W' at least one character string */ + /* value was truncated when it was */ + /* stored into a host variable. */ + + /* + * 2: if 'W' a (hopefully) non-fatal notice occurred + */ /* 3: empty */ + /* 4: empty */ + /* 5: empty */ + /* 6: empty */ + /* 7: empty */ + + char sqlstate[5]; +}; + +struct sqlca_t *ECPGget_sqlca(void); + +#ifndef POSTGRES_ECPG_INTERNAL +#define sqlca (*ECPGget_sqlca()) +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#line 5 "const.pgc" + + +#line 1 "regression.h" + + + + + + +#line 6 "const.pgc" + + +int +main (void) +{ +/* exec sql begin declare section */ + + + +#line 12 "const.pgc" + int b , hb ; + +#line 13 "const.pgc" + char s [ 100 ] , es [ 100 ] , ns [ 100 ] , us [ 100 ] ; +/* exec sql end declare section */ +#line 14 "const.pgc" + + + ECPGdebug(1, stderr); + + { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); +#line 18 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 18 "const.pgc" + + + { ECPGtrans(__LINE__, NULL, "begin work"); +#line 20 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 20 "const.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test ( b bit ( 4 ) , hb bit ( 12 ) , s text , es text , ns text , us text )", ECPGt_EOIT, ECPGt_EORT); +#line 22 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 22 "const.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test values ( b'1010' , x'9aE' , 'test' , E'test\\\\ab' , N'test' , U&'\\0047bc' )", ECPGt_EOIT, ECPGt_EORT); +#line 25 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 25 "const.pgc" + + + { ECPGtrans(__LINE__, NULL, "commit"); +#line 27 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 27 "const.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select b :: int , hb :: int , s , es , ns , us from test limit 1", ECPGt_EOIT, + ECPGt_int,&(b),(long)1,(long)1,sizeof(int), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_int,&(hb),(long)1,(long)1,sizeof(int), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_char,(s),(long)100,(long)1,(100)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_char,(es),(long)100,(long)1,(100)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_char,(ns),(long)100,(long)1,(100)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_char,(us),(long)100,(long)1,(100)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); +#line 30 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 30 "const.pgc" + + + printf("b=%d, hb=%d, s=%s, es=%s, ns=%s, us=%s\n", + b, hb, s, es, ns, us); + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table test", ECPGt_EOIT, ECPGt_EORT); +#line 35 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 35 "const.pgc" + + { ECPGtrans(__LINE__, NULL, "commit"); +#line 36 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 36 "const.pgc" + + { ECPGdisconnect(__LINE__, "CURRENT"); +#line 37 "const.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 37 "const.pgc" + + + return 0; +} diff --git a/src/interfaces/ecpg/test/expected/sql-const.stderr b/src/interfaces/ecpg/test/expected/sql-const.stderr new file mode 100644 index 0000000000..8b85c7dfb7 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-const.stderr @@ -0,0 +1,48 @@ +[NO_PID]: ECPGdebug: set to 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGconnect: opening database ecpg1_regression on port +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGtrans on line 20: action "begin work"; connection "ecpg1_regression" +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 22: query: create table test ( b bit ( 4 ) , hb bit ( 12 ) , s text , es text , ns text , us text ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 22: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 22: OK: CREATE TABLE +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 24: query: insert into test values ( b'1010' , x'9aE' , 'test' , E'test\\ab' , N'test' , U&'\0047bc' ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 24: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 24: OK: INSERT 0 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGtrans on line 27: action "commit"; connection "ecpg1_regression" +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 29: query: select b :: int , hb :: int , s , es , ns , us from test limit 1; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 29: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 29: correctly got 1 tuples with 6 fields +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: 10 offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: 2478 offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: test offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: test\ab offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: test offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 29: RESULT: Gbc offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 35: query: drop table test; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 35: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 35: OK: DROP TABLE +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGtrans on line 36: action "commit"; connection "ecpg1_regression" +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_finish: connection ecpg1_regression closed +[NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-const.stdout b/src/interfaces/ecpg/test/expected/sql-const.stdout new file mode 100644 index 0000000000..85d542ded7 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-const.stdout @@ -0,0 +1 @@ +b=10, hb=2478, s=test, es=test\ab, ns=test, us=Gbc diff --git a/src/interfaces/ecpg/test/sql/.gitignore b/src/interfaces/ecpg/test/sql/.gitignore index 613bdebc96..9715b27a8b 100644 --- a/src/interfaces/ecpg/test/sql/.gitignore +++ b/src/interfaces/ecpg/test/sql/.gitignore @@ -6,6 +6,8 @@ /bytea.c /code100 /code100.c +/const +/const.c /copystdout /copystdout.c /createtableas diff --git a/src/interfaces/ecpg/test/sql/Makefile b/src/interfaces/ecpg/test/sql/Makefile index 170bcd72c4..0e6cfdd164 100644 --- a/src/interfaces/ecpg/test/sql/Makefile +++ b/src/interfaces/ecpg/test/sql/Makefile @@ -6,7 +6,8 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress TESTS = array array.c \ binary binary.c \ code100 code100.c \ - copystdout copystdout.c \ + const const.c \ + copystdout copystdout.c \ createtableas createtableas.c \ define define.c \ desc desc.c \ diff --git a/src/interfaces/ecpg/test/sql/const.pgc b/src/interfaces/ecpg/test/sql/const.pgc new file mode 100644 index 0000000000..c16ee11dc4 --- /dev/null +++ b/src/interfaces/ecpg/test/sql/const.pgc @@ -0,0 +1,40 @@ +#include + +exec sql whenever sqlerror sqlprint; + +exec sql include sqlca; +exec sql include ../regression; + +int +main (void) +{ +EXEC SQL BEGIN DECLARE SECTION; + int b,hb; + char s[100],es[100],ns[100],us[100]; +EXEC SQL END DECLARE SECTION; + + ECPGdebug(1, stderr); + + EXEC SQL CONNECT TO REGRESSDB1; + + EXEC SQL BEGIN WORK; + + EXEC SQL CREATE TABLE test(b bit(4), hb bit(12), s text, es text, ns text, us text); + + EXEC SQL INSERT INTO test VALUES(b'1010', x'9aE', 'test', e'test\\ab', + n'test', u&'\0047bc'); + + EXEC SQL COMMIT; + + EXEC SQL SELECT b::int, hb::int, s, es, ns, us INTO + :b, :hb, :s, :es, :ns, :us FROM test LIMIT 1; + + printf("b=%d, hb=%d, s=%s, es=%s, ns=%s, us=%s\n", + b, hb, s, es, ns, us); + + EXEC SQL DROP TABLE test; + EXEC SQL COMMIT; + EXEC SQL DISCONNECT; + + return 0; +} -- 2.26.2