mirror of https://github.com/postgres/postgres
Synced parser.
Made ecpg parser use backend provided keyword list. Changed whenever test so exit value is 0.
This commit is contained in:
parent
1ac1bea076
commit
f7563e9710
|
@ -2351,6 +2351,13 @@ Mon, 12 May 2008 18:19:08 +0200
|
|||
|
||||
- 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.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# 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 $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
|
@ -25,7 +25,7 @@ override CPPFLAGS := -I../include -I$(top_srcdir)/src/interfaces/ecpg/include \
|
|||
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
|
||||
|
@ -56,6 +56,11 @@ endif
|
|||
|
||||
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
|
||||
|
@ -68,7 +73,7 @@ uninstall:
|
|||
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
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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 $
|
||||
* §
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -21,37 +21,39 @@
|
|||
* 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);
|
||||
}
|
||||
|
|
|
@ -4,11 +4,18 @@
|
|||
* 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.
|
||||
*
|
||||
|
@ -16,50 +23,129 @@
|
|||
* 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);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/* $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
|
||||
|
@ -74,7 +75,6 @@ extern void base_yyerror(const char *);
|
|||
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 *);
|
||||
|
@ -96,8 +96,9 @@ extern void check_indicator(struct ECPGtype *);
|
|||
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);
|
||||
|
|
|
@ -1,476 +0,0 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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);
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -680,7 +680,7 @@ cppline {space}*#(.*\\{space})*.*{newline}
|
|||
if (!isdefine())
|
||||
{
|
||||
/* Is it an SQL/ECPG keyword? */
|
||||
keyword = ScanKeywordLookup(yytext);
|
||||
keyword = ScanECPGKeywordLookup(yytext);
|
||||
if (keyword != NULL)
|
||||
return keyword->value;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $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 */
|
||||
%{
|
||||
|
@ -392,11 +392,11 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
|
|||
/* 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
|
||||
|
@ -427,7 +427,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
|
|||
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
|
||||
|
||||
|
@ -441,14 +441,14 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
|
|||
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
|
||||
|
||||
|
@ -555,7 +555,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
|
|||
%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
|
||||
|
@ -1862,6 +1862,8 @@ OptSeqElem: CACHE NumConst
|
|||
{ $$ = 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); }
|
||||
;
|
||||
|
@ -2179,7 +2181,10 @@ opt_opfamily: FAMILY any_name { $$ = cat2_str(make_str("family"), $2); }
|
|||
| /*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; }
|
||||
;
|
||||
|
||||
|
@ -2282,10 +2287,16 @@ attrs: '.' attr_name { $$ = cat2_str(make_str("."), $2); }
|
|||
* 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:
|
||||
|
@ -2852,6 +2863,8 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
|
|||
{ $$ = 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"); }
|
||||
|
@ -2960,6 +2973,7 @@ event: SELECT { $$ = make_str("select"); }
|
|||
| UPDATE { $$ = make_str("update"); }
|
||||
| DELETE_P { $$ = make_str("delete"); }
|
||||
| INSERT { $$ = make_str("insert"); }
|
||||
| TRUNCATE { $$ = make_str("truncate"); }
|
||||
;
|
||||
|
||||
opt_instead: INSTEAD { $$ = make_str("instead"); }
|
||||
|
@ -4538,29 +4552,26 @@ expr_list: a_expr
|
|||
{ $$ = 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"); }
|
||||
|
@ -4703,6 +4714,14 @@ target_list: target_list ',' target_el
|
|||
|
||||
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
|
||||
|
@ -5999,7 +6018,7 @@ ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
|
|||
* manipulate a descriptor header
|
||||
*/
|
||||
|
||||
ECPGGetDescriptorHeader: GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
|
||||
ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
|
||||
{ $$ = $3; }
|
||||
;
|
||||
|
||||
|
@ -6034,7 +6053,7 @@ desc_header_item: SQL_COUNT { $$ = ECPGd_count; }
|
|||
* 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; }
|
||||
;
|
||||
|
||||
|
@ -6214,7 +6233,7 @@ ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
|
|||
}
|
||||
;
|
||||
|
||||
action : SQL_CONTINUE
|
||||
action : CONTINUE_P
|
||||
{
|
||||
$<action>$.code = W_NOTHING;
|
||||
$<action>$.command = NULL;
|
||||
|
@ -6280,7 +6299,6 @@ ECPGKeywords: ECPGKeywords_vanames { $$ = $1; }
|
|||
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"); }
|
||||
|
@ -6467,6 +6485,7 @@ ECPGunreserved_con: ABORT_P { $$ = make_str("abort"); }
|
|||
/* | 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"); }
|
||||
|
@ -6515,6 +6534,7 @@ ECPGunreserved_con: ABORT_P { $$ = make_str("abort"); }
|
|||
| 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"); }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $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
|
||||
|
@ -190,10 +190,4 @@ struct fetch_desc
|
|||
char *name;
|
||||
};
|
||||
|
||||
typedef struct ScanKeyword
|
||||
{
|
||||
char *name;
|
||||
int value;
|
||||
} ScanKeyword;
|
||||
|
||||
#endif /* _ECPG_PREPROC_TYPE_H */
|
||||
|
|
|
@ -2,68 +2,68 @@
|
|||
[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
|
||||
|
@ -72,9 +72,9 @@
|
|||
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
|
||||
|
|
|
@ -220,25 +220,27 @@ if (sqlca.sqlcode < 0) goto error;}
|
|||
/* 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);
|
||||
}
|
||||
|
|
|
@ -82,11 +82,13 @@ sql error: relation "nonexistant" does not exist on line 47
|
|||
[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
|
||||
|
|
|
@ -59,7 +59,9 @@ int main(void)
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue