PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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"

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 psql_scan_get_location (PsqlScanState state, int *lineno, int *offset)
 
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)
 
charpsqlscan_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

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

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 1133 of file psqlscan.l.

1136{
1138 int lexresult;
uint32 result
static int fb(int x)
PsqlScanResult
Definition psqlscan.h:31
1139
1140 /* Must be scanning already */
1141 Assert(state->scanbufhandle != NULL);
#define Assert(condition)
Definition c.h:943
1142
1143 /* Set current output target */
1144 state->output_buf = query_buf;
1145
1146 /* Set input source */
1147 if (state->buffer_stack != NULL)
1148 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
1149 else
1150 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1151
1152 /* And lex. */
1153 lexresult = yylex(NULL, state->scanner);
int yylex(void)
Definition pgc.l:465
1154
1155 /* Notify psql_scan_get_location() that a yylex call has been made. */
1156 if (state->cur_line_no == 0)
1157 state->cur_line_no = 1;
1158
1159 /*
1160 * Check termination state and return appropriate result info.
1161 */
1162 switch (lexresult)
1163 {
1164 case LEXRES_EOL: /* end of input */
1165 switch (state->start_state)
1166 {
1167 case INITIAL:
1168 case xqs: /* we treat this like INITIAL */
1169 if (state->paren_depth > 0)
1170 {
1173 }
1174 else if (state->begin_depth > 0)
1175 {
1178 }
1179 else if (query_buf->len > 0)
1180 {
1181 result = PSCAN_EOL;
1183 }
1184 else
1185 {
1186 /* never bother to send an empty buffer */
1189 }
1190 break;
1191 case xb:
1194 break;
1195 case xc:
1198 break;
1199 case xd:
1202 break;
1203 case xh:
1206 break;
1207 case xe:
1210 break;
1211 case xq:
1214 break;
1215 case xdolq:
1218 break;
1219 case xui:
1222 break;
1223 case xus:
1226 break;
1227 default:
1228 /* can't get here */
1229 fprintf(stderr, "invalid YY_START\n");
1230 exit(1);
1231 }
1232 break;
1233 case LEXRES_SEMI: /* semicolon */
1236 break;
1237 case LEXRES_BACKSLASH: /* backslash */
1240 break;
1241 default:
1242 /* can't get here */
1243 fprintf(stderr, "invalid yylex result\n");
1244 exit(1);
1245 }
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
@ 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
1246
1247 return result;
1248}

References Assert, fb(), fprintf, 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, result, and yylex().

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

◆ psql_scan_create()

PsqlScanState psql_scan_create ( const PsqlScanCallbacks callbacks)

Definition at line 1013 of file psqlscan.l.

1014{
1016
#define pg_malloc0_object(type)
Definition fe_memutils.h:51
1018
1019 state->callbacks = callbacks;
1020
1021 yylex_init(&state->scanner);
1022
1023 yyset_extra(state, state->scanner);
1024
void psql_scan_reset(PsqlScanState state)
Definition psqlscan.l:1287
1026
1027 return state;
1028}

References fb(), pg_malloc0_object, and psql_scan_reset().

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

◆ psql_scan_destroy()

void psql_scan_destroy ( PsqlScanState  state)

Definition at line 1034 of file psqlscan.l.

1035{
void psql_scan_finish(PsqlScanState state)
Definition psqlscan.l:1260
1037
1039
1040 yylex_destroy(state->scanner);
1041
1042 free(state);
#define free(a)
1043}

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

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

◆ psql_scan_finish()

void psql_scan_finish ( PsqlScanState  state)

Definition at line 1260 of file psqlscan.l.

1261{
1262 /* Drop any incomplete variable expansions. */
1263 while (state->buffer_stack != NULL)
void psqlscan_pop_buffer_stack(PsqlScanState state)
Definition psqlscan.l:1425
1265
1266 /* Done with the outer scan buffer, too */
1267 if (state->scanbufhandle)
1268 yy_delete_buffer(state->scanbufhandle, state->scanner);
1269 state->scanbufhandle = NULL;
1270 if (state->scanbuf)
1271 free(state->scanbuf);
1272 state->scanbuf = NULL;
1273}

