*** ./psqlscan.l.orig 2010-01-02 17:57:59.000000000 +0100 --- ./psqlscan.l 2010-01-21 17:51:33.556758460 +0100 *************** *** 119,124 **** --- 119,127 ---- static void emit(const char *txt, int len); static bool is_utf16_surrogate_first(uint32 c); + static void appendLiteral(PGconn *conn, PQExpBuffer buf, const char *str); + static void appendIdentifier(PGconn *conn, PQExpBuffer buf, const char *str); + #define ECHO emit(yytext, yyleng) %} *************** *** 706,711 **** --- 709,777 ---- ECHO; } } + + :'[A-Za-z0-9_]+' { + /* + * Possible psql variable substitution with + * literal escaping. + */ + const char *value; + + yytext[yyleng - 1] = '\0'; + value = GetVariable(pset.vars, yytext + 2); + + if (value) + { + /* It is a variable, perform substitution */ + PQExpBufferData buf; + + initPQExpBuffer(&buf); + appendLiteral(pset.db, &buf, value); + push_new_buffer(buf.data); + termPQExpBuffer(&buf); + + /* yy_scan_string already made buffer active */ + } + else + { + /* + * if the variable doesn't exist we'll copy the + * string as is + */ + ECHO; + } + } + + :\"[A-Za-z0-9_]+\" { + /* + * Possible psql variable substitution with + * identifier escaping. + */ + const char *value; + + yytext[yyleng - 1] = '\0'; + value = GetVariable(pset.vars, yytext + 2); + + if (value) + { + /* It is a variable, perform substitution */ + PQExpBufferData buf; + + initPQExpBuffer(&buf); + appendIdentifier(pset.db, &buf, value); + push_new_buffer(buf.data); + termPQExpBuffer(&buf); + /* yy_scan_string already made buffer active */ + } + else + { + /* + * if the variable doesn't exist we'll copy the + * string as is + */ + ECHO; + } + } /* * Back to backend-compatible rules. *************** *** 927,932 **** --- 993,1052 ---- return LEXRES_OK; } + + :'[A-Za-z0-9_]+' { + /* Possible psql variable substitution with literal escaping */ + if (option_type == OT_VERBATIM) + ECHO; + else + { + const char *value; + + yytext[yyleng - 1] = '\0'; + value = GetVariable(pset.vars, yytext + 2); + + /* + * The variable value is just emitted without any + * further examination. This is consistent with the + * pre-8.0 code behavior, if not with the way that + * variables are handled outside backslash commands. + */ + if (value) + appendLiteral(pset.db, output_buf, value); + } + + *option_quote = ':'; + + return LEXRES_OK; + } + + :\"[A-Za-z0-9_]+\" { + /* Possible psql variable substitution with identifier escaping */ + if (option_type == OT_VERBATIM) + ECHO; + else + { + const char *value; + + yytext[yyleng - 1] = '\0'; + value = GetVariable(pset.vars, yytext + 2); + + /* + * The variable value is just emitted without any + * further examination. This is consistent with the + * pre-8.0 code behavior, if not with the way that + * variables are handled outside backslash commands. + */ + if (value) + appendIdentifier(pset.db, output_buf, value); + } + + *option_quote = ':'; + + return LEXRES_OK; + } + + "|" { ECHO; if (option_type == OT_FILEPIPE) *************** *** 1740,1742 **** --- 1860,1916 ---- { return (c >= 0xD800 && c <= 0xDBFF); } + + /* + * Convert a string value to an SQL Literal and append it to + * the given buffer. + */ + static void + appendLiteral(PGconn *conn, PQExpBuffer buf, const char *str) + { + char *escaped_str; + size_t len; + + len = strlen(str); + escaped_str = PQescapeLiteral(conn, str, len); + + if (escaped_str == NULL) + { + const char *error_message = PQerrorMessage(pset.db); + + if (strlen(error_message)) + psql_error("%s", error_message); + } + else + { + appendPQExpBufferStr(buf, escaped_str); + free(escaped_str); + } + } + + /* + * Convert a string value to an SQL identifier and append it to + * the given buffer. + */ + static void + appendIdentifier(PGconn *conn, PQExpBuffer buf, const char *str) + { + char *escaped_str; + size_t len; + + len = strlen(str); + escaped_str = PQescapeIdentifier(conn, str, len); + + if (escaped_str == NULL) + { + const char *error_message = PQerrorMessage(pset.db); + + if (strlen(error_message)) + psql_error("%s", error_message); + } + else + { + appendPQExpBufferStr(buf, escaped_str); + free(escaped_str); + } + }