Commit 80f7c413 authored by Bruce Momjian's avatar Bruce Momjian

Here's my next patch to bring ecpg to version 1.1. It now correctly

handles all transaction commands and the exec sql include command.

Michael Meskes
parent 561aead3
......@@ -71,3 +71,18 @@ Fri Feb 27 12:00:55 CET 1998
- removed all shift/reduce conflicts
- allow syntax 'fetch cursor' as well as 'fetch in cursor'
Fri Mar 13 11:37:16 CET 1998
- finished transaction handling, needs only one function in ecpglib now
old functions are still supported for compatibility
- set library to version 1.1.0
Fri Mar 13 13:35:13 CET 1998
- exec sql include includes files during parsing
- set parser to version 1.1.0
- added -I option to ecpg to set include path
Mon Mar 16 15:09:10 CET 1998
- fixed parser to print correct filename and line number
......@@ -59,4 +59,7 @@ There is no way yet to fill a complete array with one call except arrays of
ecpg cannot use pointer variables except [unsigned] char *
List all commands as sqlcommand, not just S_SYMBOL
List all commands as sqlcommand, not just S_SYMBOL or even better rewrite
pareser to be equivalent to backend´s parser.
Set standard include paths.
#include <c.h>
#ifdef __cplusplus
extern "C" {
#endif
void ECPGdebug(int, FILE *);
bool ECPGconnect(const char *dbname);
bool ECPGdo(int, char *,...);
bool ECPGcommit(int);
bool ECPGrollback(int);
bool ECPGtrans(int, const char *);
bool ECPGfinish(void);
bool ECPGstatus(void);
void ECPGlog(const char *format,...);
/* These functions are only kept for compatibility reasons. */
/* Use ECPGtrans instead. */
bool ECPGcommit(int);
bool ECPGrollback(int);
#ifdef LIBPQ_FE_H
bool ECPGsetdb(PGconn *);
......@@ -32,3 +40,7 @@ void sqlprint(void);
/* define this for simplicity as well as compatibility */
#define SQLCODE sqlca.sqlcode
#ifdef __cplusplus
}
#endif
......@@ -29,6 +29,10 @@
*/
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
enum ECPGttype
{
ECPGt_char = 1, ECPGt_unsigned_char, ECPGt_short, ECPGt_unsigned_short,
......@@ -45,3 +49,7 @@ enum ECPGttype
#define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
const char * ECPGtype_name(enum ECPGttype);
#ifdef __cplusplus
}
#endif
#ifndef POSTGRES_SQLCA_H
#define POSTGRES_SQLCA_H
#ifdef __cplusplus
extern "C" {
#endif
struct sqlca
{
int sqlcode;
......@@ -12,3 +16,8 @@ struct sqlca
} sqlca;
#endif
#ifdef __cplusplus
}
#endif
......@@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
SO_MAJOR_VERSION=1
SO_MINOR_VERSION=0
SO_MINOR_VERSION=1
PORTNAME=@PORTNAME@
......
......@@ -572,14 +572,14 @@ ECPGdo(int lineno, char *query,...)
bool
ECPGcommit(int lineno)
ECPGtrans(int lineno, const char * transaction)
{
PGresult *res;
ECPGlog("ECPGcommit line %d\n", lineno);
if ((res = PQexec(simple_connection, "end")) == NULL)
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
if ((res = PQexec(simple_connection, transaction)) == NULL)
{
register_error(-1, "Error committing line %d.", lineno);
register_error(-1, "Error in transaction processing line %d.", lineno);
return (FALSE);
}
PQclear(res);
......@@ -587,23 +587,18 @@ ECPGcommit(int lineno)
return (TRUE);
}
/* include these for compatibility */
bool
ECPGrollback(int lineno)
ECPGcommit(int lineno)
{
PGresult *res;
ECPGlog("ECPGrollback line %d\n", lineno);
if ((res = PQexec(simple_connection, "abort")) == NULL)
{
register_error(-1, "Error rolling back line %d.", lineno);
return (FALSE);
}
PQclear(res);
committed = 1;
return (TRUE);
return(ECPGtrans(lineno, "end"));
}
bool
ECPGrollback(int lineno)
{
return(ECPGtrans(lineno, "abort"));
}
bool
ECPGsetdb(PGconn *newcon)
......
......@@ -2,10 +2,12 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global
MAJOR_VERSION=1
MINOR_VERSION=0
MINOR_VERSION=1
PATCHLEVEL=0
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL)
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
-DINCLUDE_PATH=\"$(DESTDIR)$(HEADERDIR)\"
all:: ecpg
......
......@@ -9,6 +9,8 @@
#include <getopt.h>
#else
#include <unistd.h>
extern int optind;
extern char *optarg;
#endif
#include <stdlib.h>
#if defined(HAVE_STRING_H)
......@@ -19,19 +21,37 @@
#include "extern.h"
struct _include_path *include_paths;
static void
usage(char *progname)
{
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "Usage: %s: [-v] [-d] [ -o outout file name] file1 [file2] ...\n", progname);
fprintf(stderr, "Usage: %s: [-v] [-d] [-I include path] [ -o output file name] file1 [file2] ...\n", progname);
}
static void
add_include_path(char * path)
{
struct _include_path *ip = include_paths;
include_paths = mm_alloc(sizeof(struct _include_path));
include_paths->path = path;
include_paths->next = ip;
}
int
main(int argc, char *const argv[])
{
int fnr, c, out_option = 0;
while ((c = getopt(argc, argv, "vdo:")) != EOF)
struct _include_path *ip;
add_include_path("/usr/include");
add_include_path(INCLUDE_PATH);
add_include_path("/usr/local/include");
add_include_path(".");
while ((c = getopt(argc, argv, "vdo:I:")) != EOF)
{
switch (c)
{
......@@ -45,64 +65,71 @@ main(int argc, char *const argv[])
case 'd':
debugging = 1;
break;
case 'I':
add_include_path(optarg);
break;
case 'v':
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "exec sql include ... search starts here:\n");
for (ip = include_paths; ip != NULL; ip = ip->next)
fprintf(stderr, " %s\n", ip->path);
fprintf(stderr, "End of search list.\n");
return (0);
default:
usage(argv[0]);
return (1);
}
}
if (optind >= argc) /* no files specified */
{
usage(argv[0]);
return(1);
}
else
{
/* after the options there must not be anything but filenames */
for (fnr = optind; fnr < argc; fnr++)
{
char *filename,
*ptr2ext;
int ext = 0;
char *output_filename, *ptr2ext;
filename = mm_alloc(strlen(argv[fnr]) + 4);
input_filename = mm_alloc(strlen(argv[fnr]) + 5);
strcpy(filename, argv[fnr]);
strcpy(input_filename, argv[fnr]);
ptr2ext = strrchr(filename, '.');
/* no extension or extension not equal .pgc */
if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0)
ptr2ext = strrchr(input_filename, '.');
/* no extension? */
if (ptr2ext == NULL)
{
if (ptr2ext == NULL)
ext = 1; /* we need this information a while later */
ptr2ext = filename + strlen(filename);
ptr2ext = input_filename + strlen(input_filename);
/* no extension => add .pgc */
ptr2ext[0] = '.';
ptr2ext[1] = 'p';
ptr2ext[2] = 'g';
ptr2ext[3] = 'c';
ptr2ext[4] = '\0';
}
/* make extension = .c */
ptr2ext[1] = 'c';
ptr2ext[2] = '\0';
if (out_option == 0)/* calculate the output name */
{
yyout = fopen(filename, "w");
output_filename = strdup(input_filename);
ptr2ext = strrchr(output_filename, '.');
/* make extension = .c */
ptr2ext[1] = 'c';
ptr2ext[2] = '\0';
yyout = fopen(output_filename, "w");
if (yyout == NULL)
{
perror(filename);
free(filename);
perror(output_filename);
free(output_filename);
free(input_filename);
continue;
}
}
if (ext == 1)
{
/* no extension => add .pgc */
ptr2ext = strrchr(filename, '.');
ptr2ext[1] = 'p';
ptr2ext[2] = 'g';
ptr2ext[3] = 'c';
ptr2ext[4] = '\0';
input_filename = filename;
}
else
input_filename = argv[fnr];
yyin = fopen(input_filename, "r");
if (yyin == NULL)
perror(argv[fnr]);
......@@ -117,12 +144,14 @@ main(int argc, char *const argv[])
/* and parse the source */
yyparse();
fclose(yyin);
if (yyin != NULL)
fclose(yyin);
if (out_option == 0)
fclose(yyout);
}
free(filename);
free(output_filename);
free(input_filename);
}
}
return (0);
......
......@@ -8,6 +8,11 @@ extern int yylineno,
extern FILE *yyin,
*yyout;
struct _include_path { char * path;
struct _include_path * next;
};
extern struct _include_path *include_paths;
/* functions */
......
/* Copyright comment! */
%{
#include <sys/types.h>
#include <limits.h>
#if defined(HAVE_STRING_H)
#include <string.h>
#else
#include <strings.h>
#endif
#include "type.h"
#include "y.tab.h"
#include "extern.h"
struct _yy_buffer { YY_BUFFER_STATE buffer;
long lineno;
char * filename;
struct _yy_buffer * next;
} *yy_buffer = NULL;
#define dbg(arg) if (debugging) fprintf(stderr, "DEBUG, %d: %s\n", yylineno, #arg);
%}
%option yylineno
%s C SQL
%s C SQL incl
ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/
ws ([ \t\n][ \t\n]*|{ccomment})*
letter [A-Za-z_]
......@@ -19,6 +32,7 @@ symbol {letter}({letter}|{digit})*
label ({letter}|{digit})*
string '[^']*'
abort [aA][bB][oO][rR][tT]
begin [bB][eE][gG][iI][nN]
commit [cC][oO][mM][mM][iI][tT]
connect [cC][oO][nN][nN][eE][cC][tT]
......@@ -46,21 +60,23 @@ sql [sS][qQ][lL]
sqlerror [sS][qQ][lL][eE][rR][rR][oO][rR]
sqlprint [sS][qQ][lL][pP][rR][iI][nN][tT]
stop [sS][tT][oO][pP]
transaction [tT][rR][aA][nN][sS][aA][cC][tT][iI][oO][nN]
to [tT][oO]
varchar [vV][aA][rR][cC][hH][aA][rR]
varchar2 [vV][aA][rR][cC][hH][aA][rR]2
whenever [wW][hH][eE][nN][eE][vV][eE][rR]
work [wW][oO][rR][kK]
vacuum [vV][aA][cC][uU][uU][mM]
%%
<C>{exec}{ws}{sql} { BEGIN SQL; dbg(SQL_START); return SQL_START; }
<SQL>";" { BEGIN C; dbg(SQL_SEMI); return SQL_SEMI; }
<SQL>{abort} { dbg(SQL_ABORT); return SQL_ABORT; }
<SQL>{begin} { dbg(SQL_BEGIN); return SQL_BEGIN; }
<SQL>{end} { dbg(SQL_END); return SQL_END; }
<SQL>{declare} { dbg(SQL_DECLARE); return SQL_DECLARE; }
<SQL>{execute} { dbg(SQL_EXECUTE); return SQL_EXECUTE; }
<SQL>{immediate} { dbg(SQL_IMMEDIATE); return SQL_IMMEDIATE; }
<SQL>{section} { dbg(SQL_SECTION); return SQL_SECTION; }
<SQL>{include} { dbg(SQL_INCLUDE); return SQL_INCLUDE; }
<SQL>{connect} { dbg(SQL_CONNECT); return SQL_CONNECT; }
<SQL>{open} { dbg(SQL_OPEN); return SQL_OPEN; }
<SQL>{commit} { dbg(SQL_COMMIT); return SQL_COMMIT; }
......@@ -80,7 +96,62 @@ work [wW][oO][rR][kK]
<SQL>{stop} { dbg(SQL_STOP); return SQL_STOP; }
<SQL>{do} { dbg(SQL_DO); return SQL_DO; }
<SQL>{from} { dbg(SQL_FROM); return SQL_FROM; }
<SQL>{transaction} { dbg(SQL_TRANSACTION); return SQL_TRANSACTION; }
<SQL>{vacuum} { dbg(SQL_VACUUM); return SQL_VACUUM; }
<C>{exec}{ws}{sql}{ws}{include} { BEGIN(incl); }
<incl>{ws} /* eat the whitespace */
<incl>[^ \t\n]+ { /* got the include file name */
struct _yy_buffer *yb;
struct _include_path *ip;
char inc_file[PATH_MAX];
yb = mm_alloc(sizeof(struct _yy_buffer));
yb->buffer = YY_CURRENT_BUFFER;
yb->lineno = yylineno;
yb->filename = input_filename;
yb->next = yy_buffer;
yy_buffer = yb;
if (yytext[strlen(yytext) - 1] == ';')
yytext[strlen(yytext) - 1] = '\0';
yyin = NULL;
for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next)
{
if (strlen(ip->path) + strlen(yytext) + 3 > PATH_MAX)
{
fprintf(stderr, "Path %s/%s is too long, skipping.\n", ip->path, yytext);
continue;
}
sprintf (inc_file, "%s/%s", ip->path, yytext);
yyin = fopen( inc_file, "r" );
if (!yyin)
{
if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
{
strcat(inc_file, ".h");
yyin = fopen( inc_file, "r" );
}
}
}
if (!yyin)
{
fprintf(stderr, "Cannot open include file %s\n", yytext);
exit(1);
}
input_filename = strdup(inc_file);
yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
yylineno = 0;
BEGIN C;
}
<incl>";" { BEGIN C; }
{length} { dbg(S_LENGTH); return S_LENGTH; }
{varchar} { dbg(S_VARCHAR); return S_VARCHAR; }
......@@ -154,6 +225,28 @@ struct { dbg(S_STRUCT); return S_STRUCT; }
{ws} { ECHO; }
. { dbg(.); return S_ANYTHING; }
<<EOF>> { if (yy_buffer == NULL)
yyterminate();
else
{
struct _yy_buffer *yb = yy_buffer;
if (yyin != NULL)
fclose(yyin);
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(yy_buffer->buffer);
yylineno = yy_buffer->lineno;
free(input_filename);
input_filename = yy_buffer->filename;
yy_buffer = yy_buffer->next;
free(yb);
}
}
%%
void
lex_init(void)
......
......@@ -226,6 +226,7 @@ dump_variables(struct arguments * list)
%token <tagname> SQL_COMMIT SQL_ROLLBACK SQL_RELEASE SQL_WORK SQL_WHENEVER
%token <tagname> SQL_SQLERROR SQL_NOT_FOUND SQL_CONTINUE SQL_FROM SQL_FETCH
%token <tagname> SQL_DO SQL_GOTO SQL_SQLPRINT SQL_STOP SQL_CONV
%token <tagname> SQL_ABORT SQL_TRANSACTION SQL_VACUUM
%token <tagname> S_SYMBOL S_LENGTH S_ANYTHING S_LABEL
%token <tagname> S_VARCHAR S_VARCHAR2
......@@ -236,32 +237,31 @@ dump_variables(struct arguments * list)
%type <type> type type_detailed varchar_type simple_type struct_type string_type
/* % type <type> array_type pointer_type */
%type <symbolname> symbol label
%type <symbolname> symbol label transactionstmt
%type <tagname> maybe_storage_clause varchar_tag db_name cursor
%type <type_enum> simple_tag char_tag
%type <indexsize> index length
%type <action> action
%type <tagname> canything sqlanything both_anything vartext commit_release sqlcommand
%type <tagname> canything sqlanything both_anything vartext sqlcommand
%type <tagname> transbegin, transend, transabort
%%
prog : statements;
statements : /* empty */
| statements statement;
statement : sqldeclaration
statement : sqlconnect
| sqldeclaration
| sqlexecute
| sqlfetch
| sqlinclude
| sqlconnect
| sqlopen
| sqlcommit
| sqlrollback
| sqlexecute
| sqlwhenever
| sqlstatement
| sqlfetch
| cthing
| sqltransaction
| sqlwhenever
| blockstart
| blockend;
| blockend
| cthing;
sqldeclaration : sql_startdeclare
variable_declarations
......@@ -489,19 +489,32 @@ sqlgarbage : /* Empty */
| sqlgarbage sqlanything;
sqlcommit : SQL_START commit_release SQL_SEMI {
fprintf(yyout, "ECPGcommit(__LINE__);");
sqltransaction : SQL_START transactionstmt SQL_SEMI {
fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $<symbolname>2);
whenever_action();
}
commit_release : SQL_COMMIT
| SQL_COMMIT SQL_RELEASE
| SQL_COMMIT SQL_WORK SQL_RELEASE;
sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI {
fprintf(yyout, "ECPGrollback(__LINE__);");
whenever_action();
};
transactionstmt: transbegin
{
$<symbolname>$="begin";
}
| transend
{
$<symbolname>$="end";
}
| transabort
{
$<symbolname>$="abort";
}
transabort: SQL_ABORT SQL_TRANSACTION | SQL_ROLLBACK SQL_WORK
| SQL_ABORT | SQL_ROLLBACK;
transend: SQL_END SQL_TRANSACTION | SQL_COMMIT | SQL_COMMIT SQL_RELEASE
| SQL_COMMIT SQL_WORK SQL_RELEASE;
transbegin: SQL_BEGIN SQL_TRANSACTION | SQL_BEGIN SQL_WORK;
sqlexecute : SQL_START SQL_EXECUTE SQL_IMMEDIATE ':' symbol SQL_SEMI {
fprintf(yyout, "ECPGdo(__LINE__, %s, ECPGt_EOIT, ECPGt_EORT );", $5);
......@@ -605,9 +618,9 @@ sqlstatement : SQL_START { /* Reset stack */
}
/* FIXME: instead of S_SYMBOL we should list all possible commands */
sqlcommand : S_SYMBOL | SQL_DECLARE;
sqlcommand : S_SYMBOL | SQL_DECLARE | SQL_VACUUM;
sqlstatement_words : sqlstatement_word
sqlstatement_words : /* empty */
| sqlstatement_words sqlstatement_word;
sqlstatement_word : ':' symbol
......
......@@ -16,6 +16,7 @@ print_result(long sec, long usec, char *text)
usec+=1000000;
}
printf("I needed %ld seconds and %ld microseconds for the %s test.\n", sec, usec, text);
exec sql vacuum analyze;
}
int
......@@ -107,7 +108,5 @@ exec sql end declare section;
exec sql drop table perftest1;
exec sql commit;
return (0);
}
#include <stdio.h>
exec sql include sqlca;
exec sql include header_test;
extern void ECPGdebug(int n, FILE *dbgs);
exec sql whenever not found do set_not_found();
exec sql whenever sqlerror sqlprint;
static int not_found = 0;
static void
set_not_found(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment