PostgreSQL Source Code git master
psqlscan.l File Reference
#include "postgres_fe.h"
#include "common/logging.h"
#include "fe_utils/psqlscan.h"
#include "libpq-fe.h"
#include "fe_utils/psqlscan_int.h"
Include dependency graph for psqlscan.l:

Go to the source code of this file.

Macros

#define LEXRES_EOL   0 /* end of input */
 
#define LEXRES_SEMI   1 /* command-terminating semicolon found */
 
#define LEXRES_BACKSLASH   2 /* backslash command start */
 
#define ECHO   psqlscan_emit(cur_state, yytext, yyleng)
 

Typedefs

typedef int YYSTYPE
 

Functions

int yylex (YYSTYPE *yylval_param, yyscan_t yyscanner)
 
PsqlScanState psql_scan_create (const PsqlScanCallbacks *callbacks)
 
void psql_scan_destroy (PsqlScanState state)
 
void psql_scan_set_passthrough (PsqlScanState state, void *passthrough)
 
void psql_scan_setup (PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
 
PsqlScanResult psql_scan (PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
 
void psql_scan_finish (PsqlScanState state)
 
void psql_scan_reset (PsqlScanState state)
 
void psql_scan_reselect_sql_lexer (PsqlScanState state)
 
bool psql_scan_in_quote (PsqlScanState state)
 
void psqlscan_push_new_buffer (PsqlScanState state, const char *newstr, const char *varname)
 
void psqlscan_pop_buffer_stack (PsqlScanState state)
 
void psqlscan_select_top_buffer (PsqlScanState state)
 
bool psqlscan_var_is_current_source (PsqlScanState state, const char *varname)
 
YY_BUFFER_STATE psqlscan_prepare_buffer (PsqlScanState state, const char *txt, int len, char **txtcopy)
 
void psqlscan_emit (PsqlScanState state, const char *txt, int len)
 
char * psqlscan_extract_substring (PsqlScanState state, const char *txt, int len)
 
void psqlscan_escape_variable (PsqlScanState state, const char *txt, int len, PsqlScanQuoteType quote)
 
void psqlscan_test_variable (PsqlScanState state, const char *txt, int len)
 

Macro Definition Documentation

◆ ECHO

#define ECHO   psqlscan_emit(cur_state, yytext, yyleng)

Definition at line 62 of file psqlscan.l.

◆ LEXRES_BACKSLASH

#define LEXRES_BACKSLASH   2 /* backslash command start */

Definition at line 59 of file psqlscan.l.

◆ LEXRES_EOL

#define LEXRES_EOL   0 /* end of input */

Definition at line 57 of file psqlscan.l.

◆ LEXRES_SEMI

#define LEXRES_SEMI   1 /* command-terminating semicolon found */

Definition at line 58 of file psqlscan.l.

Typedef Documentation

◆ YYSTYPE

typedef int YYSTYPE

Definition at line 53 of file psqlscan.l.

Function Documentation

◆ psql_scan()

PsqlScanResult psql_scan ( PsqlScanState  state,
PQExpBuffer  query_buf,
promptStatus_t prompt 
)

Definition at line 1117 of file psqlscan.l.

1120{
1121 PsqlScanResult result;
1122 int lexresult;
PsqlScanResult
Definition: psqlscan.h:31
1123
1124 /* Must be scanning already */
1125 Assert(state->scanbufhandle != NULL);
#define Assert(condition)
Definition: c.h:815
Definition: regguts.h:323
1126
1127 /* Set current output target */
1128 state->output_buf = query_buf;
1129
1130 /* Set input source */
1131 if (state->buffer_stack != NULL)
1132 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
1133 else
1134 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1135
1136 /* And lex. */
1137 lexresult = yylex(NULL, state->scanner);
int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner)
Definition: psqlscan.l:385
1138
1139 /*
1140 * Check termination state and return appropriate result info.
1141 */
1142 switch (lexresult)
1143 {
1144 case LEXRES_EOL: /* end of input */
1145 switch (state->start_state)
1146 {
1147 case INITIAL:
1148 case xqs: /* we treat this like INITIAL */
1149 if (state->paren_depth > 0)
1150 {
1151 result = PSCAN_INCOMPLETE;
1152 *prompt = PROMPT_PAREN;
1153 }
1154 else if (state->begin_depth > 0)
1155 {
1156 result = PSCAN_INCOMPLETE;
1157 *prompt = PROMPT_CONTINUE;
1158 }
1159 else if (query_buf->len > 0)
1160 {
1161 result = PSCAN_EOL;
1162 *prompt = PROMPT_CONTINUE;
1163 }
1164 else
1165 {
1166 /* never bother to send an empty buffer */
1167 result = PSCAN_INCOMPLETE;
1168 *prompt = PROMPT_READY;
1169 }
1170 break;
1171 case xb:
1172 result = PSCAN_INCOMPLETE;
1173 *prompt = PROMPT_SINGLEQUOTE;
1174 break;
1175 case xc:
1176 result = PSCAN_INCOMPLETE;
1177 *prompt = PROMPT_COMMENT;
1178 break;
1179 case xd:
1180 result = PSCAN_INCOMPLETE;
1181 *prompt = PROMPT_DOUBLEQUOTE;
1182 break;
1183 case xh:
1184 result = PSCAN_INCOMPLETE;
1185 *prompt = PROMPT_SINGLEQUOTE;
1186 break;
1187 case xe:
1188 result = PSCAN_INCOMPLETE;
1189 *prompt = PROMPT_SINGLEQUOTE;
1190 break;
1191 case xq:
1192 result = PSCAN_INCOMPLETE;
1193 *prompt = PROMPT_SINGLEQUOTE;
1194 break;
1195 case xdolq:
1196 result = PSCAN_INCOMPLETE;
1197 *prompt = PROMPT_DOLLARQUOTE;
1198 break;
1199 case xui:
1200 result = PSCAN_INCOMPLETE;
1201 *prompt = PROMPT_DOUBLEQUOTE;
1202 break;
1203 case xus:
1204 result = PSCAN_INCOMPLETE;
1205 *prompt = PROMPT_SINGLEQUOTE;
1206 break;
1207 default:
1208 /* can't get here */
1209 fprintf(stderr, "invalid YY_START\n");
1210 exit(1);
1211 }
1212 break;
1213 case LEXRES_SEMI: /* semicolon */
1214 result = PSCAN_SEMICOLON;
1215 *prompt = PROMPT_READY;
1216 break;
1217 case LEXRES_BACKSLASH: /* backslash */
1218 result = PSCAN_BACKSLASH;
1219 *prompt = PROMPT_READY;
1220 break;
1221 default:
1222 /* can't get here */
1223 fprintf(stderr, "invalid yylex result\n");
1224 exit(1);
1225 }
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
exit(1)
@ PSCAN_BACKSLASH
Definition: psqlscan.h:33
@ PSCAN_EOL
Definition: psqlscan.h:35
@ PSCAN_INCOMPLETE
Definition: psqlscan.h:34
@ PSCAN_SEMICOLON
Definition: psqlscan.h:32
@ PROMPT_READY
Definition: psqlscan.h:41
@ PROMPT_PAREN
Definition: psqlscan.h:47
@ PROMPT_COMMENT
Definition: psqlscan.h:43
@ PROMPT_CONTINUE
Definition: psqlscan.h:42
@ PROMPT_SINGLEQUOTE
Definition: psqlscan.h:44
@ PROMPT_DOLLARQUOTE
Definition: psqlscan.h:46
@ PROMPT_DOUBLEQUOTE
Definition: psqlscan.h:45
#define LEXRES_BACKSLASH
Definition: psqlscan.l:59
#define LEXRES_SEMI
Definition: psqlscan.l:58
#define LEXRES_EOL
Definition: psqlscan.l:57
1226
1227 return result;
1228}

References Assert, exit(), fprintf, PQExpBufferData::len, LEXRES_BACKSLASH, LEXRES_EOL, LEXRES_SEMI, PROMPT_COMMENT, PROMPT_CONTINUE, PROMPT_DOLLARQUOTE, PROMPT_DOUBLEQUOTE, PROMPT_PAREN, PROMPT_READY, PROMPT_SINGLEQUOTE, PSCAN_BACKSLASH, PSCAN_EOL, PSCAN_INCOMPLETE, PSCAN_SEMICOLON, and yylex().

Referenced by MainLoop(), and ParseScript().

◆ psql_scan_create()

PsqlScanState psql_scan_create ( const PsqlScanCallbacks callbacks)

Definition at line 1001 of file psqlscan.l.

1002{
1004
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
1006
1007 state->callbacks = callbacks;
1008
1009 yylex_init(&state->scanner);
1010
1011 yyset_extra(state, state->scanner);
1012
void psql_scan_reset(PsqlScanState state)
Definition: psqlscan.l:1267
1014
1015 return state;
1016}

References pg_malloc0(), and psql_scan_reset().

Referenced by main(), MainLoop(), and ParseScript().

◆ psql_scan_destroy()

void psql_scan_destroy ( PsqlScanState  state)

Definition at line 1022 of file psqlscan.l.

1023{
void psql_scan_finish(PsqlScanState state)
Definition: psqlscan.l:1240
1025
1027
1028 yylex_destroy(state->scanner);
1029
1030 free(state);
#define free(a)
Definition: header.h:65
1031}

References free, psql_scan_finish(), and psql_scan_reset().

Referenced by main(), MainLoop(), and ParseScript().

◆ psql_scan_finish()

void psql_scan_finish ( PsqlScanState  state)

Definition at line 1240 of file psqlscan.l.

1241{
1242 /* Drop any incomplete variable expansions. */
1243 while (state->buffer_stack != NULL)
void psqlscan_pop_buffer_stack(PsqlScanState state)
Definition: psqlscan.l:1359
1245
1246 /* Done with the outer scan buffer, too */
1247 if (state->scanbufhandle)
1248 yy_delete_buffer(state->scanbufhandle, state->scanner);
1249 state->scanbufhandle = NULL;
1250 if (state->scanbuf)
1251 free(state->scanbuf);
1252 state->scanbuf = NULL;
1253}

References free, and psqlscan_pop_buffer_stack().

Referenced by MainLoop(), ParseScript(), and psql_scan_destroy().

◆ psql_scan_in_quote()

bool psql_scan_in_quote ( PsqlScanState  state)

Definition at line 1308 of file psqlscan.l.

1309{
1310 return state->start_state != INITIAL &&
1311 state->start_state != xqs;
1312}

Referenced by MainLoop().

◆ psql_scan_reselect_sql_lexer()

void psql_scan_reselect_sql_lexer ( PsqlScanState  state)

Definition at line 1295 of file psqlscan.l.

1296{
1297 state->start_state = INITIAL;
1298}

Referenced by expr_lex_one_word(), expr_scanner_finish(), psql_scan_slash_command(), psql_scan_slash_command_end(), and psql_scan_slash_option().

◆ psql_scan_reset()

void psql_scan_reset ( PsqlScanState  state)

Definition at line 1267 of file psqlscan.l.

1268{
1269 state->start_state = INITIAL;
1270 state->paren_depth = 0;
1271 state->xcdepth = 0; /* not really necessary */
1272 if (state->dolqstart)
1273 free(state->dolqstart);
1274 state->dolqstart = NULL;
1275 state->identifier_count = 0;
1276 state->begin_depth = 0;
1277}

References free.

Referenced by exec_command_reset(), exec_command_watch(), MainLoop(), psql_scan_create(), and psql_scan_destroy().

◆ psql_scan_set_passthrough()

void psql_scan_set_passthrough ( PsqlScanState  state,
void *  passthrough 
)

Definition at line 1041 of file psqlscan.l.

1042{
1043 state->cb_passthrough = passthrough;
1044}

Referenced by main(), and MainLoop().

◆ psql_scan_setup()

void psql_scan_setup ( PsqlScanState  state,
const char *  line,
int  line_len,
int  encoding,
bool  std_strings 
)

Definition at line 1059 of file psqlscan.l.

1062{
1063 /* Mustn't be scanning already */
1064 Assert(state->scanbufhandle == NULL);
1065 Assert(state->buffer_stack == NULL);
1066
1067 /* Do we need to hack the character set encoding? */
1068 state->encoding = encoding;
1069 state->safe_encoding = pg_valid_server_encoding_id(encoding);
int32 encoding
Definition: pg_database.h:41
#define pg_valid_server_encoding_id
Definition: pg_wchar.h:632
1070
1071 /* Save standard-strings flag as well */
1072 state->std_strings = std_strings;
1073
1074 /* Set up flex input buffer with appropriate translation and padding */
1075 state->scanbufhandle = psqlscan_prepare_buffer(state, line, line_len,
1076 &state->scanbuf);
1077 state->scanline = line;
YY_BUFFER_STATE psqlscan_prepare_buffer(PsqlScanState state, const char *txt, int len, char **txtcopy)
Definition: psqlscan.l:1422
1078
1079 /* Set lookaside data in case we have to map unsafe encoding */
1080 state->curline = state->scanbuf;
1081 state->refline = state->scanline;
1082}

References Assert, encoding, pg_valid_server_encoding_id, and psqlscan_prepare_buffer().

Referenced by main(), MainLoop(), and ParseScript().

◆ psqlscan_emit()

void psqlscan_emit ( PsqlScanState  state,
const char *  txt,
int  len 
)

Definition at line 1463 of file psqlscan.l.

1464{
1465 PQExpBuffer output_buf = state->output_buf;
1466
1467 if (state->safe_encoding)
1468 appendBinaryPQExpBuffer(output_buf, txt, len);
1469 else
1470 {
1471 /* Gotta do it the hard way */
1472 const char *reference = state->refline;
1473 int i;
int i
Definition: isn.c:72
const void size_t len
void appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
Definition: pqexpbuffer.c:397
1474
1475 reference += (txt - state->curline);
1476
1477 for (i = 0; i < len; i++)
1478 {
1479 char ch = txt[i];
1480
1481 if (ch == (char) 0xFF)
1482 ch = reference[i];
1483 appendPQExpBufferChar(output_buf, ch);
1484 }
1485 }
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
1486}

References appendBinaryPQExpBuffer(), appendPQExpBufferChar(), i, and len.

Referenced by psqlscan_escape_variable(), and psqlscan_test_variable().

◆ psqlscan_escape_variable()

void psqlscan_escape_variable ( PsqlScanState  state,
const char *  txt,
int  len,
PsqlScanQuoteType  quote 
)

Definition at line 1531 of file psqlscan.l.

1533{
1534 char *varname;
1535 char *value;
static struct @162 value
1536
1537 /* Variable lookup. */
1538 varname = psqlscan_extract_substring(state, txt + 2, len - 3);
1539 if (state->callbacks->get_variable)
1540 value = state->callbacks->get_variable(varname, quote,
1541 state->cb_passthrough);
1542 else
1543 value = NULL;
1544 free(varname);
char * psqlscan_extract_substring(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1495
1545
1546 if (value)
1547 {
1548 /* Emit the suitably-escaped value */
1549 appendPQExpBufferStr(state->output_buf, value);
1550 free(value);
1551 }
1552 else
1553 {
1554 /* Emit original token as-is */
1555 psqlscan_emit(state, txt, len);
1556 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void psqlscan_emit(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1463
1557}

References appendPQExpBufferStr(), free, len, psqlscan_emit(), psqlscan_extract_substring(), and value.

◆ psqlscan_extract_substring()

char * psqlscan_extract_substring ( PsqlScanState  state,
const char *  txt,
int  len 
)

Definition at line 1495 of file psqlscan.l.

1496{
1497 char *result = (char *) pg_malloc(len + 1);
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
1498
1499 if (state->safe_encoding)
1500 memcpy(result, txt, len);
1501 else
1502 {
1503 /* Gotta do it the hard way */
1504 const char *reference = state->refline;
1505 int i;
1506
1507 reference += (txt - state->curline);
1508
1509 for (i = 0; i < len; i++)
1510 {
1511 char ch = txt[i];
1512
1513 if (ch == (char) 0xFF)
1514 ch = reference[i];
1515 result[i] = ch;
1516 }
1517 }
1518 result[len] = '\0';
1519 return result;
1520}

References i, len, and pg_malloc().

Referenced by psqlscan_escape_variable(), and psqlscan_test_variable().

◆ psqlscan_pop_buffer_stack()

void psqlscan_pop_buffer_stack ( PsqlScanState  state)

Definition at line 1359 of file psqlscan.l.

1360{
1361 StackElem *stackelem = state->buffer_stack;
1362
1363 state->buffer_stack = stackelem->next;
1364 yy_delete_buffer(stackelem->buf, state->scanner);
1365 free(stackelem->bufstring);
1366 if (stackelem->origstring)
1367 free(stackelem->origstring);
1368 if (stackelem->varname)
1369 free(stackelem->varname);
1370 free(stackelem);
char * origstring
Definition: psqlscan_int.h:73
char * varname
Definition: psqlscan_int.h:74
YY_BUFFER_STATE buf
Definition: psqlscan_int.h:71
char * bufstring
Definition: psqlscan_int.h:72
struct StackElem * next
Definition: psqlscan_int.h:75
1371}

References StackElem::buf, StackElem::bufstring, free, StackElem::next, StackElem::origstring, and StackElem::varname.

Referenced by psql_scan_finish().

◆ psqlscan_prepare_buffer()

YY_BUFFER_STATE psqlscan_prepare_buffer ( PsqlScanState  state,
const char *  txt,
int  len,
char **  txtcopy 
)

Definition at line 1422 of file psqlscan.l.

1424{
1425 char *newtxt;
1426
1427 /* Flex wants two \0 characters after the actual data */
1428 newtxt = pg_malloc(len + 2);
1429 *txtcopy = newtxt;
1430 newtxt[len] = newtxt[len + 1] = YY_END_OF_BUFFER_CHAR;
1431
1432 if (state->safe_encoding)
1433 memcpy(newtxt, txt, len);
1434 else
1435 {
1436 /* Gotta do it the hard way */
1437 int i = 0;
1438
1439 while (i < len)
1440 {
1441 int thislen = PQmblen(txt + i, state->encoding);
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1233
1442
1443 /* first byte should always be okay... */
1444 newtxt[i] = txt[i];
1445 i++;
1446 while (--thislen > 0 && i < len)
1447 newtxt[i++] = (char) 0xFF;
1448 }
1449 }
1450
1451 return yy_scan_buffer(newtxt, len + 2, state->scanner);
1452}

References i, len, pg_malloc(), and PQmblen().

Referenced by psql_scan_setup(), and psqlscan_push_new_buffer().

◆ psqlscan_push_new_buffer()

void psqlscan_push_new_buffer ( PsqlScanState  state,
const char *  newstr,
const char *  varname 
)

Definition at line 1320 of file psqlscan.l.

1322{
1323 StackElem *stackelem;
1324
1325 stackelem = (StackElem *) pg_malloc(sizeof(StackElem));
1326
1327 /*
1328 * In current usage, the passed varname points at the current flex input
1329 * buffer; we must copy it before calling psqlscan_prepare_buffer()
1330 * because that will change the buffer state.
1331 */
1332 stackelem->varname = varname ? pg_strdup(varname) : NULL;
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
1333
1334 stackelem->buf = psqlscan_prepare_buffer(state, newstr, strlen(newstr),
1335 &stackelem->bufstring);
1336 state->curline = stackelem->bufstring;
1337 if (state->safe_encoding)
1338 {
1339 stackelem->origstring = NULL;
1340 state->refline = stackelem->bufstring;
1341 }
1342 else
1343 {
1344 stackelem->origstring = pg_strdup(newstr);
1345 state->refline = stackelem->origstring;
1346 }
1347 stackelem->next = state->buffer_stack;
1348 state->buffer_stack = stackelem;
1349}

References StackElem::buf, StackElem::bufstring, StackElem::next, StackElem::origstring, pg_malloc(), pg_strdup(), psqlscan_prepare_buffer(), and StackElem::varname.

◆ psqlscan_select_top_buffer()

void psqlscan_select_top_buffer ( PsqlScanState  state)

Definition at line 1377 of file psqlscan.l.

1378{
1379 StackElem *stackelem = state->buffer_stack;
1380
1381 if (stackelem != NULL)
1382 {
1383 yy_switch_to_buffer(stackelem->buf, state->scanner);
1384 state->curline = stackelem->bufstring;
1385 state->refline = stackelem->origstring ? stackelem->origstring : stackelem->bufstring;
1386 }
1387 else
1388 {
1389 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1390 state->curline = state->scanbuf;
1391 state->refline = state->scanline;
1392 }
1393}

References StackElem::buf, StackElem::bufstring, and StackElem::origstring.

◆ psqlscan_test_variable()

void psqlscan_test_variable ( PsqlScanState  state,
const char *  txt,
int  len 
)

Definition at line 1560 of file psqlscan.l.

1561{
1562 char *varname;
1563 char *value;
1564
1565 varname = psqlscan_extract_substring(state, txt + 3, len - 4);
1566 if (state->callbacks->get_variable)
1567 value = state->callbacks->get_variable(varname, PQUOTE_PLAIN,
1568 state->cb_passthrough);
1569 else
1570 value = NULL;
1571 free(varname);
@ PQUOTE_PLAIN
Definition: psqlscan.h:54
1572
1573 if (value != NULL)
1574 {
1575 psqlscan_emit(state, "TRUE", 4);
1576 free(value);
1577 }
1578 else
1579 {
1580 psqlscan_emit(state, "FALSE", 5);
1581 }
1582}

References free, len, PQUOTE_PLAIN, psqlscan_emit(), psqlscan_extract_substring(), and value.

◆ psqlscan_var_is_current_source()

bool psqlscan_var_is_current_source ( PsqlScanState  state,
const char *  varname 
)

Definition at line 1400 of file psqlscan.l.

1401{
1402 StackElem *stackelem;
1403
1404 for (stackelem = state->buffer_stack;
1405 stackelem != NULL;
1406 stackelem = stackelem->next)
1407 {
1408 if (stackelem->varname && strcmp(stackelem->varname, varname) == 0)
1409 return true;
1410 }
1411 return false;
1412}

References StackElem::next, and StackElem::varname.

◆ yylex()

int yylex ( YYSTYPE yylval_param,
yyscan_t  yyscanner 
)

Definition at line 385 of file psqlscan.l.

387 {
388 /* Declare some local variables inside yylex(), for convenience */
389 PsqlScanState cur_state = yyextra;
390 PQExpBuffer output_buf = cur_state->output_buf;
#define yyextra
Definition: scan.l:1118
PQExpBuffer output_buf
Definition: psqlscan_int.h:88
391
392 /*
393 * Force flex into the state indicated by start_state. This has a
394 * couple of purposes: it lets some of the functions below set a new
395 * starting state without ugly direct access to flex variables, and it
396 * allows us to transition from one flex lexer to another so that we
397 * can lex different parts of the source string using separate lexers.
398 */
399 BEGIN(cur_state->start_state);
400%}
401
402{whitespace} {
403 /*
404 * Note that the whitespace rule includes both true
405 * whitespace and single-line ("--" style) comments.
406 * We suppress whitespace until we have collected some
407 * non-whitespace data. (This interacts with some
408 * decisions in MainLoop(); see there for details.)
409 */
410 if (output_buf->len > 0)
411 ECHO;
412 }
#define ECHO
Definition: psqlscan.l:62
413
414{xcstart} {
415 cur_state->xcdepth = 0;
416 BEGIN(xc);
417 /* Put back any characters past slash-star; see above */
418 yyless(2);
419 ECHO;
420 }
421
422<xc>{
423{xcstart} {
424 cur_state->xcdepth++;
425 /* Put back any characters past slash-star; see above */
426 yyless(2);
427 ECHO;
428 }
429
430{xcstop} {
431 if (cur_state->xcdepth <= 0)
432 BEGIN(INITIAL);
433 else
434 cur_state->xcdepth--;
435 ECHO;
436 }
437
438{xcinside} {
439 ECHO;
440 }
441
442{op_chars} {
443 ECHO;
444 }
445
446\*+ {
447 ECHO;
448 }
449} /* <xc> */
450
451{xbstart} {
452 BEGIN(xb);
453 ECHO;
454 }
455<xh>{xhinside} |
456<xb>{xbinside} {
457 ECHO;
458 }
459
460{xhstart} {
461 /* Hexadecimal bit type.
462 * At some point we should simply pass the string
463 * forward to the parser and label it there.
464 * In the meantime, place a leading "x" on the string
465 * to mark it for the input routine as a hex string.
466 */
467 BEGIN(xh);
468 ECHO;
469 }
470
471{xnstart} {
472 yyless(1); /* eat only 'n' this time */
473 ECHO;
474 }
475
476{xqstart} {
477 if (cur_state->std_strings)
478 BEGIN(xq);
479 else
480 BEGIN(xe);
481 ECHO;
482 }
483{xestart} {
484 BEGIN(xe);
485 ECHO;
486 }
487{xusstart} {
488 BEGIN(xus);
489 ECHO;
490 }
491
492<xb,xh,xq,xe,xus>{quote} {
493 /*
494 * When we are scanning a quoted string and see an end
495 * quote, we must look ahead for a possible continuation.
496 * If we don't see one, we know the end quote was in fact
497 * the end of the string. To reduce the lexer table size,
498 * we use a single "xqs" state to do the lookahead for all
499 * types of strings.
500 */
501 cur_state->state_before_str_stop = YYSTATE;
502 BEGIN(xqs);
503 ECHO;
504 }
505<xqs>{quotecontinue} {
506 /*
507 * Found a quote continuation, so return to the in-quote
508 * state and continue scanning the literal. Nothing is
509 * added to the literal's contents.
510 */
511 BEGIN(cur_state->state_before_str_stop);
512 ECHO;
513 }
514<xqs>{quotecontinuefail} |
515<xqs>{other} {
516 /*
517 * Failed to see a quote continuation. Throw back
518 * everything after the end quote, and handle the string
519 * according to the state we were in previously.
520 */
521 yyless(0);
522 BEGIN(INITIAL);
523 /* There's nothing to echo ... */
524 }
525
526<xq,xe,xus>{xqdouble} {
527 ECHO;
528 }
529<xq,xus>{xqinside} {
530 ECHO;
531 }
532<xe>{xeinside} {
533 ECHO;
534 }
535<xe>{xeunicode} {
536 ECHO;
537 }
538<xe>{xeunicodefail} {
539 ECHO;
540 }
541<xe>{xeescape} {
542 ECHO;
543 }
544<xe>{xeoctesc} {
545 ECHO;
546 }
547<xe>{xehexesc} {
548 ECHO;
549 }
550<xe>. {
551 /* This is only needed for \ just before EOF */
552 ECHO;
553 }
554
555{dolqdelim} {
556 cur_state->dolqstart = pg_strdup(yytext);
557 BEGIN(xdolq);
558 ECHO;
559 }
560{dolqfailed} {
561 /* throw back all but the initial "$" */
562 yyless(1);
563 ECHO;
564 }
565<xdolq>{dolqdelim} {
566 if (strcmp(yytext, cur_state->dolqstart) == 0)
567 {
568 free(cur_state->dolqstart);
569 cur_state->dolqstart = NULL;
570 BEGIN(INITIAL);
571 }
572 else
573 {
574 /*
575 * When we fail to match $...$ to dolqstart, transfer
576 * the $... part to the output, but put back the final
577 * $ for rescanning. Consider $delim$...$junk$delim$
578 */
579 yyless(yyleng - 1);
580 }
581 ECHO;
582 }
#define yyleng
Definition: scan.l:1124
583<xdolq>{dolqinside} {
584 ECHO;
585 }
586<xdolq>{dolqfailed} {
587 ECHO;
588 }
589<xdolq>. {
590 /* This is only needed for $ inside the quoted text */
591 ECHO;
592 }
593
594{xdstart} {
595 BEGIN(xd);
596 ECHO;
597 }
598{xuistart} {
599 BEGIN(xui);
600 ECHO;
601 }
602<xd>{xdstop} {
603 BEGIN(INITIAL);
604 ECHO;
605 }
606<xui>{dquote} {
607 BEGIN(INITIAL);
608 ECHO;
609 }
610<xd,xui>{xddouble} {
611 ECHO;
612 }
613<xd,xui>{xdinside} {
614 ECHO;
615 }
616
617{xufailed} {
618 /* throw back all but the initial u/U */
619 yyless(1);
620 ECHO;
621 }
622
623{typecast} {
624 ECHO;
625 }
626
627{dot_dot} {
628 ECHO;
629 }
630
631{colon_equals} {
632 ECHO;
633 }
634
635{equals_greater} {
636 ECHO;
637 }
638
639{less_equals} {
640 ECHO;
641 }
642
643{greater_equals} {
644 ECHO;
645 }
646
647{less_greater} {
648 ECHO;
649 }
650
651{not_equals} {
652 ECHO;
653 }
654
655 /*
656 * These rules are specific to psql --- they implement parenthesis
657 * counting and detection of command-ending semicolon. These must
658 * appear before the {self} rule so that they take precedence over it.
659 */
660
661"(" {
662 cur_state->paren_depth++;
663 ECHO;
664 }
665
666")" {
667 if (cur_state->paren_depth > 0)
668 cur_state->paren_depth--;
669 ECHO;
670 }
671
672";" {
673 ECHO;
674 if (cur_state->paren_depth == 0 && cur_state->begin_depth == 0)
675 {
676 /* Terminate lexing temporarily */
677 cur_state->start_state = YY_START;
678 cur_state->identifier_count = 0;
679 return LEXRES_SEMI;
680 }
681 }
682
683 /*
684 * psql-specific rules to handle backslash commands and variable
685 * substitution. We want these before {self}, also.
686 */
687
688"\\"[;:] {
689 /* Force a semi-colon or colon into the query buffer */
690 psqlscan_emit(cur_state, yytext + 1, 1);
691 if (yytext[1] == ';')
692 cur_state->identifier_count = 0;
693 }
694
695"\\" {
696 /* Terminate lexing temporarily */
697 cur_state->start_state = YY_START;
698 return LEXRES_BACKSLASH;
699 }
700
701:{variable_char}+ {
702 /* Possible psql variable substitution */
703 char *varname;
704 char *value;
705
706 varname = psqlscan_extract_substring(cur_state,
707 yytext + 1,
708 yyleng - 1);
709 if (cur_state->callbacks->get_variable)
710 value = cur_state->callbacks->get_variable(varname,
712 cur_state->cb_passthrough);
713 else
714 value = NULL;
715
716 if (value)
717 {
718 /* It is a variable, check for recursion */
719 if (psqlscan_var_is_current_source(cur_state, varname))
720 {
721 /* Recursive expansion --- don't go there */
722 pg_log_warning("skipping recursive expansion of variable \"%s\"",
723 varname);
724 /* Instead copy the string as is */
725 ECHO;
726 }
727 else
728 {
729 /* OK, perform substitution */
730 psqlscan_push_new_buffer(cur_state, value, varname);
731 /* yy_scan_string already made buffer active */
732 }
733 free(value);
734 }
735 else
736 {
737 /*
738 * if the variable doesn't exist we'll copy the string
739 * as is
740 */
741 ECHO;
742 }
#define pg_log_warning(...)
Definition: pgfnames.c:24
void psqlscan_push_new_buffer(PsqlScanState state, const char *newstr, const char *varname)
Definition: psqlscan.l:1320
bool psqlscan_var_is_current_source(PsqlScanState state, const char *varname)
Definition: psqlscan.l:1400
743
744 free(varname);
745 }
746
747:'{variable_char}+' {
748 psqlscan_escape_variable(cur_state, yytext, yyleng,
750 }
@ PQUOTE_SQL_LITERAL
Definition: psqlscan.h:55
void psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, PsqlScanQuoteType quote)
Definition: psqlscan.l:1531
751
752:\"{variable_char}+\" {
753 psqlscan_escape_variable(cur_state, yytext, yyleng,
755 }
@ PQUOTE_SQL_IDENT
Definition: psqlscan.h:56
756
757:\{\?{variable_char}+\} {
758 psqlscan_test_variable(cur_state, yytext, yyleng);
759 }
void psqlscan_test_variable(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1560
760
761 /*
762 * These rules just avoid the need for scanner backup if one of the
763 * three rules above fails to match completely.
764 */
765
766:'{variable_char}* {
767 /* Throw back everything but the colon */
768 yyless(1);
769 ECHO;
770 }
771
772:\"{variable_char}* {
773 /* Throw back everything but the colon */
774 yyless(1);
775 ECHO;
776 }
777
778:\{\?{variable_char}* {
779 /* Throw back everything but the colon */
780 yyless(1);
781 ECHO;
782 }
783:\{ {
784 /* Throw back everything but the colon */
785 yyless(1);
786 ECHO;
787 }
788
789 /*
790 * Back to backend-compatible rules.
791 */
792
793{self} {
794 ECHO;
795 }
796
797{operator} {
798 /*
799 * Check for embedded slash-star or dash-dash; those
800 * are comment starts, so operator must stop there.
801 * Note that slash-star or dash-dash at the first
802 * character will match a prior rule, not this one.
803 */
804 int nchars = yyleng;
805 char *slashstar = strstr(yytext, "/*");
806 char *dashdash = strstr(yytext, "--");
807
808 if (slashstar && dashdash)
809 {
810 /* if both appear, take the first one */
811 if (slashstar > dashdash)
812 slashstar = dashdash;
813 }
814 else if (!slashstar)
815 slashstar = dashdash;
816 if (slashstar)
817 nchars = slashstar - yytext;
818
819 /*
820 * For SQL compatibility, '+' and '-' cannot be the
821 * last char of a multi-char operator unless the operator
822 * contains chars that are not in SQL operators.
823 * The idea is to lex '=-' as two operators, but not
824 * to forbid operator names like '?-' that could not be
825 * sequences of SQL operators.
826 */
827 if (nchars > 1 &&
828 (yytext[nchars - 1] == '+' ||
829 yytext[nchars - 1] == '-'))
830 {
831 int ic;
832
833 for (ic = nchars - 2; ic >= 0; ic--)
834 {
835 char c = yytext[ic];
836 if (c == '~' || c == '!' || c == '@' ||
837 c == '#' || c == '^' || c == '&' ||
838 c == '|' || c == '`' || c == '?' ||
839 c == '%')
840 break;
841 }
842 if (ic < 0)
843 {
844 /*
845 * didn't find a qualifying character, so remove
846 * all trailing [+-]
847 */
848 do {
849 nchars--;
850 } while (nchars > 1 &&
851 (yytext[nchars - 1] == '+' ||
852 yytext[nchars - 1] == '-'));
853 }
854 }
char * c
855
856 if (nchars < yyleng)
857 {
858 /* Strip the unwanted chars from the token */
859 yyless(nchars);
860 }
861 ECHO;
862 }
863
864{param} {
865 ECHO;
866 }
867{param_junk} {
868 ECHO;
869 }
870
871{decinteger} {
872 ECHO;
873 }
874{hexinteger} {
875 ECHO;
876 }
877{octinteger} {
878 ECHO;
879 }
880{bininteger} {
881 ECHO;
882 }
883{hexfail} {
884 ECHO;
885 }
886{octfail} {
887 ECHO;
888 }
889{binfail} {
890 ECHO;
891 }
892{numeric} {
893 ECHO;
894 }
895{numericfail} {
896 /* throw back the .., and treat as integer */
897 yyless(yyleng - 2);
898 ECHO;
899 }
900{real} {
901 ECHO;
902 }
903{realfail} {
904 ECHO;
905 }
906{integer_junk} {
907 ECHO;
908 }
909{numeric_junk} {
910 ECHO;
911 }
912{real_junk} {
913 ECHO;
914 }
915
916
917{identifier} {
918 /*
919 * We need to track if we are inside a BEGIN .. END block
920 * in a function definition, so that semicolons contained
921 * therein don't terminate the whole statement. Short of
922 * writing a full parser here, the following heuristic
923 * should work. First, we track whether the beginning of
924 * the statement matches CREATE [OR REPLACE]
925 * {FUNCTION|PROCEDURE}
926 */
927
928 if (cur_state->identifier_count == 0)
929 memset(cur_state->identifiers, 0, sizeof(cur_state->identifiers));
930
931 if (pg_strcasecmp(yytext, "create") == 0 ||
932 pg_strcasecmp(yytext, "function") == 0 ||
933 pg_strcasecmp(yytext, "procedure") == 0 ||
934 pg_strcasecmp(yytext, "or") == 0 ||
935 pg_strcasecmp(yytext, "replace") == 0)
936 {
937 if (cur_state->identifier_count < sizeof(cur_state->identifiers))
938 cur_state->identifiers[cur_state->identifier_count] = pg_tolower((unsigned char) yytext[0]);
939 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
940
941 cur_state->identifier_count++;
942
943 if (cur_state->identifiers[0] == 'c' &&
944 (cur_state->identifiers[1] == 'f' || cur_state->identifiers[1] == 'p' ||
945 (cur_state->identifiers[1] == 'o' && cur_state->identifiers[2] == 'r' &&
946 (cur_state->identifiers[3] == 'f' || cur_state->identifiers[3] == 'p'))) &&
947 cur_state->paren_depth == 0)
948 {
949 if (pg_strcasecmp(yytext, "begin") == 0)
950 cur_state->begin_depth++;
951 else if (pg_strcasecmp(yytext, "case") == 0)
952 {
953 /*
954 * CASE also ends with END. We only need to track
955 * this if we are already inside a BEGIN.
956 */
957 if (cur_state->begin_depth >= 1)
958 cur_state->begin_depth++;
959 }
960 else if (pg_strcasecmp(yytext, "end") == 0)
961 {
962 if (cur_state->begin_depth > 0)
963 cur_state->begin_depth--;
964 }
965 }
966
967 ECHO;
968 }
969
970{other} {
971 ECHO;
972 }
973
974<<EOF>> {
975 if (cur_state->buffer_stack == NULL)
976 {
977 cur_state->start_state = YY_START;
978 return LEXRES_EOL; /* end of input reached */
979 }
980
981 /*
982 * We were expanding a variable, so pop the inclusion
983 * stack and keep lexing
984 */
985 psqlscan_pop_buffer_stack(cur_state);
987 }
void psqlscan_select_top_buffer(PsqlScanState state)
Definition: psqlscan.l:1377
988
989%%

Referenced by psql_scan().