References fb(), free, and psqlscan_pop_buffer_stack().

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

◆ psql_scan_get_location()

void psql_scan_get_location ( PsqlScanState  state,
int lineno,
int offset 
)

Definition at line 1347 of file psqlscan.l.

1349{
1350 const char *line_end;
1351
1352 /*
1353 * We rely on flex's having stored a NUL after the current token in
1354 * scanbuf. Therefore we must specially handle the state before yylex()
1355 * has been called, when obviously that won't have happened yet.
1356 */
1357 if (state->cur_line_no == 0)
1358 {
1359 *lineno = 1;
1360 *offset = 0;
1361 return;
1362 }
1363
1364 /*
1365 * Advance cur_line_no/cur_line_ptr past whatever has been lexed so far.
1366 * Doing this prevents repeated calls from being O(N^2) for long inputs.
1367 */
1368 while ((line_end = strchr(state->cur_line_ptr, '\n')) != NULL)
1369 {
1370 state->cur_line_no++;
1371 state->cur_line_ptr = line_end + 1;
1372 }
1373 state->cur_line_ptr += strlen(state->cur_line_ptr);
1374
1375 /* Report current location. */
1376 *lineno = state->cur_line_no;
1377 *offset = state->cur_line_ptr - state->scanbuf;
1378}

References fb().

Referenced by expr_lex_one_word(), expr_yyerror_more(), and ParseScript().

◆ psql_scan_in_quote()

bool psql_scan_in_quote ( PsqlScanState  state)

Definition at line 1328 of file psqlscan.l.

1329{
1330 return state->start_state != INITIAL &&
1331 state->start_state != xqs;
1332}

References fb().

Referenced by MainLoop().

◆ psql_scan_reselect_sql_lexer()

void psql_scan_reselect_sql_lexer ( PsqlScanState  state)

Definition at line 1315 of file psqlscan.l.

1316{
1317 state->start_state = INITIAL;
1318}

References fb().

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 1287 of file psqlscan.l.

1288{
1289 state->start_state = INITIAL;
1290 state->paren_depth = 0;
1291 state->xcdepth = 0; /* not really necessary */
1292 if (state->dolqstart)
1293 free(state->dolqstart);
1294 state->dolqstart = NULL;
1295 state->identifier_count = 0;
1296 state->begin_depth = 0;
1297}

References fb(), and 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 1053 of file psqlscan.l.

1054{
1055 state->cb_passthrough = passthrough;
1056}

References fb().

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 1071 of file psqlscan.l.

1074{
1075 /* Mustn't be scanning already */
1076 Assert(state->scanbufhandle == NULL);
1077 Assert(state->buffer_stack == NULL);
1078
1079 /* Do we need to hack the character set encoding? */
1080 state->encoding = encoding;
1081 state->safe_encoding = pg_valid_server_encoding_id(encoding);
static char * encoding
Definition initdb.c:139
#define pg_valid_server_encoding_id
Definition pg_wchar.h:485
1082
1083 /* Save standard-strings flag as well */
1084 state->std_strings = std_strings;
1085
1086 /* Set up flex input buffer with appropriate translation and padding */
1087 state->scanbufhandle = psqlscan_prepare_buffer(state, line, line_len,
1088 &state->scanbuf);
1089 state->scanline = line;
YY_BUFFER_STATE psqlscan_prepare_buffer(PsqlScanState state, const char *txt, int len, char **txtcopy)
Definition psqlscan.l:1488
1090
1091 /* Set lookaside data in case we have to map unsafe encoding */
1092 state->curline = state->scanbuf;
1093 state->refline = state->scanline;
1094
1095 /* Initialize state for psql_scan_get_location() */
1096 state->cur_line_no = 0; /* yylex not called yet */
1097 state->cur_line_ptr = state->scanbuf;
1098}

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

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

