next token that syntactically cannot belong to the preceding
command starts a new one. (Usually you would put a new command on
a new line, for clarity.) Tokens can be certain key words, special
- characters (parentheses, commas, etc.), numbers, or double-quoted
- strings. Everything is case sensitive.
+ characters (parentheses, commas, etc.), identifiers, numbers, or
+ single-quoted strings. Everything is case sensitive.
NULL values can be specified using the special key word
_null_. Values that do not look like
- identifiers or digit strings must be double quoted.
+ identifiers or digit strings must be single-quoted.
+ (To include a single quote in a value, write it twice.
+ Escape-string-style backslash escapes are allowed in the string, too.)
create test_table 420 (oid = oid, cola = int4, colb = text)
open test_table
-insert ( 421 1 "value1" )
+insert ( 421 1 'value 1' )
insert ( 422 2 _null_ )
close test_table
#include
-#include "access/attnum.h"
-#include "access/htup.h"
-#include "access/itup.h"
-#include "access/tupdesc.h"
#include "bootstrap/bootstrap.h"
-#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/namespace.h"
#include "catalog/pg_am.h"
-#include "catalog/pg_attribute.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_class.h"
#include "catalog/pg_namespace.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
-#include "nodes/nodes.h"
-#include "nodes/parsenodes.h"
-#include "nodes/pg_list.h"
-#include "nodes/primnodes.h"
-#include "rewrite/prs2lock.h"
-#include "storage/block.h"
-#include "storage/fd.h"
-#include "storage/ipc.h"
-#include "storage/itemptr.h"
-#include "storage/off.h"
-#include "storage/smgr.h"
-#include "tcop/dest.h"
#include "utils/memutils.h"
-#include "utils/rel.h"
/*
*/
#include "postgres.h"
-#include "access/attnum.h"
-#include "access/htup.h"
-#include "access/itup.h"
-#include "access/tupdesc.h"
#include "bootstrap/bootstrap.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_attribute.h"
-#include "catalog/pg_class.h"
-#include "nodes/nodes.h"
-#include "nodes/parsenodes.h"
-#include "nodes/pg_list.h"
-#include "nodes/primnodes.h"
-#include "parser/scansup.h"
-#include "rewrite/prs2lock.h"
-#include "storage/block.h"
-#include "storage/fd.h"
-#include "storage/itemptr.h"
-#include "storage/off.h"
-#include "utils/rel.h"
+#include "utils/guc.h"
/* Not needed now that this file is compiled as part of bootparse. */
/* #include "bootparse.h" */
id [-A-Za-z0-9_]+
-sid \"([^\"])*\"
+sid \'([^']|\'\')*\'
/*
* Keyword tokens return the keyword text (as a constant string) in yylval.kw,
NULL { yylval.kw = "NULL"; return XNULL; }
{id} {
- yylval.str = scanstr(yytext);
+ yylval.str = pstrdup(yytext);
return ID;
}
{sid} {
- /* leading and trailing quotes are not passed to scanstr */
- yytext[strlen(yytext) - 1] = '\0';
- yylval.str = scanstr(yytext+1);
- yytext[strlen(yytext)] = '"'; /* restore yytext */
+ /* strip quotes and escapes */
+ yylval.str = DeescapeQuotedString(yytext);
return ID;
}
# since that represents a NUL char in C code.
$bki_value = '' if $bki_value eq '\0';
- # Handle single quotes by doubling them, and double quotes by
- # converting them to octal escapes, because that's what the
+ # Handle single quotes by doubling them, because that's what the
# bootstrap scanner requires. We do not process backslashes
# specially; this allows escape-string-style backslash escapes
# to be used in catalog data.
$bki_value =~ s/'/''/g;
- $bki_value =~ s/"/\\042/g;
# Quote value if needed. We need not quote values that satisfy
# the "id" pattern in bootscanner.l, currently "[-A-Za-z0-9_]+".
- $bki_value = sprintf(qq'"%s"', $bki_value)
+ $bki_value = sprintf("'%s'", $bki_value)
if length($bki_value) == 0
or $bki_value =~ /[^-A-Za-z0-9_]/;
/*-------------------------------------------------------------------------
*
* scansup.c
- * support routines for the lex/flex scanner, used by both the normal
- * backend as well as the bootstrap backend
+ * scanner support routines used by the core lexer
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
#include "mb/pg_wchar.h"
#include "parser/scansup.h"
-/* ----------------
- * scanstr
- *
- * if the string passed in has escaped codes, map the escape codes to actual
- * chars
- *
- * the string returned is palloc'd and should eventually be pfree'd by the
- * caller!
- * ----------------
- */
-
-char *
-scanstr(const char *s)
-{
- char *newStr;
- int len,
- i,
- j;
-
- if (s == NULL || s[0] == '\0')
- return pstrdup("");
-
- len = strlen(s);
-
- newStr = palloc(len + 1); /* string cannot get longer */
-
- for (i = 0, j = 0; i < len; i++)
- {
- if (s[i] == '\'')
- {
- /*
- * Note: if scanner is working right, unescaped quotes can only
- * appear in pairs, so there should be another character.
- */
- i++;
- /* The bootstrap parser is not as smart, so check here. */
- Assert(s[i] == '\'');
- newStr[j] = s[i];
- }
- else if (s[i] == '\\')
- {
- i++;
- switch (s[i])
- {
- case 'b':
- newStr[j] = '\b';
- break;
- case 'f':
- newStr[j] = '\f';
- break;
- case 'n':
- newStr[j] = '\n';
- break;
- case 'r':
- newStr[j] = '\r';
- break;
- case 't':
- newStr[j] = '\t';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int k;
- long octVal = 0;
-
- for (k = 0;
- s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
- k++)
- octVal = (octVal << 3) + (s[i + k] - '0');
- i += k - 1;
- newStr[j] = ((char) octVal);
- }
- break;
- default:
- newStr[j] = s[i];
- break;
- } /* switch */
- } /* s[i] == '\\' */
- else
- newStr[j] = s[i];
- j++;
- }
- newStr[j] = '\0';
- return newStr;
-}
-
/*
* downcase_truncate_identifier() --- do appropriate downcasing and
ConfigVariable **tail_p);
static int GUC_flex_fatal(const char *msg);
-static char *GUC_scanstr(const char *s);
/* LCOV_EXCL_START */
token != GUC_UNQUOTED_STRING)
goto parse_error;
if (token == GUC_STRING) /* strip quotes and escapes */
- opt_value = GUC_scanstr(yytext);
+ opt_value = DeescapeQuotedString(yytext);
else
opt_value = pstrdup(yytext);
/*
- * scanstr
+ * DeescapeQuotedString
*
* Strip the quotes surrounding the given string, and collapse any embedded
* '' sequences and backslash escapes.
*
- * the string returned is palloc'd and should eventually be pfree'd by the
+ * The string returned is palloc'd and should eventually be pfree'd by the
* caller.
+ *
+ * This is exported because it is also used by the bootstrap scanner.
*/
-static char *
-GUC_scanstr(const char *s)
+char *
+DeescapeQuotedString(const char *s)
{
char *newStr;
int len,
i,
j;
+ /* We just Assert that there are leading and trailing quotes */
Assert(s != NULL && s[0] == '\'');
len = strlen(s);
Assert(len >= 2);
/*
* Escape a field value to be inserted into the BKI data.
- * Here, we first run the value through escape_quotes (which
- * will be inverted by the backend's scanstr() function) and
- * then overlay special processing of double quotes, which
- * bootscanner.l will only accept as data if converted to octal
- * representation ("\042"). We always wrap the value in double
- * quotes, even if that isn't strictly necessary.
+ * Run the value through escape_quotes (which will be inverted
+ * by the backend's DeescapeQuotedString() function), then wrap
+ * the value in single quotes, even if that isn't strictly necessary.
*/
static char *
escape_quotes_bki(const char *src)
char *data = escape_quotes(src);
char *resultp;
char *datap;
- int nquotes = 0;
- /* count double quotes in data */
- datap = data;
- while ((datap = strchr(datap, '"')) != NULL)
- {
- nquotes++;
- datap++;
- }
-
- result = (char *) pg_malloc(strlen(data) + 3 + nquotes * 3);
+ result = (char *) pg_malloc(strlen(data) + 3);
resultp = result;
- *resultp++ = '"';
+ *resultp++ = '\'';
for (datap = data; *datap; datap++)
- {
- if (*datap == '"')
- {
- strcpy(resultp, "\\042");
- resultp += 4;
- }
- else
- *resultp++ = *datap;
- }
- *resultp++ = '"';
+ *resultp++ = *datap;
+ *resultp++ = '\'';
*resultp = '\0';
free(data);
/*-------------------------------------------------------------------------
*
* scansup.h
- * scanner support routines. used by both the bootstrap lexer
- * as well as the normal lexer
+ * scanner support routines used by the core lexer
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
#ifndef SCANSUP_H
#define SCANSUP_H
-extern char *scanstr(const char *s);
-
extern char *downcase_truncate_identifier(const char *ident, int len,
bool warn);
ConfigVariable **head_p,
ConfigVariable **tail_p);
extern void FreeConfigVariables(ConfigVariable *list);
+extern char *DeescapeQuotedString(const char *s);
/*
* The possible values of an enum variable are specified by an array of