Made ecpg parser use backend provided keyword list.
Changed whenever test so exit value is 0.
- Check for non-existant connection in prepare statement handling.
- Do not close files that weren't opened.
+
+Tue, 20 May 2008 17:31:01 +0200
+
+ - Synced parser.
+ - Made ecpg parser use backend provided keyword list. One less file to
+ sync manually.
+ - Changed whenever test so exit value is 0.
- Set pgtypes library version to 3.1.
- Set compat library version to 3.1.
- Set ecpg library version to 6.2.
#
# Copyright (c) 1998-2008, PostgreSQL Global Development Group
#
-# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.132 2008/03/18 17:46:23 petere Exp $
+# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.133 2008/05/20 23:17:32 meskes Exp $
#
#-------------------------------------------------------------------------
override CFLAGS += $(PTHREAD_CFLAGS)
OBJS= preproc.o type.o ecpg.o output.o parser.o \
- keywords.o c_keywords.o ../ecpglib/typename.o descriptor.o variable.o \
+ keywords.o c_keywords.o ecpg_keywords.o ../ecpglib/typename.o descriptor.o variable.o \
$(WIN32RES)
all: submake-libpgport ecpg
c_keywords.o keywords.o preproc.o parser.o: preproc.h
+# instead of maintaining our own list, take the one from the backend
+# we cannot just link it in, but must copy and make some minor changes
+keywords.c: % : $(top_srcdir)/src/backend/parser/%
+ sed -e 's/#include "parser\/parse.h"/#include "preproc.h"/' $< > $@
+
distprep: $(srcdir)/preproc.c $(srcdir)/preproc.h $(srcdir)/pgc.c
install: all installdirs
rm -f '$(DESTDIR)$(bindir)/ecpg$(X)'
clean distclean:
- rm -f *.o ecpg$(X)
+ rm -f keywords.c *.o ecpg$(X)
# garbage from partial builds
@rm -f y.tab.c y.tab.h
# garbage from development
* keywords.c
* lexical token lookup for reserved words in postgres embedded SQL
*
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.21 2007/08/22 08:20:58 meskes Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.22 2008/05/20 23:17:32 meskes Exp $
* ยง
*-------------------------------------------------------------------------
*/
* search is used to locate entries.
*/
static const ScanKeyword ScanCKeywords[] = {
- /* name value */
- {"VARCHAR", VARCHAR},
- {"auto", S_AUTO},
- {"bool", SQL_BOOL},
- {"char", CHAR_P},
- {"const", S_CONST},
- {"enum", ENUM_P},
- {"extern", S_EXTERN},
- {"float", FLOAT_P},
- {"hour", HOUR_P},
- {"int", INT_P},
- {"long", SQL_LONG},
- {"minute", MINUTE_P},
- {"month", MONTH_P},
- {"register", S_REGISTER},
- {"second", SECOND_P},
- {"short", SQL_SHORT},
- {"signed", SQL_SIGNED},
- {"static", S_STATIC},
- {"struct", SQL_STRUCT},
- {"to", TO},
- {"typedef", S_TYPEDEF},
- {"union", UNION},
- {"unsigned", SQL_UNSIGNED},
- {"varchar", VARCHAR},
- {"volatile", S_VOLATILE},
- {"year", YEAR_P},
+ /* name, value, category */
+ /* category is not needed in ecpg, it is only here so we can share
+ * the data structure with the backend */
+ {"VARCHAR", VARCHAR, 0},
+ {"auto", S_AUTO, 0},
+ {"bool", SQL_BOOL, 0},
+ {"char", CHAR_P, 0},
+ {"const", S_CONST, 0},
+ {"enum", ENUM_P, 0},
+ {"extern", S_EXTERN, 0},
+ {"float", FLOAT_P, 0},
+ {"hour", HOUR_P, 0},
+ {"int", INT_P, 0},
+ {"long", SQL_LONG, 0},
+ {"minute", MINUTE_P, 0},
+ {"month", MONTH_P, 0},
+ {"register", S_REGISTER, 0},
+ {"second", SECOND_P, 0},
+ {"short", SQL_SHORT, 0},
+ {"signed", SQL_SIGNED, 0},
+ {"static", S_STATIC, 0},
+ {"struct", SQL_STRUCT, 0},
+ {"to", TO, 0},
+ {"typedef", S_TYPEDEF, 0},
+ {"union", UNION, 0},
+ {"unsigned", SQL_UNSIGNED, 0},
+ {"varchar", VARCHAR, 0},
+ {"volatile", S_VOLATILE, 0},
+ {"year", YEAR_P, 0},
};
const ScanKeyword *
-ScanCKeywordLookup(char *text)
+ScanCKeywordLookup(const char *text)
{
return DoLookup(text, &ScanCKeywords[0], endof(ScanCKeywords) - 1);
}
* lexical token lookup for reserved words in postgres embedded SQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.37 2007/11/15 21:14:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.38 2008/05/20 23:17:32 meskes Exp $
*
*-------------------------------------------------------------------------
*/
+#include "postgres_fe.h"
+
+#include <ctype.h>
+
+#include "extern.h"
+#include "preproc.h"
+
/*
* List of (keyword-name, keyword-token-value) pairs.
*
* search is used to locate entries.
*/
static const ScanKeyword ScanECPGKeywords[] = {
- /* name value */
- {"allocate", SQL_ALLOCATE},
- {"autocommit", SQL_AUTOCOMMIT},
- {"bool", SQL_BOOL},
- {"break", SQL_BREAK},
- {"call", SQL_CALL},
- {"cardinality", SQL_CARDINALITY},
- {"connect", SQL_CONNECT},
- {"continue", SQL_CONTINUE},
- {"count", SQL_COUNT},
- {"data", SQL_DATA},
- {"datetime_interval_code", SQL_DATETIME_INTERVAL_CODE},
- {"datetime_interval_precision", SQL_DATETIME_INTERVAL_PRECISION},
- {"describe", SQL_DESCRIBE},
- {"descriptor", SQL_DESCRIPTOR},
- {"disconnect", SQL_DISCONNECT},
- {"found", SQL_FOUND},
- {"free", SQL_FREE},
- {"go", SQL_GO},
- {"goto", SQL_GOTO},
- {"identified", SQL_IDENTIFIED},
- {"indicator", SQL_INDICATOR},
- {"key_member", SQL_KEY_MEMBER},
- {"length", SQL_LENGTH},
- {"long", SQL_LONG},
- {"nullable", SQL_NULLABLE},
- {"octet_length", SQL_OCTET_LENGTH},
- {"open", SQL_OPEN},
- {"output", SQL_OUTPUT},
- {"reference", SQL_REFERENCE},
- {"returned_length", SQL_RETURNED_LENGTH},
- {"returned_octet_length", SQL_RETURNED_OCTET_LENGTH},
- {"scale", SQL_SCALE},
- {"section", SQL_SECTION},
- {"short", SQL_SHORT},
- {"signed", SQL_SIGNED},
- {"sql", SQL_SQL}, /* strange thing, used for into sql descriptor
+ /* name, value, category */
+ /* category is not needed in ecpg, it is only here so we can share
+ * the data structure with the backend */
+ {"allocate", SQL_ALLOCATE, 0},
+ {"autocommit", SQL_AUTOCOMMIT, 0},
+ {"bool", SQL_BOOL, 0},
+ {"break", SQL_BREAK, 0},
+ {"call", SQL_CALL, 0},
+ {"cardinality", SQL_CARDINALITY, 0},
+ {"connect", SQL_CONNECT, 0},
+ {"count", SQL_COUNT, 0},
+ {"data", SQL_DATA, 0},
+ {"datetime_interval_code", SQL_DATETIME_INTERVAL_CODE, 0},
+ {"datetime_interval_precision", SQL_DATETIME_INTERVAL_PRECISION, 0},
+ {"describe", SQL_DESCRIBE, 0},
+ {"descriptor", SQL_DESCRIPTOR, 0},
+ {"disconnect", SQL_DISCONNECT, 0},
+ {"found", SQL_FOUND, 0},
+ {"free", SQL_FREE, 0},
+ {"get", SQL_GET, 0},
+ {"go", SQL_GO, 0},
+ {"goto", SQL_GOTO, 0},
+ {"identified", SQL_IDENTIFIED, 0},
+ {"indicator", SQL_INDICATOR, 0},
+ {"key_member", SQL_KEY_MEMBER, 0},
+ {"length", SQL_LENGTH, 0},
+ {"long", SQL_LONG, 0},
+ {"nullable", SQL_NULLABLE, 0},
+ {"octet_length", SQL_OCTET_LENGTH, 0},
+ {"open", SQL_OPEN, 0},
+ {"output", SQL_OUTPUT, 0},
+ {"reference", SQL_REFERENCE, 0},
+ {"returned_length", SQL_RETURNED_LENGTH, 0},
+ {"returned_octet_length", SQL_RETURNED_OCTET_LENGTH, 0},
+ {"scale", SQL_SCALE, 0},
+ {"section", SQL_SECTION, 0},
+ {"short", SQL_SHORT, 0},
+ {"signed", SQL_SIGNED, 0},
+ {"sql", SQL_SQL, 0}, /* strange thing, used for into sql descriptor
* MYDESC; */
- {"sqlerror", SQL_SQLERROR},
- {"sqlprint", SQL_SQLPRINT},
- {"sqlwarning", SQL_SQLWARNING},
- {"stop", SQL_STOP},
- {"struct", SQL_STRUCT},
- {"unsigned", SQL_UNSIGNED},
- {"var", SQL_VAR},
- {"whenever", SQL_WHENEVER},
+ {"sqlerror", SQL_SQLERROR, 0},
+ {"sqlprint", SQL_SQLPRINT, 0},
+ {"sqlwarning", SQL_SQLWARNING, 0},
+ {"stop", SQL_STOP, 0},
+ {"struct", SQL_STRUCT, 0},
+ {"unsigned", SQL_UNSIGNED, 0},
+ {"var", SQL_VAR, 0},
+ {"whenever", SQL_WHENEVER, 0},
};
+
+/* This is all taken from src/backend/parser/keyword.c and adjusted for our needs. */
+/*
+ * Do a binary search using plain strcmp() comparison.
+ */
+const ScanKeyword *
+DoLookup(const char *word, const ScanKeyword *low, const ScanKeyword *high)
+{
+ while (low <= high)
+ {
+ const ScanKeyword *middle;
+ int difference;
+
+ middle = low + (high - low) / 2;
+ difference = strcmp(middle->name, word);
+ if (difference == 0)
+ return middle;
+ else if (difference < 0)
+ low = middle + 1;
+ else
+ high = middle - 1;
+ }
+
+ return NULL;
+}
+
+/*
+ * ScanECPGKeywordLookup - see if a given word is a keyword
+ *
+ * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
+ *
+ * The match is done case-insensitively. Note that we deliberately use a
+ * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
+ * even if we are in a locale where tolower() would produce more or different
+ * translations. This is to conform to the SQL99 spec, which says that
+ * keywords are to be matched in this way even though non-keyword identifiers
+ * receive a different case-normalization mapping.
+ */
+const ScanKeyword *
+ScanECPGKeywordLookup(const char *text)
+{
+ int len,
+ i;
+ char word[NAMEDATALEN];
+ const ScanKeyword *res;
+
+ /* First check SQL symbols defined by the backend. */
+
+ res = ScanKeywordLookup(text);
+ if (res)
+ return res;
+
+ len = strlen(text);
+ /* We assume all keywords are shorter than NAMEDATALEN. */
+ if (len >= NAMEDATALEN)
+ return NULL;
+
+ /*
+ * Apply an ASCII-only downcasing. We must not use tolower() since it may
+ * produce the wrong translation in some locales (eg, Turkish).
+ */
+ for (i = 0; i < len; i++)
+ {
+ char ch = text[i];
+
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ word[i] = ch;
+ }
+ word[len] = '\0';
+
+ /*
+ * Now do a binary search using plain strcmp() comparison.
+ */
+
+ return DoLookup(word, &ScanECPGKeywords[0], endof(ScanECPGKeywords) - 1);
+}
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.70 2007/11/15 21:14:45 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.71 2008/05/20 23:17:32 meskes Exp $ */
#ifndef _ECPG_PREPROC_EXTERN_H
#define _ECPG_PREPROC_EXTERN_H
#include "type.h"
+#include "parser/keywords.h"
#include <errno.h>
#ifndef CHAR_BIT
extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
extern char *mm_strdup(const char *);
extern void mmerror(int, enum errortype, char *,...);
-extern const ScanKeyword *ScanCKeywordLookup(char *);
extern void output_get_descr_header(char *);
extern void output_get_descr(char *, char *);
extern void output_set_descr_header(char *);
extern void remove_typedefs(int);
extern void remove_variables(int);
extern struct variable *new_variable(const char *, struct ECPGtype *, int);
-extern const ScanKeyword *ScanKeywordLookup(char *text);
-extern const ScanKeyword *DoLookup(char *, const ScanKeyword *, const ScanKeyword *);
+extern const ScanKeyword *ScanCKeywordLookup(const char *);
+extern const ScanKeyword *ScanECPGKeywordLookup(const char *text);
+extern const ScanKeyword *DoLookup(const char *, const ScanKeyword *, const ScanKeyword *);
extern void scanner_init(const char *);
extern void parser_init(void);
extern void scanner_finish(void);
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * keywords.c
- * lexical token lookup for reserved words in PostgreSQL
- *
- * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.85 2008/01/01 19:45:59 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-
-#include "extern.h"
-#include "preproc.h"
-
-/* compile both keyword lists in one file because they are always scanned together */
-#include "ecpg_keywords.c"
-
-/*
- * List of (keyword-name, keyword-token-value) pairs.
- *
- * !!WARNING!!: This list must be sorted, because binary
- * search is used to locate entries.
- */
-static const ScanKeyword ScanPGSQLKeywords[] = {
- /* name, value */
- {"abort", ABORT_P},
- {"absolute", ABSOLUTE_P},
- {"access", ACCESS},
- {"action", ACTION},
- {"add", ADD_P},
- {"admin", ADMIN},
- {"after", AFTER},
- {"aggregate", AGGREGATE},
- {"all", ALL},
- {"also", ALSO},
- {"alter", ALTER},
- {"always", ALWAYS},
- {"analyse", ANALYSE}, /* British spelling */
- {"analyze", ANALYZE},
- {"and", AND},
- {"any", ANY},
- {"array", ARRAY},
- {"as", AS},
- {"asc", ASC},
- {"assertion", ASSERTION},
- {"assignment", ASSIGNMENT},
- {"asymmetric", ASYMMETRIC},
- {"at", AT},
- {"authorization", AUTHORIZATION},
- {"backward", BACKWARD},
- {"before", BEFORE},
- {"begin", BEGIN_P},
- {"between", BETWEEN},
- {"bigint", BIGINT},
- {"binary", BINARY},
- {"bit", BIT},
- {"boolean", BOOLEAN_P},
- {"both", BOTH},
- {"by", BY},
- {"cache", CACHE},
- {"called", CALLED},
- {"cascade", CASCADE},
- {"cascaded", CASCADED},
- {"case", CASE},
- {"cast", CAST},
- {"chain", CHAIN},
- {"char", CHAR_P},
- {"character", CHARACTER},
- {"characteristics", CHARACTERISTICS},
- {"check", CHECK},
- {"checkpoint", CHECKPOINT},
- {"class", CLASS},
- {"close", CLOSE},
- {"cluster", CLUSTER},
- {"coalesce", COALESCE},
- {"collate", COLLATE},
- {"column", COLUMN},
- {"comment", COMMENT},
- {"commit", COMMIT},
- {"committed", COMMITTED},
- {"concurrently", CONCURRENTLY},
- {"configuration", CONFIGURATION},
- {"connection", CONNECTION},
- {"constraint", CONSTRAINT},
- {"constraints", CONSTRAINTS},
- {"content", CONTENT_P},
- {"conversion", CONVERSION_P},
- {"copy", COPY},
- {"cost", COST},
- {"create", CREATE},
- {"createdb", CREATEDB},
- {"createrole", CREATEROLE},
- {"createuser", CREATEUSER},
- {"cross", CROSS},
- {"csv", CSV},
- {"current", CURRENT_P},
- {"current_date", CURRENT_DATE},
- {"current_role", CURRENT_ROLE},
- {"current_time", CURRENT_TIME},
- {"current_timestamp", CURRENT_TIMESTAMP},
- {"cursor", CURSOR},
- {"cycle", CYCLE},
- {"database", DATABASE},
- {"day", DAY_P},
- {"deallocate", DEALLOCATE},
- {"dec", DEC},
- {"decimal", DECIMAL_P},
- {"declare", DECLARE},
- {"default", DEFAULT},
- {"defaults", DEFAULTS},
- {"deferrable", DEFERRABLE},
- {"deferred", DEFERRED},
- {"definer", DEFINER},
- {"delete", DELETE_P},
- {"delimiter", DELIMITER},
- {"delimiters", DELIMITERS},
- {"desc", DESC},
- {"dictionary", DICTIONARY},
- {"disable", DISABLE_P},
- {"discard", DISCARD},
- {"distinct", DISTINCT},
- {"do", DO},
- {"document", DOCUMENT_P},
- {"domain", DOMAIN_P},
- {"double", DOUBLE_P},
- {"drop", DROP},
- {"each", EACH},
- {"else", ELSE},
- {"enable", ENABLE_P},
- {"encoding", ENCODING},
- {"encrypted", ENCRYPTED},
- {"end", END_P},
- {"enum", ENUM_P},
- {"escape", ESCAPE},
- {"except", EXCEPT},
- {"excluding", EXCLUDING},
- {"exclusive", EXCLUSIVE},
- {"execute", EXECUTE},
- {"exists", EXISTS},
- {"explain", EXPLAIN},
- {"external", EXTERNAL},
- {"extract", EXTRACT},
- {"false", FALSE_P},
- {"family", FAMILY},
- {"fetch", FETCH},
- {"first", FIRST_P},
- {"float", FLOAT_P},
- {"for", FOR},
- {"force", FORCE},
- {"foreign", FOREIGN},
- {"forward", FORWARD},
- {"freeze", FREEZE},
- {"from", FROM},
- {"full", FULL},
- {"function", FUNCTION},
- {"get", GET},
- {"global", GLOBAL},
- {"grant", GRANT},
- {"granted", GRANTED},
- {"greatest", GREATEST},
- {"group", GROUP_P},
- {"handler", HANDLER},
- {"having", HAVING},
- {"header", HEADER_P},
- {"hold", HOLD},
- {"hour", HOUR_P},
- {"if", IF_P},
- {"ilike", ILIKE},
- {"immediate", IMMEDIATE},
- {"immutable", IMMUTABLE},
- {"implicit", IMPLICIT_P},
- {"in", IN_P},
- {"including", INCLUDING},
- {"increment", INCREMENT},
- {"index", INDEX},
- {"indexes", INDEXES},
- {"inherit", INHERIT},
- {"inherits", INHERITS},
- {"initially", INITIALLY},
- {"inner", INNER_P},
- {"inout", INOUT},
- {"input", INPUT_P},
- {"insensitive", INSENSITIVE},
- {"insert", INSERT},
- {"instead", INSTEAD},
- {"int", INT_P},
- {"integer", INTEGER},
- {"intersect", INTERSECT},
- {"interval", INTERVAL},
- {"into", INTO},
- {"invoker", INVOKER},
- {"is", IS},
- {"isnull", ISNULL},
- {"isolation", ISOLATION},
- {"join", JOIN},
- {"key", KEY},
- {"lancompiler", LANCOMPILER},
- {"language", LANGUAGE},
- {"large", LARGE_P},
- {"last", LAST_P},
- {"leading", LEADING},
- {"least", LEAST},
- {"left", LEFT},
- {"level", LEVEL},
- {"like", LIKE},
- {"limit", LIMIT},
- {"listen", LISTEN},
- {"load", LOAD},
- {"local", LOCAL},
- {"location", LOCATION},
- {"lock", LOCK_P},
- {"login", LOGIN_P},
- {"mapping", MAPPING},
- {"match", MATCH},
- {"maxvalue", MAXVALUE},
- {"minute", MINUTE_P},
- {"minvalue", MINVALUE},
- {"mode", MODE},
- {"month", MONTH_P},
- {"move", MOVE},
- {"name", NAME_P},
- {"names", NAMES},
- {"national", NATIONAL},
- {"natural", NATURAL},
- {"nchar", NCHAR},
- {"new", NEW},
- {"next", NEXT},
- {"no", NO},
- {"nocreatedb", NOCREATEDB},
- {"nocreaterole", NOCREATEROLE},
- {"nocreateuser", NOCREATEUSER},
- {"noinherit", NOINHERIT},
- {"nologin", NOLOGIN_P},
- {"none", NONE},
- {"nosuperuser", NOSUPERUSER},
- {"not", NOT},
- {"nothing", NOTHING},
- {"notify", NOTIFY},
- {"notnull", NOTNULL},
- {"nowait", NOWAIT},
- {"null", NULL_P},
- {"nullif", NULLIF},
- {"nulls", NULLS_P},
- {"numeric", NUMERIC},
- {"object", OBJECT_P},
- {"of", OF},
- {"off", OFF},
- {"offset", OFFSET},
- {"oids", OIDS},
- {"old", OLD},
- {"on", ON},
- {"only", ONLY},
- {"operator", OPERATOR},
- {"option", OPTION},
- {"or", OR},
- {"order", ORDER},
- {"out", OUT_P},
- {"outer", OUTER_P},
- {"overlaps", OVERLAPS},
- {"owned", OWNED},
- {"owner", OWNER},
- {"parser", PARSER},
- {"partial", PARTIAL},
- {"password", PASSWORD},
- {"placing", PLACING},
- {"plans", PLANS},
- {"position", POSITION},
- {"precision", PRECISION},
- {"prepare", PREPARE},
- {"prepared", PREPARED},
- {"preserve", PRESERVE},
- {"primary", PRIMARY},
- {"prior", PRIOR},
- {"privileges", PRIVILEGES},
- {"procedural", PROCEDURAL},
- {"procedure", PROCEDURE},
- {"quote", QUOTE},
- {"read", READ},
- {"real", REAL},
- {"reassign", REASSIGN},
- {"recheck", RECHECK},
- {"references", REFERENCES},
- {"reindex", REINDEX},
- {"relative", RELATIVE_P},
- {"release", RELEASE},
- {"rename", RENAME},
- {"repeatable", REPEATABLE},
- {"replace", REPLACE},
- {"replica", REPLICA},
- {"reset", RESET},
- {"restart", RESTART},
- {"restrict", RESTRICT},
- {"returning", RETURNING},
- {"returns", RETURNS},
- {"revoke", REVOKE},
- {"right", RIGHT},
- {"role", ROLE},
- {"rollback", ROLLBACK},
- {"row", ROW},
- {"rows", ROWS},
- {"rule", RULE},
- {"savepoint", SAVEPOINT},
- {"schema", SCHEMA},
- {"scroll", SCROLL},
- {"search", SEARCH},
- {"second", SECOND_P},
- {"security", SECURITY},
- {"select", SELECT},
- {"sequence", SEQUENCE},
- {"serializable", SERIALIZABLE},
- {"session", SESSION},
- {"session_user", SESSION_USER},
- {"set", SET},
- {"setof", SETOF},
- {"share", SHARE},
- {"show", SHOW},
- {"similar", SIMILAR},
- {"simple", SIMPLE},
- {"smallint", SMALLINT},
- {"some", SOME},
- {"stable", STABLE},
- {"standalone", STANDALONE_P},
- {"start", START},
- {"statement", STATEMENT},
- {"statistics", STATISTICS},
- {"stdin", STDIN},
- {"stdout", STDOUT},
- {"storage", STORAGE},
- {"strict", STRICT_P},
- {"strip", STRIP_P},
- {"substring", SUBSTRING},
- {"superuser", SUPERUSER_P},
- {"symmetric", SYMMETRIC},
- {"sysid", SYSID},
- {"system", SYSTEM_P},
- {"table", TABLE},
- {"tablespace", TABLESPACE},
- {"temp", TEMP},
- {"template", TEMPLATE},
- {"temporary", TEMPORARY},
- {"text", TEXT_P},
- {"then", THEN},
- {"time", TIME},
- {"timestamp", TIMESTAMP},
- {"to", TO},
- {"trailing", TRAILING},
- {"transaction", TRANSACTION},
- {"treat", TREAT},
- {"trigger", TRIGGER},
- {"trim", TRIM},
- {"true", TRUE_P},
- {"truncate", TRUNCATE},
- {"trusted", TRUSTED},
- {"type", TYPE_P},
- {"uncommitted", UNCOMMITTED},
- {"unencrypted", UNENCRYPTED},
- {"union", UNION},
- {"unique", UNIQUE},
- {"unknown", UNKNOWN},
- {"unlisten", UNLISTEN},
- {"until", UNTIL},
- {"update", UPDATE},
- {"user", USER},
- {"using", USING},
- {"vacuum", VACUUM},
- {"valid", VALID},
- {"validator", VALIDATOR},
- {"value", VALUE_P},
- {"values", VALUES},
- {"varchar", VARCHAR},
- {"varying", VARYING},
- {"verbose", VERBOSE},
- {"version", VERSION_P},
- {"view", VIEW},
- {"volatile", VOLATILE},
- {"when", WHEN},
- {"where", WHERE},
- {"whitespace", WHITESPACE_P},
- {"with", WITH},
- {"without", WITHOUT},
- {"work", WORK},
- {"write", WRITE},
- {"xml", XML_P},
- {"xmlattributes", XMLATTRIBUTES},
- {"xmlconcat", XMLCONCAT},
- {"xmlelement", XMLELEMENT},
- {"xmlforest", XMLFOREST},
- {"xmlparse", XMLPARSE},
- {"xmlpi", XMLPI},
- {"xmlroot", XMLROOT},
- {"xmlserialize", XMLSERIALIZE},
- {"year", YEAR_P},
- {"yes", YES_P},
- {"zone", ZONE},
-};
-
-
-/*
- * Now do a binary search using plain strcmp() comparison.
- */
-const ScanKeyword *
-DoLookup(char *word, const ScanKeyword *low, const ScanKeyword *high)
-{
- while (low <= high)
- {
- const ScanKeyword *middle;
- int difference;
-
- middle = low + (high - low) / 2;
- difference = strcmp(middle->name, word);
- if (difference == 0)
- return middle;
- else if (difference < 0)
- low = middle + 1;
- else
- high = middle - 1;
- }
-
- return NULL;
-}
-
-/*
- * ScanKeywordLookup - see if a given word is a keyword
- *
- * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
- *
- * The match is done case-insensitively. Note that we deliberately use a
- * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
- * even if we are in a locale where tolower() would produce more or different
- * translations. This is to conform to the SQL99 spec, which says that
- * keywords are to be matched in this way even though non-keyword identifiers
- * receive a different case-normalization mapping.
- */
-const ScanKeyword *
-ScanKeywordLookup(char *text)
-{
- int len,
- i;
- char word[NAMEDATALEN];
- const ScanKeyword *res;
-
- len = strlen(text);
- /* We assume all keywords are shorter than NAMEDATALEN. */
- if (len >= NAMEDATALEN)
- return NULL;
-
- /*
- * Apply an ASCII-only downcasing. We must not use tolower() since it may
- * produce the wrong translation in some locales (eg, Turkish).
- */
- for (i = 0; i < len; i++)
- {
- char ch = text[i];
-
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
- word[i] = ch;
- }
- word[len] = '\0';
-
- /*
- * Now do a binary search using plain strcmp() comparison.
- */
- res = DoLookup(word, &ScanPGSQLKeywords[0], endof(ScanPGSQLKeywords) - 1);
- if (res)
- return res;
-
- return DoLookup(word, &ScanECPGKeywords[0], endof(ScanECPGKeywords) - 1);
-}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.165 2008/05/16 15:20:04 petere Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.166 2008/05/20 23:17:32 meskes Exp $
*
*-------------------------------------------------------------------------
*/
if (!isdefine())
{
/* Is it an SQL/ECPG keyword? */
- keyword = ScanKeywordLookup(yytext);
+ keyword = ScanECPGKeywordLookup(yytext);
if (keyword != NULL)
return keyword->value;
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.365 2008/05/16 15:20:04 petere Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.366 2008/05/20 23:17:32 meskes Exp $ */
/* Copyright comment */
%{
/* special embedded SQL token */
%token SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
SQL_CALL SQL_CARDINALITY SQL_CONNECT
- SQL_CONTINUE SQL_COUNT SQL_DATA
+ SQL_COUNT SQL_DATA
SQL_DATETIME_INTERVAL_CODE
SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
SQL_DESCRIPTOR SQL_DISCONNECT SQL_FOUND
- SQL_FREE SQL_GO SQL_GOTO SQL_IDENTIFIED
+ SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED
SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
SQL_LONG SQL_NULLABLE SQL_OCTET_LENGTH
SQL_OPEN SQL_OUTPUT SQL_REFERENCE
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
- CONTENT_P CONVERSION_P COPY COST CREATE CREATEDB
+ CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P CURRENT_DATE CURRENT_ROLE
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM
FULL FUNCTION
- GET GLOBAL GRANT GRANTED GREATEST GROUP_P
+ GLOBAL GRANT GRANTED GREATEST GROUP_P
HANDLER HAVING HEADER_P HOLD HOUR_P
- IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
- INDEX INDEXES INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
- INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
- INTERVAL INTO INVOKER IS ISNULL ISOLATION
+ IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
+ INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY
+ INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
+ INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
%type <str> ConstraintElem key_actions ColQualList cluster_index_specification
%type <str> target_list target_el alias_clause type_func_name_keyword
%type <str> qualified_name database_name alter_using type_function_name
-%type <str> access_method attr_name index_name name func_name
+%type <str> access_method attr_name index_name name func_name opt_restart_seqs
%type <str> file_name AexprConst c_expr ConstTypename var_list
%type <str> a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by
%type <str> opt_indirection expr_list extract_list extract_arg
{ $$ = cat2_str(make_str("owned by"), $3); }
| START opt_with NumConst
{ $$ = cat_str(3, make_str("start"), $2, $3); }
+ | RESTART
+ { $$ = make_str("restart"); }
| RESTART opt_with NumConst
{ $$ = cat_str(3, make_str("restart"), $2, $3); }
;
| /*EMPTY*/ { $$ = EMPTY; }
;
-opt_recheck: RECHECK { $$ = make_str("recheck"); }
+opt_recheck: RECHECK {
+ mmerror(PARSE_ERROR, ET_WARNING, "no longer supported RECHECK OPTION will be passed to backend");
+ $$ = make_str("recheck");
+ }
| /*EMPTY*/ { $$ = EMPTY; }
;
* truncate table relname1, relname2, ....
*
*****************************************************************************/
-TruncateStmt: TRUNCATE opt_table qualified_name_list opt_drop_behavior
- { $$ = cat_str(4, make_str("truncate table"), $2, $3, $4); }
+TruncateStmt: TRUNCATE opt_table qualified_name_list opt_restart_seqs opt_drop_behavior
+ { $$ = cat_str(5, make_str("truncate table"), $2, $3, $4, $5); }
;
+opt_restart_seqs:
+ CONTINUE_P IDENTITY_P { $$ = cat2_str(make_str("continue"), make_str("identity")); }
+ | RESTART IDENTITY_P { $$ = cat2_str(make_str("restart"), make_str("identity")); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
+
/*****************************************************************************
*
* QUERY:
{ $$ = cat_str(4, make_str("alter text search template"), $5, make_str("rename to"), $8); }
| ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name
{ $$ = cat_str(4, make_str("alter text search configuration"), $5, make_str("rename to"), $8); }
+ | ALTER TYPE_P any_name RENAME TO name
+ { $$ = cat_str(4, make_str("alter type"), $3, make_str("rename to"), $6); }
;
opt_column: COLUMN { $$ = make_str("column"); }
| UPDATE { $$ = make_str("update"); }
| DELETE_P { $$ = make_str("delete"); }
| INSERT { $$ = make_str("insert"); }
+ | TRUNCATE { $$ = make_str("truncate"); }
;
opt_instead: INSTEAD { $$ = make_str("instead"); }
{ $$ = cat_str(3, $1, make_str(","), $3); }
;
-extract_list: extract_arg FROM a_expr
- { $$ = cat_str(3, $1, make_str("from"), $3); }
- | /* EMPTY */
- { $$ = EMPTY; }
- ;
-
type_list: Typename
{ $$ = $1; }
| type_list ',' Typename
{ $$ = cat_str(3, $1, ',', $3); }
;
+array_expr: '[' expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
+ | '[' array_expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
+ | '[' ']' { $$ = make_str("[]"); }
+ ;
+
array_expr_list: array_expr { $$ = $1; }
| array_expr_list ',' array_expr { $$ = cat_str(3, $1, make_str(","), $3); }
;
-
-array_expr: '[' expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
- | '[' array_expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
+extract_list: extract_arg FROM a_expr
+ { $$ = cat_str(3, $1, make_str("from"), $3); }
+ | /* EMPTY */
+ { $$ = EMPTY; }
;
-/* Allow delimited string SCONST in extract_arg as an SQL extension.
- * - thomas 2001-04-12
- */
extract_arg: ident { $$ = $1; }
| YEAR_P { $$ = make_str("year"); }
target_el: a_expr AS ColLabel
{ $$ = cat_str(3, $1, make_str("as"), $3); }
+ /*
+ * We support omitting AS only for column labels that aren't
+ * any known keyword. There is an ambiguity against postfix
+ * operators: is "a ! b" an infix expression, or a postfix
+ * expression and a column label? We prefer to resolve this
+ * as an infix expression, which we accomplish by assigning
+ * IDENT a precedence higher than POSTFIXOP.
+ */
| a_expr IDENT
{ $$ = cat_str(3, $1, make_str("as"), $2); }
| a_expr
* manipulate a descriptor header
*/
-ECPGGetDescriptorHeader: GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
+ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
{ $$ = $3; }
;
* manipulate a descriptor
*/
-ECPGGetDescriptor: GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
+ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
{ $$.str = $5; $$.name = $3; }
;
}
;
-action : SQL_CONTINUE
+action : CONTINUE_P
{
$<action>$.code = W_NOTHING;
$<action>$.command = NULL;
ECPGKeywords_vanames: SQL_BREAK { $$ = make_str("break"); }
| SQL_CALL { $$ = make_str("call"); }
| SQL_CARDINALITY { $$ = make_str("cardinality"); }
- | SQL_CONTINUE { $$ = make_str("continue"); }
| SQL_COUNT { $$ = make_str("count"); }
| SQL_DATA { $$ = make_str("data"); }
| SQL_DATETIME_INTERVAL_CODE { $$ = make_str("datetime_interval_code"); }
/* | CONNECTION { $$ = make_str("connection"); }*/
| CONSTRAINTS { $$ = make_str("constraints"); }
| CONTENT_P { $$ = make_str("content"); }
+ | CONTINUE_P { $$ = make_str("continue"); }
| CONVERSION_P { $$ = make_str("conversion"); }
| COPY { $$ = make_str("copy"); }
| COST { $$ = make_str("cost"); }
| HEADER_P { $$ = make_str("header"); }
| HOLD { $$ = make_str("hold"); }
/* | HOUR_P { $$ = make_str("hour"); }*/
+ | IDENTITY_P { $$ = make_str("identity"); }
| IF_P { $$ = make_str("if"); }
| IMMEDIATE { $$ = make_str("immediate"); }
| IMMUTABLE { $$ = make_str("immutable"); }
/*
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.h,v 1.49 2008/05/17 01:28:25 adunstan Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.h,v 1.50 2008/05/20 23:17:32 meskes Exp $
*/
#ifndef _ECPG_PREPROC_TYPE_H
#define _ECPG_PREPROC_TYPE_H
char *name;
};
-typedef struct ScanKeyword
-{
- char *name;
- int value;
-} ScanKeyword;
-
#endif /* _ECPG_PREPROC_TYPE_H */
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on <DEFAULT> port <DEFAULT>
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute line 23: QUERY: alter user connectuser encrypted password 'connectpw' with 0 parameter on connection main
+[NO_PID]: ecpg_execute on line 23: query: alter user connectuser encrypted password 'connectpw'; with 0 parameter(s) on connection main
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute line 23: using PQexec
+[NO_PID]: ecpg_execute on line 23: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute line 23 Ok: ALTER ROLE
+[NO_PID]: ecpg_execute on line 23: OK: ALTER ROLE
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on localhost port <DEFAULT>
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database <DEFAULT> on localhost port <DEFAULT> for user connectdb
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on localhost port <REGRESSION_PORT>
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database <DEFAULT> on localhost port <REGRESSION_PORT> for user connectdb
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on <DEFAULT> port <REGRESSION_PORT>
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database <DEFAULT> on <DEFAULT> port <REGRESSION_PORT> for user connectdb
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection main closed.
+[NO_PID]: ecpg_finish: connection main closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on localhost port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection connectdb closed.
+[NO_PID]: ecpg_finish: connection connectdb closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database <DEFAULT> on localhost port <REGRESSION_PORT> for user connectdb
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection (null) closed.
+[NO_PID]: ecpg_finish: connection (null) closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on localhost port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection connectdb closed.
+[NO_PID]: ecpg_finish: connection connectdb closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on <DEFAULT> port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection connectdb closed.
+[NO_PID]: ecpg_finish: connection connectdb closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database connectdb on <DEFAULT> port <REGRESSION_PORT> with options connect_timeout=14 for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection connectdb closed.
+[NO_PID]: ecpg_finish: connection connectdb closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database nonexistant on localhost port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: could not open database: FATAL: database "nonexistant" does not exist
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection nonexistant closed.
+[NO_PID]: ecpg_finish: connection nonexistant closed
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlcode -402 in line 62, 'Could not connect to database nonexistant in line 62.'.
+[NO_PID]: raising sqlcode -402 on line 62: could not connect to database "nonexistant" on line 62
[NO_PID]: sqlca: code: -402, state: 08001
-[NO_PID]: raising sqlcode -220 in line 63, 'No such connection CURRENT in line 63.'.
+[NO_PID]: raising sqlcode -220 on line 63: no such connection CURRENT on line 63
[NO_PID]: sqlca: code: -220, state: 08003
[NO_PID]: ECPGconnect: opening database connectdb on localhost port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
TCP/IP connections on port 20?
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_finish: Connection connectdb closed.
+[NO_PID]: ecpg_finish: connection connectdb closed
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlcode -402 in line 66, 'Could not connect to database connectdb in line 66.'.
+[NO_PID]: raising sqlcode -402 on line 66: could not connect to database "connectdb" on line 66
[NO_PID]: sqlca: code: -402, state: 08001
[NO_PID]: ECPGconnect: opening database connectdb on <DEFAULT> port <REGRESSION_PORT> for user connectuser
[NO_PID]: sqlca: code: 0, state: 00000
/* exec sql whenever sqlerror stop ; */
#line 61 "whenever.pgc"
- { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select * from nonexistant ", ECPGt_EOIT,
+ /* This cannot fail, thus we don't get an exit value not equal 0. */
+ /* However, it still test the precompiler output. */
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select 1 ", ECPGt_EOIT,
ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
-#line 62 "whenever.pgc"
+#line 64 "whenever.pgc"
if (sqlca.sqlwarn[0] == 'W') warn ( );
-#line 62 "whenever.pgc"
+#line 64 "whenever.pgc"
if (sqlca.sqlcode < 0) exit (1);}
-#line 62 "whenever.pgc"
+#line 64 "whenever.pgc"
{ ECPGtrans(__LINE__, NULL, "rollback");
-#line 63 "whenever.pgc"
+#line 65 "whenever.pgc"
if (sqlca.sqlwarn[0] == 'W') warn ( );
-#line 63 "whenever.pgc"
+#line 65 "whenever.pgc"
if (sqlca.sqlcode < 0) exit (1);}
-#line 63 "whenever.pgc"
+#line 65 "whenever.pgc"
exit (0);
}
[NO_PID]: sqlca: code: -400, state: 42P01
[NO_PID]: ECPGtrans on line 59: action "rollback"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 62: query: select * from nonexistant ; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 64: query: select 1 ; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 62: using PQexec
+[NO_PID]: ecpg_execute on line 64: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_check_PQresult on line 62: ERROR: relation "nonexistant" does not exist
+[NO_PID]: ecpg_execute on line 64: correctly got 1 tuples with 1 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 64: RESULT: 1 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGtrans on line 65: action "rollback"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: raising sqlstate 42P01 (sqlcode -400) on line 62: relation "nonexistant" does not exist on line 62
-[NO_PID]: sqlca: code: -400, state: 42P01
exec sql rollback;
exec sql whenever sqlerror stop;
- exec sql select * into :i from nonexistant;
+ /* This cannot fail, thus we don't get an exit value not equal 0. */
+ /* However, it still test the precompiler output. */
+ exec sql select 1 into :i;
exec sql rollback;
exit (0);
}