aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2000-01-27 19:01:35 +0000
committerMichael Meskes <meskes@postgresql.org>2000-01-27 19:01:35 +0000
commitb53955f38aa3832b84970c806e1afdd7d3053d9e (patch)
tree7c20f619884a37ba72608f998e02071d4e736f8a
parentdd979f66be20fc54aad06da743f788fbc505bbe1 (diff)
downloadpostgresql-b53955f38aa3832b84970c806e1afdd7d3053d9e.tar.gz
postgresql-b53955f38aa3832b84970c806e1afdd7d3053d9e.zip
*** empty log message ***
-rw-r--r--src/interfaces/ecpg/ChangeLog16
-rw-r--r--src/interfaces/ecpg/lib/ecpglib.c7
-rw-r--r--src/interfaces/ecpg/preproc/c_keywords.c29
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c2
-rw-r--r--src/interfaces/ecpg/preproc/extern.h1
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l29
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y408
-rw-r--r--src/interfaces/ecpg/preproc/type.h2
-rw-r--r--src/interfaces/ecpg/test/Makefile12
-rw-r--r--src/interfaces/ecpg/test/stp.pgc16
-rw-r--r--src/interfaces/ecpg/test/test1.pgc9
-rw-r--r--src/interfaces/ecpg/test/test2.pgc2
-rw-r--r--src/interfaces/ecpg/test/test3.pgc6
-rw-r--r--src/interfaces/ecpg/test/test5.pgc61
14 files changed, 277 insertions, 323 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index bb8517a4b0f..aaa63f616a2 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -775,5 +775,21 @@ Mon Jan 17 21:55:40 CET 2000
- Synced preproc.y with gram.y.
- Changed FETCH syntax using Rene's final patch. Made it more
standard compliant.
+
+Thu Jan 20 10:00:50 CET 2000
+
+ - Synced preproc.y with gram.y.
+
+Fri Jan 21 14:52:27 CET 2000
+
+ - Added more log output to ecpglib.
+
+Thu Jan 27 08:12:05 CET 2000
+
+ - Added another patch by Rene Hogendoorn.
+ - Fixed error messages in pgc.l.
+ - Improved variable parsing.
+ - Synced preproc.y with gram.y.
- Set library version to 3.0.10.
- Set ecpg version to 2.7.0.
+
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 5190dd0635c..7e755782715 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -9,7 +9,7 @@
slightly modified)
*/
-/* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
+/* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
on Feb. 5th, 1998 */
#include <stdio.h>
@@ -724,6 +724,9 @@ ECPGexecute(struct statement * stmt)
*((void **) var->pointer) = var->value;
add_mem(var->value, stmt->lineno);
}
+
+
+ ECPGlog("ECPGexecute line %d: TYPE db: %d c: %d\n", stmt->lineno, PQftype(results, act_field), var->type);
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
{
@@ -764,7 +767,7 @@ ECPGexecute(struct statement * stmt)
status = false;
break;
}
-
+
switch (var->type)
{
long res;
diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c
index 4d04c00dd9c..15e1494eea5 100644
--- a/src/interfaces/ecpg/preproc/c_keywords.c
+++ b/src/interfaces/ecpg/preproc/c_keywords.c
@@ -19,25 +19,26 @@
*/
static ScanKeyword ScanKeywords[] = {
/* name value */
- {"VARCHAR", S_VARCHAR},
+ {"VARCHAR", VARCHAR},
{"auto", S_AUTO},
- {"bool", S_BOOL},
- {"char", S_CHAR},
+ {"bool", SQL_BOOL},
+ {"char", CHAR},
{"const", S_CONST},
- {"double", S_DOUBLE},
- {"enum", S_ENUM},
+ {"double", DOUBLE},
+ {"enum", SQL_ENUM},
{"extern", S_EXTERN},
- {"float", S_FLOAT},
- {"int", S_INT},
- {"long", S_LONG},
+ {"float", FLOAT},
+ {"int", SQL_INT},
+ {"long", SQL_LONG},
{"register", S_REGISTER},
- {"short", S_SHORT},
- {"signed", S_SIGNED},
+ {"short", SQL_SHORT},
+ {"signed", SQL_SIGNED},
{"static", S_STATIC},
- {"struct", S_STRUCT},
- {"union", S_UNION},
- {"unsigned", S_UNSIGNED},
- {"varchar", S_VARCHAR},
+ {"struct", SQL_STRUCT},
+ {"union", UNION},
+ {"unsigned", SQL_UNSIGNED},
+ {"varchar", VARCHAR},
+ {"volatile", S_VOLATILE},
};
ScanKeyword *
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index 46c29ba2a2d..2da1761c6d2 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -1,5 +1,5 @@
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
-/* (C) Michael Meskes <meskes@debian.org> Feb 5th, 1998 */
+/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
/* Placed under the same copyright as PostgresSQL */
#include <unistd.h>
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index e921cf664fb..682ead43ec8 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -40,6 +40,7 @@ extern int yylex(void);
extern void yyerror(char *);
extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
extern char *mm_strdup(const char *);
+extern void mmerror(enum errortype, char * );
ScanKeyword *ScanECPGKeywordLookup(char *);
ScanKeyword *ScanCKeywordLookup(char *);
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 7477676d2ff..f69f21b94d0 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.49 2000/01/26 05:58:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.50 2000/01/27 19:00:39 meskes Exp $
*
*-------------------------------------------------------------------------
*/
@@ -246,7 +246,7 @@ cppline {space}*#(.*\\{line_end})*.*
errno = 0;
yylval.ival = strtol(literalbuf, &endptr, 2);
if (*endptr != '\0' || errno == ERANGE)
- yyerror("ERROR: Bad binary integer input!");
+ mmerror(ET_ERROR, "Bad binary integer input!");
return ICONST;
}
<xh>{xhinside} |
@@ -268,7 +268,7 @@ cppline {space}*#(.*\\{line_end})*.*
errno = 0;
yylval.ival = strtol(literalbuf, &endptr, 16);
if (*endptr != '\0' || errno == ERANGE)
- yyerror("ERROR: Bad hexadecimal integer input");
+ mmerror(ET_ERROR, "Bad hexadecimal integer input");
return ICONST;
}
@@ -355,7 +355,7 @@ cppline {space}*#(.*\\{line_end})*.*
errno = 0;
yylval.dval = strtod((char *)yytext,&endptr);
if (*endptr != '\0' || errno == ERANGE)
- yyerror("ERROR: Bad float8 input");
+ mmerror(ET_ERROR, "Bad float8 input");
return FCONST;
}
yylval.str = mm_strdup((char*)yytext);
@@ -367,7 +367,7 @@ cppline {space}*#(.*\\{line_end})*.*
errno = 0;
yylval.dval = strtod((char *)yytext,&endptr);
if (*endptr != '\0' || errno == ERANGE)
- yyerror("ERROR: Bad float input");
+ mmerror(ET_ERROR, "Bad float input");
return FCONST;
}
<SQL>:{identifier}(("->"|\.){identifier})* {
@@ -385,6 +385,13 @@ cppline {space}*#(.*\\{line_end})*.*
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
lower_text[i] = tolower(lower_text[i]);
+ if (i >= NAMEDATALEN)
+ {
+ sprintf(errortext, "Identifier \"%s\" will be truncated to \"%.*s\"", yytext, NAMEDATALEN-1, yytext);
+ mmerror (ET_WARN, errortext);
+ yytext[NAMEDATALEN-1] = '\0';
+ }
+
keyword = ScanKeywordLookup((char*)lower_text);
if (keyword != NULL) {
return keyword->value;
@@ -509,10 +516,10 @@ cppline {space}*#(.*\\{line_end})*.*
<C,xskip>{exec_sql}{elif}{space_or_nl}* { /* pop stack */
if ( preproc_tos == 0 ) {
- yyerror("ERROR: missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
+ mmerror(ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
}
else if ( stacked_if_value[preproc_tos].else_branch ) {
- yyerror("ERROR: missing 'EXEC SQL ENDIF;'");
+ mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
}
else {
preproc_tos--;
@@ -523,7 +530,7 @@ cppline {space}*#(.*\\{line_end})*.*
<C,xskip>{exec_sql}{else}{space_or_nl}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */
if ( stacked_if_value[preproc_tos].else_branch ) {
- yyerror("ERROR: duplicated 'EXEC SQL ELSE;'");
+ mmerror(ET_FATAL, "Duplicated 'EXEC SQL ELSE;'");
}
else {
stacked_if_value[preproc_tos].else_branch = TRUE;
@@ -541,7 +548,7 @@ cppline {space}*#(.*\\{line_end})*.*
}
<C,xskip>{exec_sql}{endif}{space_or_nl}*";" {
if ( preproc_tos == 0 ) {
- yyerror("ERROR: unmatched 'EXEC SQL ENDIF;'");
+ mmerror(ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'");
}
else {
preproc_tos--;
@@ -559,7 +566,7 @@ cppline {space}*#(.*\\{line_end})*.*
<xcond>{identifier}{space_or_nl}*";" {
if ( preproc_tos >= MAX_NESTED_IF-1 ) {
- yyerror("ERROR: too many nested 'EXEC SQL IFDEF' conditions");
+ mmerror(ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions");
}
else {
struct _defines *defptr;
@@ -680,7 +687,7 @@ cppline {space}*#(.*\\{line_end})*.*
if ( preproc_tos > 0 ) {
preproc_tos = 0;
- yyerror("ERROR: missing 'EXEC SQL ENDIF;'");
+ mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
}
if (yy_buffer == NULL)
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index c43ffcfa577..7b8d16f31a4 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -24,6 +24,7 @@ int struct_level = 0;
char errortext[128];
static char *connection = NULL;
static int QueryIsRule = 0, ForUpdateNotAllowed = 0, FoundInto = 0;
+static int initializer = 0;
static struct this_type actual_type[STRUCT_DEPTH];
static char *actual_storage[STRUCT_DEPTH];
static char *actual_startline[STRUCT_DEPTH];
@@ -36,12 +37,10 @@ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}};
-enum errortype {ET_WARN, ET_ERROR, ET_FATAL};
-
/*
* Handle parsing errors and warnings
*/
-static void
+void
mmerror(enum errortype type, char * error)
{
@@ -643,10 +642,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
%token SQL_VAR SQL_WHENEVER
/* C token */
-%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN
-%token S_FLOAT S_INT S
-%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
-%token S_UNION S_UNSIGNED S_VARCHAR
+%token S_ANYTHING S_AUTO S_CONST S_EXTERN
+%token S_REGISTER S_STATIC S_VOLATILE
/* I need this and don't know where it is defined inside the backend */
%token TYPECAST
@@ -814,21 +811,20 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
%type <str> indicator ECPGExecute ECPGPrepare ecpg_using
%type <str> storage_clause opt_initializer c_anything blockstart
%type <str> blockend variable_list variable c_thing c_term
-%type <str> opt_pointer cvariable ECPGDisconnect dis_name
+%type <str> opt_pointer cvariable ECPGDisconnect dis_name storage_modifier
%type <str> stmt symbol opt_symbol ECPGRelease execstring server_name
%type <str> connection_object opt_server opt_port c_stuff opt_reference
%type <str> user_name opt_user char_variable ora_user ident
%type <str> db_prefix server opt_options opt_connection_name c_list
-%type <str> ECPGSetConnection cpp_line s_enum ECPGTypedef c_args
+%type <str> ECPGSetConnection cpp_line ECPGTypedef c_args
%type <str> enum_type civariableonly ECPGCursorStmt ECPGDeallocate
-%type <str> ECPGFree ECPGDeclare ECPGVar sql_variable_declarations
-%type <str> sql_declaration sql_variable_list sql_variable opt_at
+%type <str> ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
%type <str> struct_type s_struct declaration declarations variable_declarations
%type <str> s_struct s_union union_type ECPGSetAutocommit on_off
-%type <type_enum> simple_type varchar_type
+%type <type_enum> simple_type signed_type unsigned_type varchar_type
-%type <type> type ctype
+%type <type> type
%type <action> action
@@ -943,7 +939,8 @@ stmt: AlterTableStmt { output_statement($1, 0); }
output_statement($1, 0);
}
| ECPGFree {
- fprintf(yyout, "{ ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
+ fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
+
whenever_action(2);
free($1);
}
@@ -1320,9 +1317,9 @@ DEFAULT} */
}
/* ALTER TABLE <name> DROP [COLUMN] <name> {RESTRICT|CASCADE} */
| ALTER TABLE relation_name opt_inh_star DROP opt_column ColId
- drop_behavior
+ /* drop_behavior */
{
- $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("drop"), $6, $7, $8);
+ $$ = cat_str(5, make_str("alter table"), $3, $4, make_str("drop"), $6, $7);
}
/* ALTER TABLE <name> ADD CONSTRAINT ... */
| ALTER TABLE relation_name opt_inh_star ADD TableConstraint
@@ -2584,21 +2581,21 @@ createdb_opt_location: LOCATION '=' Sconst { $$ = cat2_str(make_str("location =
createdb_opt_encoding: ENCODING '=' Sconst
{
#ifndef MULTIBYTE
- mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
#endif
$$ = cat2_str(make_str("encoding ="), $3);
}
| ENCODING '=' Iconst
{
#ifndef MULTIBYTE
- mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
#endif
$$ = cat2_str(make_str("encoding ="), $3);
}
| ENCODING '=' DEFAULT
{
#ifndef MULTIBYTE
- mmerror(ET_ERROR, "WITH ENCODING is not supported.");
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
#endif
$$ = make_str("encoding = default");
}
@@ -3405,17 +3402,16 @@ opt_decimal: '(' Iconst ',' Iconst ')'
}
;
-/* SQL92 character data types
+/*
+ * SQL92 character data types
* The following implements CHAR() and VARCHAR().
* - ay 6/95
*/
Character: character '(' Iconst ')'
{
- if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar")))
- mmerror(ET_ERROR, "internal parsing error; unrecognized character type");
if (atol($3) < 1)
{
- sprintf(errortext, "length for '%s' type must be at least 1",$1);
+ sprintf(errortext, "length for type '%s' type must be at least 1",$1);
mmerror(ET_ERROR, errortext);
}
else if (atol($3) > MaxAttrSize)
@@ -4332,7 +4328,9 @@ ColLabel: ColId { $$ = $1; }
| EXPLAIN { $$ = make_str("explain"); }
| EXTEND { $$ = make_str("extend"); }
| FALSE_P { $$ = make_str("false"); }
+ | FLOAT { $$ = make_str("float"); }
| FOREIGN { $$ = make_str("foreign"); }
+ | GLOBAL { $$ = make_str("global"); }
| GROUP { $$ = make_str("group"); }
| LISTEN { $$ = make_str("listen"); }
| LOAD { $$ = make_str("load"); }
@@ -4620,30 +4618,40 @@ variable_declarations: /* empty */ { $$ = EMPTY; }
declarations: declaration { $$ = $1; }
| declarations declaration { $$ = cat2_str($1, $2); }
-declaration: storage_clause
+declaration: storage_clause storage_modifier
{
- actual_storage[struct_level] = mm_strdup($1);
+ actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
actual_startline[struct_level] = hashline_number();
}
type
{
- actual_type[struct_level].type_enum = $3.type_enum;
- actual_type[struct_level].type_dimension = $3.type_dimension;
- actual_type[struct_level].type_index = $3.type_index;
+ actual_type[struct_level].type_enum = $4.type_enum;
+ actual_type[struct_level].type_dimension = $4.type_dimension;
+ actual_type[struct_level].type_index = $4.type_index;
+
+ /* we do not need the string "varchar" for output */
+ /* so replace it with an empty string */
+ if ($4.type_enum == ECPGt_varchar)
+ {
+ free($4.type_str);
+ $4.type_str=EMPTY;
+ }
}
variable_list ';'
{
- $$ = cat_str(5, actual_startline[struct_level], $1, $3.type_str, $5, make_str(";\n"));
+ $$ = cat_str(6, actual_startline[struct_level], $1, $2, $4.type_str, $6, make_str(";\n"));
}
storage_clause : S_EXTERN { $$ = make_str("extern"); }
| S_STATIC { $$ = make_str("static"); }
- | S_SIGNED { $$ = make_str("signed"); }
- | S_CONST { $$ = make_str("const"); }
| S_REGISTER { $$ = make_str("register"); }
| S_AUTO { $$ = make_str("auto"); }
| /* empty */ { $$ = EMPTY; }
+storage_modifier : S_CONST { $$ = make_str("const"); }
+ | S_VOLATILE { $$ = make_str("volatile"); }
+ | /* empty */ { $$ = EMPTY; }
+
type: simple_type
{
$$.type_enum = $1;
@@ -4654,7 +4662,7 @@ type: simple_type
| varchar_type
{
$$.type_enum = ECPGt_varchar;
- $$.type_str = EMPTY;
+ $$.type_str = make_str("varchar");;
$$.type_dimension = -1;
$$.type_index = -1;
}
@@ -4691,12 +4699,16 @@ type: simple_type
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
-enum_type: s_enum '{' c_list '}'
+enum_type: SQL_ENUM opt_symbol enum_definition
{
- $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
+ $$ = cat_str(3, make_str("enum"), $2, $3);
+ }
+ | SQL_ENUM symbol
+ {
+ $$ = cat2_str(make_str("enum"), $2);
}
-
-s_enum: S_ENUM opt_symbol { $$ = cat2_str(make_str("enum"), $2); }
+
+enum_definition: '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
struct_type: s_struct '{' variable_declarations '}'
{
@@ -4712,38 +4724,64 @@ union_type: s_union '{' variable_declarations '}'
$$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
}
-s_struct : S_STRUCT opt_symbol
+s_struct: SQL_STRUCT opt_symbol
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+ /* reset this variable so we see if there was */
+ /* an initializer specified */
+ initializer = 0;
+
$$ = cat2_str(make_str("struct"), $2);
}
-s_union : S_UNION opt_symbol
+s_union: UNION opt_symbol
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+ /* reset this variable so we see if there was */
+ /* an initializer specified */
+ initializer = 0;
+
$$ = cat2_str(make_str("union"), $2);
}
opt_symbol: /* empty */ { $$ = EMPTY; }
| symbol { $$ = $1; }
-simple_type: S_SHORT { $$ = ECPGt_short; }
- | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; }
- | S_INT { $$ = ECPGt_int; }
- | S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; }
- | S_LONG { $$ = ECPGt_long; }
- | S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; }
- | S_FLOAT { $$ = ECPGt_float; }
- | S_DOUBLE { $$ = ECPGt_double; }
- | S_BOOL { $$ = ECPGt_bool; };
- | S_CHAR { $$ = ECPGt_char; }
- | S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; }
+simple_type: unsigned_type { $$=$1; }
+ | opt_signed signed_type { $$=$2; }
+ ;
-varchar_type: S_VARCHAR { $$ = ECPGt_varchar; }
+unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; }
+ | SQL_UNSIGNED SQL_SHORT SQL_INT { $$ = ECPGt_unsigned_short; }
+ | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; }
+ | SQL_UNSIGNED SQL_INT { $$ = ECPGt_unsigned_int; }
+ | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; }
+ | SQL_UNSIGNED SQL_LONG SQL_INT { $$ = ECPGt_unsigned_long; }
+ | SQL_UNSIGNED CHAR { $$ = ECPGt_unsigned_char; }
+ ;
+
+signed_type: SQL_SHORT { $$ = ECPGt_short; }
+ | SQL_SHORT SQL_INT { $$ = ECPGt_short; }
+ | SQL_INT { $$ = ECPGt_int; }
+ | SQL_LONG { $$ = ECPGt_long; }
+ | SQL_LONG SQL_INT { $$ = ECPGt_long; }
+ | SQL_BOOL { $$ = ECPGt_bool; };
+ | FLOAT { $$ = ECPGt_float; }
+ | DOUBLE { $$ = ECPGt_double; }
+ | CHAR { $$ = ECPGt_char; }
+ ;
+
+opt_signed: SQL_SIGNED
+ | /* EMPTY */
+ ;
+
+varchar_type: VARCHAR { $$ = ECPGt_varchar; }
variable_list: variable
{
@@ -4830,7 +4868,10 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer
}
opt_initializer: /* empty */ { $$ = EMPTY; }
- | '=' c_term { $$ = cat2_str(make_str("="), $2); }
+ | '=' c_term {
+ initializer = 1;
+ $$ = cat2_str(make_str("="), $2);
+ }
opt_pointer: /* empty */ { $$ = EMPTY; }
| '*' { $$ = make_str("*"); }
@@ -4966,19 +5007,24 @@ ECPGSetConnection: SET SQL_CONNECTION to_equal connection_object
/*
* define a new type for embedded SQL
*/
-ECPGTypedef: TYPE_P symbol IS ctype opt_type_array_bounds opt_reference
+ECPGTypedef: TYPE_P symbol IS type opt_type_array_bounds opt_reference
{
/* add entry to list */
struct typedefs *ptr, *this;
int dimension = $5.index1;
int length = $5.index2;
+ if (($4.type_enum == ECPGt_struct ||
+ $4.type_enum == ECPGt_union) &&
+ initializer == 1)
+ mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
for (ptr = types; ptr != NULL; ptr = ptr->next)
{
if (strcmp($2, ptr->name) == 0)
{
/* re-definition is a bug */
- sprintf(errortext, "type %s already defined", $2);
+ sprintf(errortext, "Type %s already defined", $2);
mmerror(ET_ERROR, errortext);
}
}
@@ -5050,237 +5096,21 @@ opt_type_array_bounds: '[' ']' opt_type_array_bounds
opt_reference: SQL_REFERENCE { $$ = make_str("reference"); }
| /* empty */ { $$ = EMPTY; }
-ctype: CHAR
- {
- $$.type_str = make_str("char");
- $$.type_enum = ECPGt_char;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | VARCHAR
- {
- $$.type_str = make_str("varchar");
- $$.type_enum = ECPGt_varchar;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | FLOAT
- {
- $$.type_str = make_str("float");
- $$.type_enum = ECPGt_float;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | DOUBLE
- {
- $$.type_str = make_str("double");
- $$.type_enum = ECPGt_double;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | opt_signed SQL_INT
- {
- $$.type_str = make_str("int");
- $$.type_enum = ECPGt_int;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_ENUM
- {
- $$.type_str = make_str("int");
- $$.type_enum = ECPGt_int;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | opt_signed SQL_SHORT
- {
- $$.type_str = make_str("short");
- $$.type_enum = ECPGt_short;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | opt_signed SQL_LONG
- {
- $$.type_str = make_str("long");
- $$.type_enum = ECPGt_long;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_BOOL
- {
- $$.type_str = make_str("bool");
- $$.type_enum = ECPGt_bool;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_UNSIGNED SQL_INT
- {
- $$.type_str = make_str("unsigned int");
- $$.type_enum = ECPGt_unsigned_int;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_UNSIGNED SQL_SHORT
- {
- $$.type_str = make_str("unsigned short");
- $$.type_enum = ECPGt_unsigned_short;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_UNSIGNED SQL_LONG
- {
- $$.type_str = make_str("unsigned long");
- $$.type_enum = ECPGt_unsigned_long;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | SQL_STRUCT
- {
- struct_member_list[struct_level++] = NULL;
- if (struct_level >= STRUCT_DEPTH)
- mmerror(ET_ERROR, "Too many levels in nested structure definition");
- } '{' sql_variable_declarations '}'
- {
- ECPGfree_struct_member(struct_member_list[struct_level--]);
- $$.type_str = cat_str(3, make_str("struct {"), $4, make_str("}"));
- $$.type_enum = ECPGt_struct;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | UNION
- {
- struct_member_list[struct_level++] = NULL;
- if (struct_level >= STRUCT_DEPTH)
- mmerror(ET_ERROR, "Too many levels in nested structure definition");
- } '{' sql_variable_declarations '}'
- {
- ECPGfree_struct_member(struct_member_list[struct_level--]);
- $$.type_str = cat_str(3, make_str("union {"), $4, make_str("}"));
- $$.type_enum = ECPGt_union;
- $$.type_index = -1;
- $$.type_dimension = -1;
- }
- | symbol
- {
- struct typedefs *this = get_typedef($1);
-
- $$.type_str = mm_strdup($1);
- $$.type_enum = this->type->type_enum;
- $$.type_dimension = this->type->type_dimension;
- $$.type_index = this->type->type_index;
- struct_member_list[struct_level] = this->struct_member_list;
- }
-
-opt_signed: SQL_SIGNED | /* empty */
-
-sql_variable_declarations: /* empty */
- {
- $$ = EMPTY;
- }
- | sql_declaration sql_variable_declarations
- {
- $$ = cat2_str($1, $2);
- }
- ;
-
-sql_declaration: ctype
- {
- actual_type[struct_level].type_enum = $1.type_enum;
- actual_type[struct_level].type_dimension = $1.type_dimension;
- actual_type[struct_level].type_index = $1.type_index;
- }
- sql_variable_list ';'
- {
- $$ = cat_str(3, $1.type_str, $3, make_str(";"));
- }
-
-sql_variable_list: sql_variable
- {
- $$ = $1;
- }
- | sql_variable_list ',' sql_variable
- {
- $$ = cat_str(3, $1, make_str(","), $3);
- }
-
-sql_variable: opt_pointer symbol opt_array_bounds
- {
- int dimension = $3.index1;
- int length = $3.index2;
- struct ECPGtype * type;
- char dim[14L];
-
- adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
-
- switch (actual_type[struct_level].type_enum)
- {
- case ECPGt_struct:
- case ECPGt_union:
- if (dimension < 0)
- type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum);
- else
- type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum), dimension);
-
- break;
- case ECPGt_varchar:
- if (dimension == -1)
- type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
- switch(dimension)
- {
- case 0:
- strcpy(dim, "[]");
- break;
- case -1:
- case 1:
- *dim = '\0';
- break;
- default:
- sprintf(dim, "[%d]", dimension);
- break;
- }
-
- break;
- case ECPGt_char:
- case ECPGt_unsigned_char:
- if (dimension == -1)
- type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
- break;
- default:
- if (length >= 0)
- mmerror(ET_ERROR, "No multi-dimensional array support for simple data types");
-
- if (dimension < 0)
- type = ECPGmake_simple_type(actual_type[struct_level].type_enum, 1);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, 1), dimension);
-
- break;
- }
-
- if (struct_level == 0)
- new_variable($2, type);
- else
- ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
-
- $$ = cat_str(3, $1, $2, $3.str);
- }
-
/*
* define the type of one variable for embedded SQL
*/
-ECPGVar: SQL_VAR symbol IS ctype opt_type_array_bounds opt_reference
+ECPGVar: SQL_VAR symbol IS type opt_type_array_bounds opt_reference
{
struct variable *p = find_variable($2);
int dimension = $5.index1;
int length = $5.index2;
struct ECPGtype * type;
+ if (($4.type_enum == ECPGt_struct ||
+ $4.type_enum == ECPGt_union) &&
+ initializer == 1)
+ mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
switch ($4.type_enum)
@@ -5561,25 +5391,25 @@ c_anything: IDENT { $$ = $1; }
| '-' { $$ = make_str("-"); }
| '/' { $$ = make_str("/"); }
| '%' { $$ = make_str("%"); }
+ | S_ANYTHING { $$ = make_name(); }
| S_AUTO { $$ = make_str("auto"); }
- | S_BOOL { $$ = make_str("bool"); }
- | S_CHAR { $$ = make_str("char"); }
| S_CONST { $$ = make_str("const"); }
- | S_DOUBLE { $$ = make_str("double"); }
- | S_ENUM { $$ = make_str("enum"); }
| S_EXTERN { $$ = make_str("extern"); }
- | S_FLOAT { $$ = make_str("float"); }
- | S_INT { $$ = make_str("int"); }
- | S_LONG { $$ = make_str("long"); }
| S_REGISTER { $$ = make_str("register"); }
- | S_SHORT { $$ = make_str("short"); }
- | S_SIGNED { $$ = make_str("signed"); }
| S_STATIC { $$ = make_str("static"); }
- | S_STRUCT { $$ = make_str("struct"); }
- | S_UNION { $$ = make_str("union"); }
- | S_UNSIGNED { $$ = make_str("unsigned"); }
- | S_VARCHAR { $$ = make_str("varchar"); }
- | S_ANYTHING { $$ = make_name(); }
+ | SQL_BOOL { $$ = make_str("bool"); }
+ | SQL_ENUM { $$ = make_str("enum"); }
+ | SQL_INT { $$ = make_str("int"); }
+ | SQL_LONG { $$ = make_str("long"); }
+ | SQL_SHORT { $$ = make_str("short"); }
+ | SQL_SIGNED { $$ = make_str("signed"); }
+ | SQL_STRUCT { $$ = make_str("struct"); }
+ | SQL_UNSIGNED { $$ = make_str("unsigned"); }
+ | CHAR { $$ = make_str("char"); }
+ | DOUBLE { $$ = make_str("double"); }
+ | FLOAT { $$ = make_str("float"); }
+ | UNION { $$ = make_str("union"); }
+ | VARCHAR { $$ = make_str("varchar"); }
| '[' { $$ = make_str("["); }
| ']' { $$ = make_str("]"); }
/* | '(' { $$ = make_str("("); }
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 1af1e63344f..efc8c669238 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -138,3 +138,5 @@ struct arguments
struct variable *indicator;
struct arguments *next;
};
+
+enum errortype {ET_WARN, ET_ERROR, ET_FATAL};
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
index e183ebc4b9f..0af784f8eab 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -1,10 +1,12 @@
-all: test1 test2 test3 test4 perftest
+all: stp.so test1 test2 test3 test4 test5 perftest
#LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt
LDFLAGS=-g -I../include -I/usr/include/postgresql -L/usr/lib/postgresql -L../lib -lecpg -lpq -lcrypt
+#LDFLAGS=-g -I/usr/include/postgresql -lecpg -lpq -lcrypt
#ECPG=/usr/local/pgsql/bin/ecpg
ECPG=../preproc/ecpg -I../include
+#ECPG=/usr/bin/ecpg -I/usr/include/postgresql
.SUFFIXES: .pgc .c
@@ -12,10 +14,16 @@ test1: test1.c
test2: test2.c
test3: test3.c
test4: test4.c
+test5: test5.c
perftest: perftest.c
.pgc.c:
$(ECPG) $?
+stp.so: stp.c
+ cc -fPIC -I../include -I/usr/include/postgresql -c -o stp.o stp.c
+ cc -shared -Wl,-soname,stp.so -o stp.so stp.o -lpq -lecpg
+
+
clean:
- -/bin/rm test1 test2 test3 test4 perftest *.c log
+ -/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so
diff --git a/src/interfaces/ecpg/test/stp.pgc b/src/interfaces/ecpg/test/stp.pgc
new file mode 100644
index 00000000000..6021ae0db40
--- /dev/null
+++ b/src/interfaces/ecpg/test/stp.pgc
@@ -0,0 +1,16 @@
+EXEC SQL INCLUDE sqlca;
+
+int my_fun (void)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int sql_index = 0;
+ EXEC SQL END DECLARE SECTION;
+
+ EXEC SQL WHENEVER SQLERROR GOTO Error;
+ EXEC SQL SELECT MIN(index) INTO :sql_index FROM tab;
+
+ return (sql_index);
+
+Error:
+ return (sqlca.sqlcode);
+ }
diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc
index d8980ade54b..02a631a12f5 100644
--- a/src/interfaces/ecpg/test/test1.pgc
+++ b/src/interfaces/ecpg/test/test1.pgc
@@ -94,11 +94,20 @@ exec sql end declare section;
strcpy(msg, "select");
exec sql select name, amount, letter into :name, :amount, :letter from "Test";
+ printf("Database: mm\n");
for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
+ {
printf("name[%d]=%8.8s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
+ amount[i]+=1000;
+ }
+ strcpy(msg, "insert");
+ exec sql at pm insert into "Test" (name, amount, letter) values (:name, :amount, :letter);
+
+ strcpy(msg, "select");
exec sql at pm select * into :name, :amount, :letter from "Test";
+ printf("Database: pm\n");
for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
printf("name[%d]=%8.8s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
index 3288b7df6a5..2c5d16c4448 100644
--- a/src/interfaces/ecpg/test/test2.pgc
+++ b/src/interfaces/ecpg/test/test2.pgc
@@ -62,7 +62,7 @@ exec sql end declare section;
while (1) {
strcpy(msg, "fetch");
- exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
+ exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
printf("%8.8s", personal.name.arr);
if (ind_personal.ind_birth.born >= 0)
printf(", born %d", personal.birth.born);
diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc
index 8e0f6c30c6e..8ba8995e334 100644
--- a/src/interfaces/ecpg/test/test3.pgc
+++ b/src/interfaces/ecpg/test/test3.pgc
@@ -19,7 +19,7 @@ exec sql begin declare section;
int ind_children;
str *married = NULL;
char *wifesname="Petra";
- char *query="select * from meskes where name = :var1";
+ char *query="select * from meskes where name = ?";
exec sql end declare section;
exec sql declare cur cursor for
@@ -54,7 +54,7 @@ exec sql end declare section;
while (1) {
strcpy(msg, "fetch");
- exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children:ind_children;
+ exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children:ind_children;
printf("%8.8s", personal.name.arr);
if (ind_personal.ind_birth.born >= 0)
printf(", born %d", personal.birth.born);
@@ -74,7 +74,7 @@ exec sql end declare section;
exec sql close cur;
/* and now a query with prepare */
- exec sql prepare MM from "select name, born, age, married, children from meskes where name = ?";
+ exec sql prepare MM from :query;
exec sql declare prep cursor for MM;
strcpy(msg, "open");
diff --git a/src/interfaces/ecpg/test/test5.pgc b/src/interfaces/ecpg/test/test5.pgc
new file mode 100644
index 00000000000..1e0c60c4ddb
--- /dev/null
+++ b/src/interfaces/ecpg/test/test5.pgc
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+EXEC SQL INCLUDE sqlca;
+
+static void ErrorExit (void);
+
+int main (void)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int result;
+ int values[2], i;
+ EXEC SQL END DECLARE SECTION;
+ FILE *dbgs;
+
+
+ if ((dbgs = fopen("log", "w")) != NULL)
+ ECPGdebug(1, dbgs);
+
+ EXEC SQL WHENEVER SQLERROR DO ErrorExit();
+ EXEC SQL CONNECT TO 'mm';
+ EXEC SQL CREATE TABLE tab (index int);
+ EXEC SQL INSERT INTO tab(index) values(14);
+ EXEC SQL INSERT INTO tab(index) values(7);
+ EXEC SQL COMMIT;
+
+ EXEC SQL CREATE FUNCTION my_fun () RETURNS int AS
+ '/home/postgres/pgsql/src/interfaces/ecpg.mm/test/stp.so' LANGUAGE 'C';
+ EXEC SQL COMMIT;
+
+ EXEC SQL SELECT index INTO :values FROM tab;
+ for (i = 0; i < 2; i++)
+ printf("tab[%d] = %d\n", i, values[i]);
+
+ EXEC SQL SELECT my_fun () INTO :result;
+ printf ("result = %d\n", result);
+
+ EXEC SQL DROP TABLE tab;
+ EXEC SQL DROP FUNCTION my_fun ();
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT;
+
+ if (dbgs != NULL)
+ fclose(dbgs);
+ exit (0);
+ }
+
+
+static void ErrorExit (void)
+ {
+ EXEC SQL WHENEVER SQLERROR CONTINUE;
+
+ sqlprint();
+
+ EXEC SQL DROP TABLE tab;
+ EXEC SQL DROP FUNCTION my_fun ();
+ EXEC SQL COMMIT;
+
+ EXEC SQL DISCONNECT;
+ exit (-1);
+ }