◆ psqlscan_emit()

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

Definition at line 1529 of file psqlscan.l.

1530{
1531 PQExpBuffer output_buf = state->output_buf;
1532
1533 if (state->safe_encoding)
1534 appendBinaryPQExpBuffer(output_buf, txt, len);
1535 else
1536 {
1537 /* Gotta do it the hard way */
1538 const char *reference = state->refline;
1539 int i;
int i
Definition isn.c:77
const void size_t len
void appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
1540
1541 reference += (txt - state->curline);
1542
1543 for (i = 0; i < len; i++)
1544 {
1545 char ch = txt[i];
1546
1547 if (ch == (char) 0xFF)
1548 ch = reference[i];
1549 appendPQExpBufferChar(output_buf, ch);
1550 }
1551 }
void appendPQExpBufferChar(PQExpBuffer str, char ch)
1552}

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

Referenced by psqlscan_escape_variable().

◆ psqlscan_escape_variable()

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

Definition at line 1597 of file psqlscan.l.

1599{
1600 char *varname;
1601 char *value;
static struct @177 value
1602
1603 /* Variable lookup. */
1604 varname = psqlscan_extract_substring(state, txt + 2, len - 3);
1605 if (state->callbacks->get_variable)
1606 value = state->callbacks->get_variable(varname, quote,
1607 state->cb_passthrough);
1608 else
1609 value = NULL;
1610 free(varname);
char * psqlscan_extract_substring(PsqlScanState state, const char *txt, int len)
Definition psqlscan.l:1561
1611
1612 if (value)
1613 {
1614 /* Emit the suitably-escaped value */
1615 appendPQExpBufferStr(state->output_buf, value);
1616 free(value);
1617 }
1618 else
1619 {
1620 /* Emit original token as-is */
1622 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void psqlscan_emit(PsqlScanState state, const char *txt, int len)
Definition psqlscan.l:1529
1623}

References appendPQExpBufferStr(), fb(), 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 1561 of file psqlscan.l.

1562{
1563 char *result = pg_malloc_array(char, (len + 1));
#define pg_malloc_array(type, count)
Definition fe_memutils.h:56
1564
1565 if (state->safe_encoding)
1566 memcpy(result, txt, len);
1567 else
1568 {
1569 /* Gotta do it the hard way */
1570 const char *reference = state->refline;
1571 int i;
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
1572
1573 reference += (txt - state->curline);
1574
1575 for (i = 0; i < len; i++)
1576 {
1577 char ch = txt[i];
1578
1579 if (ch == (char) 0xFF)
1580 ch = reference[i];
1581 result[i] = ch;
1582 }
1583 }
1584 result[len] = '\0';
1585 return result;
1586}

References fb(), i, len, memcpy(), pg_malloc_array, and result.

Referenced by psqlscan_escape_variable(), and psqlscan_test_variable().

◆ psqlscan_pop_buffer_stack()

void psqlscan_pop_buffer_stack ( PsqlScanState  state)

Definition at line 1425 of file psqlscan.l.

1426{
1427 StackElem *stackelem = state->buffer_stack;
1428
1429 state->buffer_stack = stackelem->next;
1430 yy_delete_buffer(stackelem->buf, state->scanner);
1431 free(stackelem->bufstring);
1432 if (stackelem->origstring)
1433 free(stackelem->origstring);
1434 if (stackelem->varname)
1435 free(stackelem->varname);
1436 free(stackelem);
struct state * next
Definition regguts.h:332
1437}

References fb(), free, and state::next.

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 1488 of file psqlscan.l.

1490{
1491 char *newtxt;
1492
1493 /* Flex wants two \0 characters after the actual data */
1494 newtxt = pg_malloc_array(char, (len + 2));
1495 *txtcopy = newtxt;
1497
1498 if (state->safe_encoding)
1499 memcpy(newtxt, txt, len);
1500 else
1501 {
1502 /* Gotta do it the hard way */
1503 int i = 0;
1504
1505 while (i < len)
1506 {
1507 int thislen = PQmblen(txt + i, state->encoding);
int PQmblen(const char *s, int encoding)
Definition fe-misc.c:1255
1508
1509 /* first byte should always be okay... */
1510 newtxt[i] = txt[i];
1511 i++;
1512 while (--thislen > 0 && i < len)
1513 newtxt[i++] = (char) 0xFF;
1514 }
1515 }
1516
1517 return yy_scan_buffer(newtxt, len + 2, state->scanner);
1518}

References fb(), i, len, memcpy(), pg_malloc_array, 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 1386 of file psqlscan.l.

1388{
1390
#define pg_malloc_object(type)
Definition fe_memutils.h:50
1392
1393 /*
1394 * In current usage, the passed varname points at the current flex input
1395 * buffer; we must copy it before calling psqlscan_prepare_buffer()
1396 * because that will change the buffer state.
1397 */
1398 stackelem->varname = varname ? pg_strdup(varname) : NULL;
char * pg_strdup(const char *in)
Definition fe_memutils.c:85
1399
1401 &stackelem->bufstring);
1402 state->curline = stackelem->bufstring;
1403 if (state->safe_encoding)
1404 {
1405 stackelem->origstring = NULL;
1406 state->refline = stackelem->bufstring;
1407 }
1408 else
1409 {
1410 stackelem->origstring = pg_strdup(newstr);
1411 state->refline = stackelem->origstring;
1412 }
1413 stackelem->next = state->buffer_stack;
1414 state->buffer_stack = stackelem;
1415}

References fb(), state::next, pg_malloc_object, pg_strdup(), and psqlscan_prepare_buffer().

◆ psqlscan_select_top_buffer()

void psqlscan_select_top_buffer ( PsqlScanState  state)

Definition at line 1443 of file psqlscan.l.

1444{
1445 StackElem *stackelem = state->buffer_stack;
1446
1447 if (stackelem != NULL)
1448 {
1449 yy_switch_to_buffer(stackelem->buf, state->scanner);
1450 state->curline = stackelem->bufstring;
1451 state->refline = stackelem->origstring ? stackelem->origstring : stackelem->bufstring;
1452 }
1453 else
1454 {
1455 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1456 state->curline = state->scanbuf;
1457 state->refline = state->scanline;
1458 }
1459}

References fb().

◆ psqlscan_test_variable()

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

Definition at line 1626 of file psqlscan.l.

1627{
1628 char *varname;
1629 char *value;
1630
1631 varname = psqlscan_extract_substring(state, txt + 3, len - 4);
1632 if (state->callbacks->get_variable)
1633 value = state->callbacks->get_variable(varname, PQUOTE_PLAIN,
1634 state->cb_passthrough);
1635 else
1636 value = NULL;
1637 free(varname);
@ PQUOTE_PLAIN
Definition psqlscan.h:54
1638
1639 if (value != NULL)
1640 {
1641 appendPQExpBufferStr(state->output_buf, "TRUE");
1642 free(value);
1643 }
1644 else
1645 {
1646 appendPQExpBufferStr(state->output_buf, "FALSE");
1647 }
1648}

References appendPQExpBufferStr(), fb(), free, len, PQUOTE_PLAIN, psqlscan_extract_substring(), and value.

◆ psqlscan_var_is_current_source()

bool psqlscan_var_is_current_source ( PsqlScanState  state,
const char varname 
)

Definition at line 1466 of file psqlscan.l.

1467{
1469
1470 for (stackelem = state->buffer_stack;
1471 stackelem != NULL;
1472 stackelem = stackelem->next)
1473 {
1474 if (stackelem->varname && strcmp(stackelem->varname, varname) == 0)
1475 return true;
1476 }
1477 return false;
1478}

References fb().

◆ yylex()

int yylex ( YYSTYPE yylval_param,
yyscan_t  yyscanner 
)

Definition at line 387 of file psqlscan.l.

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