Add DECLARE STATEMENT command to ECPG

This command declares a SQL identifier for a SQL statement to be used in other
embedded SQL statements. The identifier is linked to a connection.

Author: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Shawn Wang <shawn.wang.pg@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/TY2PR01MB24438A52DB04E71D0E501452F5630@TY2PR01MB2443.jpnprd01.prod.outlook.com
This commit is contained in:
Michael Meskes 2021-03-24 20:48:20 +01:00
parent 37c99d304d
commit ad8305a43d
15 changed files with 1398 additions and 17 deletions

View File

@ -278,7 +278,7 @@ EXEC SQL CONNECT TO :target USER :user USING :passwd;
SQL statements in embedded SQL programs are by default executed on
the current connection, that is, the most recently opened one. If
an application needs to manage multiple connections, then there are
two ways to handle this.
three ways to handle this.
</para>
<para>
@ -350,6 +350,46 @@ main()
current=testdb3 (should be testdb3)
current=testdb2 (should be testdb2)
current=testdb1 (should be testdb1)
</screen>
</para>
<para>
The third option is to declare sql identifier linked to
the connection, for example:
<programlisting>
EXEC SQL AT <replaceable>connection-name</replaceable> DECLARE <replaceable>statement-name</replaceable> STATEMENT;
EXEC SQL PREPARE <replaceable>statement-name</replaceable> FROM :<replaceable>dyn-string</replaceable>;
</programlisting>
Once you link a sql identifier to a connection, you execute a dynamic SQL
without AT clause. Note that this option behaves like preprocessor directives,
therefore the link is enabled only in the file.
</para>
<para>
Here is an example program using this option:
<programlisting><![CDATA[
#include <stdio.h>
EXEC SQL BEGIN DECLARE SECTION;
char dbname[128];
char *dym_sql = "SELECT current_database()";
EXEC SQL END DECLARE SECTION;
int main(){
EXEC SQL CONNECT TO postgres AS con1;
EXEC SQL CONNECT TO testdb AS con2;
EXEC SQL AT con1 DECLARE stmt STATEMENT;
EXEC SQL PREPARE stmt FROM :dym_sql;
EXEC SQL EXECUTE stmt INTO :dbname;
printf("%s\n", dbname);
EXEC SQL DISCONNECT ALL;
return 0;
}
]]></programlisting>
This example would produce this output, even if the default connection is testdb:
<screen>
postgres
</screen>
</para>
</sect2>
@ -6855,6 +6895,104 @@ EXEC SQL DECLARE cur1 CURSOR FOR stmt1;
</refsect1>
</refentry>
<refentry id="ecpg-sql-declare-statement">
<refnamediv>
<refname>DECLARE STATEMENT</refname>
<refpurpose>declare SQL statement identifier</refpurpose>
</refnamediv>
<refsynopsisdiv>
<synopsis>
EXEC SQL [ AT <replaceable class="parameter">connection_name</replaceable> ] DECLARE <replaceable class="parameter">statement_name</replaceable> STATEMENT
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>DECLARE STATEMENT</command> declares SQL statement identifier.
SQL statement identifier can be associated with the connection.
When the identifier is used by dynamic SQL statements, these SQLs are executed
by using the associated connection.
The namespace of the declaration is the precompile unit, and multiple declarations to
the same SQL statement identifier is not allowed.
Note that if the precompiler run in the Informix compatibility mode and some SQL statement
is declared, "database" can not be used as a cursor name.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">connection_name</replaceable></term>
<listitem>
<para>
A database connection name established by the <command>CONNECT</command> command.
</para>
<para>
AT clause can be omitted, but such statement has no meaning.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">statement_name</replaceable></term>
<listitem>
<para>
The name of a SQL statement identifier, either as an SQL identifier or a host variable.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
This association is valid only if the declaration is physically placed on top of a dynamic statement.
</para>
</refsect1>
<refsect1>
<title>Examples</title>
<programlisting>
EXEC SQL CONNECT TO postgres AS con1;
EXEC SQL AT con1 DECLARE sql_stmt STATEMENT;
EXEC SQL DECLARE cursor_name CURSOR FOR sql_stmt;
EXEC SQL PREPARE sql_stmt FROM :dyn_string;
EXEC SQL OPEN cursor_name;
EXEC SQL FETCH cursor_name INTO :column1;
EXEC SQL CLOSE cursor_name;
</programlisting>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>DECLARE STATEMENT</command> is a extension of the SQL standard,
but can be used in famous DBMSs.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="ecpg-sql-connect"/></member>
<member><xref linkend="ecpg-sql-declare"/></member>
<member><xref linkend="ecpg-sql-open"/></member>
</simplelist>
</refsect1>
</refentry>
<refentry id="ecpg-sql-describe">
<refnamediv>
<refname>DESCRIBE</refname>

View File

@ -33,6 +33,7 @@ ECPG: stmtUpdateStmt block
{ output_statement($1, 1, ECPGst_prepnormal); }
ECPG: stmtExecuteStmt block
{
check_declared_list($1.name);
if ($1.type == NULL || strlen($1.type) == 0)
output_statement($1.name, 1, ECPGst_execute);
else
@ -56,6 +57,7 @@ ECPG: stmtExecuteStmt block
}
ECPG: stmtPrepareStmt block
{
check_declared_list($1.name);
if ($1.type == NULL)
output_prepare_statement($1.name, $1.stmt);
else if (strlen($1.type) == 0)
@ -104,6 +106,10 @@ ECPG: stmtViewStmt rule
whenever_action(2);
free($1);
}
| ECPGDeclareStmt
{
output_simple_statement($1, 0);
}
| ECPGCursorStmt
{
output_simple_statement($1, (strncmp($1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0);
@ -244,14 +250,20 @@ ECPG: var_valueNumericOnly addon
$1 = mm_strdup("$0");
}
ECPG: fetch_argscursor_name addon
add_additional_variables($1, false);
struct cursor *ptr = add_additional_variables($1, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($1[0] == ':')
{
free($1);
$1 = mm_strdup("$0");
}
ECPG: fetch_argsfrom_incursor_name addon
add_additional_variables($2, false);
struct cursor *ptr = add_additional_variables($2, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($2[0] == ':')
{
free($2);
@ -262,14 +274,20 @@ ECPG: fetch_argsPRIORopt_from_incursor_name addon
ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
ECPG: fetch_argsLAST_Popt_from_incursor_name addon
ECPG: fetch_argsALLopt_from_incursor_name addon
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($3[0] == ':')
{
free($3);
$3 = mm_strdup("$0");
}
ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($3[0] == ':')
{
free($3);
@ -282,7 +300,10 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
}
ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($4[0] == ':')
{
free($4);
@ -292,7 +313,10 @@ ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
if ($4[0] == ':')
{
free($4);
@ -348,6 +372,9 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
char *comment, *c1, *c2;
int (* strcmp_fn)(const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp);
if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0)
mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode");
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
if (strcmp_fn($2, ptr->name) == 0)
@ -388,6 +415,17 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
ECPG: ClosePortalStmtCLOSEcursor_name block
{
char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : $2;
struct cursor *ptr = NULL;
for (ptr = cur; ptr != NULL; ptr = ptr -> next)
{
if (strcmp($2, ptr -> name) == 0)
{
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
break;
}
}
$$ = cat2_str(mm_strdup("close"), cursor_marker);
}
ECPG: opt_hold block
@ -466,49 +504,73 @@ ECPG: FetchStmtMOVEfetch_args rule
| FETCH FORWARD cursor_name opt_ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("fetch forward"), cursor_marker);
}
| FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into
{
char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("fetch forward from"), cursor_marker);
}
| FETCH BACKWARD cursor_name opt_ecpg_fetch_into
{
char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("fetch backward"), cursor_marker);
}
| FETCH BACKWARD from_in cursor_name opt_ecpg_fetch_into
{
char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("fetch backward from"), cursor_marker);
}
| MOVE FORWARD cursor_name
{
char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("move forward"), cursor_marker);
}
| MOVE FORWARD from_in cursor_name
{
char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("move forward from"), cursor_marker);
}
| MOVE BACKWARD cursor_name
{
char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
add_additional_variables($3, false);
struct cursor *ptr = add_additional_variables($3, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("move backward"), cursor_marker);
}
| MOVE BACKWARD from_in cursor_name
{
char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
add_additional_variables($4, false);
struct cursor *ptr = add_additional_variables($4, false);
if (ptr -> connection)
connection = mm_strdup(ptr -> connection);
$$ = cat_str(2, mm_strdup("move backward from"), cursor_marker);
}
ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block

View File

@ -28,6 +28,7 @@ struct _include_path *include_paths = NULL;
struct cursor *cur = NULL;
struct typedefs *types = NULL;
struct _defines *defines = NULL;
struct declared_list *g_declared_list = NULL;
static void
help(const char *progname)
@ -347,6 +348,7 @@ main(int argc, char *const argv[])
struct cursor *ptr;
struct _defines *defptr;
struct typedefs *typeptr;
struct declared_list *list;
/* remove old cursor definitions if any are still there */
for (ptr = cur; ptr != NULL;)
@ -373,6 +375,13 @@ main(int argc, char *const argv[])
}
cur = NULL;
/* remove old delared statements if any are still there */
for (list = g_declared_list; list != NULL;)
{
struct declared_list *this = list;
free(this);
}
/* remove non-pertinent old defines as well */
while (defines && !defines->pertinent)
{

View File

@ -64,6 +64,8 @@ static struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NUL
static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0);
static bool check_declared_list(const char*);
/*
* Handle parsing errors and warnings
*/
@ -576,6 +578,29 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
types = this;
}
}
/*
* check an SQL identifier is declared or not.
* If it is already declared, the global variable
* connection will be changed to the related connection.
*/
static bool
check_declared_list(const char *name)
{
struct declared_list *ptr = NULL;
for (ptr = g_declared_list; ptr != NULL; ptr = ptr -> next)
{
if (strcmp(name, ptr -> name) == 0)
{
if (ptr -> connection)
{
connection = mm_strdup(ptr -> connection);
return true;
}
}
}
return false;
}
%}
%expect 0

View File

@ -290,6 +290,42 @@ prepared_name: name
| char_variable { $$ = $1; }
;
/*
* Declare Statement
*/
ECPGDeclareStmt: DECLARE prepared_name STATEMENT
{
struct declared_list *ptr = NULL;
/* Check whether the declared name has been defined or not */
for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next)
{
if (strcmp($2, ptr->name) == 0)
{
/* re-definition is not allowed */
mmerror(PARSE_ERROR, ET_ERROR, "declared name %s is already defined", ptr->name);
}
}
/* Add a new declared name into the g_declared_list */
ptr = NULL;
ptr = (struct declared_list *)mm_alloc(sizeof(struct declared_list));
if (ptr)
{
/* initial definition */
ptr -> name = $2;
if (connection)
ptr -> connection = mm_strdup(connection);
else
ptr -> connection = NULL;
ptr -> next = g_declared_list;
g_declared_list = ptr;
}
$$ = cat_str(3 , mm_strdup("/* declare "), mm_strdup($2), mm_strdup(" as an SQL identifier */"));
}
;
/*
* Declare a prepared cursor. The syntax is different from the standard
* declare statement, so we create a new rule.
@ -300,9 +336,14 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2);
int (* strcmp_fn)(const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp);
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
char *comment;
char *con;
if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0)
mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode");
check_declared_list($7);
con = connection ? connection : "NULL";
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
if (strcmp_fn($2, ptr->name) == 0)
@ -321,7 +362,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
this->next = cur;
this->name = $2;
this->function = (current_function ? mm_strdup(current_function) : NULL);
this->connection = connection;
this->connection = connection ? mm_strdup(connection) : NULL;
this->command = cat_str(6, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for $1"));
this->argsresult = NULL;
this->argsresult_oos = NULL;

View File

@ -9,6 +9,7 @@
%type <str> ECPGDeallocateDescr
%type <str> ECPGDeclaration
%type <str> ECPGDeclare
%type <str> ECPGDeclareStmt
%type <str> ECPGDescribe
%type <str> ECPGDisconnect
%type <str> ECPGExecuteImmediateStmt

View File

@ -47,6 +47,7 @@ extern struct _include_path *include_paths;
extern struct cursor *cur;
extern struct typedefs *types;
extern struct _defines *defines;
extern struct declared_list *g_declared_list;
extern struct ECPGtype ecpg_no_indicator;
extern struct variable no_indicator;
extern struct arguments *argsinsert;

View File

@ -141,6 +141,13 @@ struct cursor
struct cursor *next;
};
struct declared_list
{
char *name;
char *connection;
struct declared_list *next;
};
struct typedefs
{
char *name;

View File

@ -53,6 +53,7 @@ test: sql/show
test: sql/insupd
test: sql/parser
test: sql/prepareas
test: sql/declare
test: thread/thread
test: thread/thread_implicit
test: thread/prep

View File

@ -0,0 +1,580 @@
/* Processed by ecpg (regression mode) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* End of automatic include section */
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
#line 1 "declare.pgc"
#include <locale.h>
#include <string.h>
#include <stdlib.h>
/* exec sql whenever sqlerror sqlprint ; */
#line 5 "declare.pgc"
#line 1 "sqlca.h"
#ifndef POSTGRES_SQLCA_H
#define POSTGRES_SQLCA_H
#ifndef PGDLLIMPORT
#if defined(WIN32) || defined(__CYGWIN__)
#define PGDLLIMPORT __declspec (dllimport)
#else
#define PGDLLIMPORT
#endif /* __CYGWIN__ */
#endif /* PGDLLIMPORT */
#define SQLERRMC_LEN 150
#ifdef __cplusplus
extern "C"
{
#endif
struct sqlca_t
{
char sqlcaid[8];
long sqlabc;
long sqlcode;
struct
{
int sqlerrml;
char sqlerrmc[SQLERRMC_LEN];
} sqlerrm;
char sqlerrp[8];
long sqlerrd[6];
/* Element 0: empty */
/* 1: OID of processed tuple if applicable */
/* 2: number of rows processed */
/* after an INSERT, UPDATE or */
/* DELETE statement */
/* 3: empty */
/* 4: empty */
/* 5: empty */
char sqlwarn[8];
/* Element 0: set to 'W' if at least one other is 'W' */
/* 1: if 'W' at least one character string */
/* value was truncated when it was */
/* stored into a host variable. */
/*
* 2: if 'W' a (hopefully) non-fatal notice occurred
*/ /* 3: empty */
/* 4: empty */
/* 5: empty */
/* 6: empty */
/* 7: empty */
char sqlstate[5];
};
struct sqlca_t *ECPGget_sqlca(void);
#ifndef POSTGRES_ECPG_INTERNAL
#define sqlca (*ECPGget_sqlca())
#endif
#ifdef __cplusplus
}
#endif
#endif
#line 7 "declare.pgc"
#line 1 "regression.h"
#line 8 "declare.pgc"
#define ARRAY_SZIE 20
void execute_test(void);
void commitTable(void);
void reset(void);
void printResult(char *tc_name, int loop);
/* exec sql begin declare section */
#line 18 "declare.pgc"
int f1 [ ARRAY_SZIE ] ;
#line 19 "declare.pgc"
int f2 [ ARRAY_SZIE ] ;
#line 20 "declare.pgc"
char f3 [ ARRAY_SZIE ] [ 20 ] ;
/* exec sql end declare section */
#line 21 "declare.pgc"
int main(void)
{
setlocale(LC_ALL, "C");
ECPGdebug(1, stderr);
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "con1", 0);
#line 29 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 29 "declare.pgc"
{ ECPGconnect(__LINE__, 0, "ecpg2_regression" , NULL, NULL , "con2", 0);
#line 30 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 30 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "create table source ( f1 integer , f2 integer , f3 varchar ( 20 ) )", ECPGt_EOIT, ECPGt_EORT);
#line 32 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 32 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "create table source ( f1 integer , f2 integer , f3 varchar ( 20 ) )", ECPGt_EOIT, ECPGt_EORT);
#line 33 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 33 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "insert into source values ( 1 , 10 , 'db on con1' )", ECPGt_EOIT, ECPGt_EORT);
#line 35 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 35 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "insert into source values ( 2 , 20 , 'db on con1' )", ECPGt_EOIT, ECPGt_EORT);
#line 36 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 36 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "insert into source values ( 1 , 10 , 'db on con2' )", ECPGt_EOIT, ECPGt_EORT);
#line 38 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 38 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "insert into source values ( 2 , 20 , 'db on con2' )", ECPGt_EOIT, ECPGt_EORT);
#line 39 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 39 "declare.pgc"
commitTable();
execute_test();
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "drop table if exists source", ECPGt_EOIT, ECPGt_EORT);
#line 45 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 45 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "drop table if exists source", ECPGt_EOIT, ECPGt_EORT);
#line 46 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 46 "declare.pgc"
commitTable();
{ ECPGdisconnect(__LINE__, "ALL");
#line 50 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 50 "declare.pgc"
return 0;
}
/*
* default connection: con2
* Non-default connection: con1
*
*/
void execute_test(void)
{
/* exec sql begin declare section */
#line 63 "declare.pgc"
int i ;
#line 64 "declare.pgc"
char * selectString = "SELECT f1,f2,f3 FROM source" ;
/* exec sql end declare section */
#line 65 "declare.pgc"
/*
* testcase1. using DECLARE STATEMENT without using AT clause,
* using PREPARE and CURSOR statement without using AT clause
*/
reset();
/* declare \"stmt_1\" as an SQL identifier */
#line 73 "declare.pgc"
{ ECPGprepare(__LINE__, NULL, 0, "stmt_1", selectString);
#line 74 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 74 "declare.pgc"
/* declare cur_1 cursor for $1 */
#line 75 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur_1 cursor for $1",
ECPGt_char_variable,(ECPGprepared_statement(NULL, "stmt_1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
#line 76 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 76 "declare.pgc"
/* exec sql whenever not found break ; */
#line 78 "declare.pgc"
i = 0;
while (1)
{
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch cur_1", ECPGt_EOIT,
ECPGt_int,&(f1[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(f2[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(f3[i]),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 82 "declare.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
#line 82 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 82 "declare.pgc"
i++;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_1", ECPGt_EOIT, ECPGt_EORT);
#line 85 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 85 "declare.pgc"
{ ECPGdeallocate(__LINE__, 0, NULL, "stmt_1");
#line 86 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 86 "declare.pgc"
/* exec sql whenever not found continue ; */
#line 87 "declare.pgc"
printResult("testcase1", 2);
/*
* testcase2. using DECLARE STATEMENT at con1,
* using PREPARE and CURSOR statement without using AT clause
*/
reset();
/* declare \"stmt_2\" as an SQL identifier */
#line 98 "declare.pgc"
{ ECPGprepare(__LINE__, "con1", 0, "stmt_2", selectString);
#line 99 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 99 "declare.pgc"
/* declare cur_2 cursor for $1 */
#line 100 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "declare cur_2 cursor for $1",
ECPGt_char_variable,(ECPGprepared_statement("con1", "stmt_2", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
#line 101 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 101 "declare.pgc"
/* exec sql whenever not found break ; */
#line 103 "declare.pgc"
i = 0;
while (1)
{
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "fetch cur_2", ECPGt_EOIT,
ECPGt_int,&(f1[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(f2[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(f3[i]),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 107 "declare.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
#line 107 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 107 "declare.pgc"
i++;
}
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "close cur_2", ECPGt_EOIT, ECPGt_EORT);
#line 110 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 110 "declare.pgc"
{ ECPGdeallocate(__LINE__, 0, NULL, "stmt_2");
#line 111 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 111 "declare.pgc"
/* exec sql whenever not found continue ; */
#line 112 "declare.pgc"
printResult("testcase2", 2);
/*
* testcase3. using DECLARE STATEMENT at con1,
* using PREPARE and CURSOR statement at con2
*/
reset();
/* declare \"stmt_3\" as an SQL identifier */
#line 122 "declare.pgc"
{ ECPGprepare(__LINE__, "con1", 0, "stmt_3", selectString);
#line 123 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 123 "declare.pgc"
/* declare cur_3 cursor for $1 */
#line 124 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "declare cur_3 cursor for $1",
ECPGt_char_variable,(ECPGprepared_statement("con1", "stmt_3", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
#line 125 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 125 "declare.pgc"
/* exec sql whenever not found break ; */
#line 127 "declare.pgc"
i = 0;
while (1)
{
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "fetch cur_3", ECPGt_EOIT,
ECPGt_int,&(f1[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(f2[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(f3[i]),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 131 "declare.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
#line 131 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 131 "declare.pgc"
i++;
}
{ ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "close cur_3", ECPGt_EOIT, ECPGt_EORT);
#line 134 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 134 "declare.pgc"
{ ECPGdeallocate(__LINE__, 0, "con2", "stmt_3");
#line 135 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 135 "declare.pgc"
/* exec sql whenever not found continue ; */
#line 136 "declare.pgc"
printResult("testcase3", 2);
/*
* testcase4. using DECLARE STATEMENT without using AT clause,
* using PREPARE and CURSOR statement at con2
*/
reset();
/* declare \"stmt_4\" as an SQL identifier */
#line 147 "declare.pgc"
{ ECPGprepare(__LINE__, "con2", 0, "stmt_4", selectString);
#line 148 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 148 "declare.pgc"
/* declare cur_4 cursor for $1 */
#line 149 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "declare cur_4 cursor for $1",
ECPGt_char_variable,(ECPGprepared_statement("con2", "stmt_4", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
#line 150 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 150 "declare.pgc"
/* exec sql whenever not found break ; */
#line 152 "declare.pgc"
i = 0;
while (1)
{
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "fetch cur_4", ECPGt_EOIT,
ECPGt_int,&(f1[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(f2[i]),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(f3[i]),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 156 "declare.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
#line 156 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 156 "declare.pgc"
i++;
}
{ ECPGdo(__LINE__, 0, 1, "con2", 0, ECPGst_normal, "close cur_4", ECPGt_EOIT, ECPGt_EORT);
#line 159 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 159 "declare.pgc"
{ ECPGdeallocate(__LINE__, 0, "con2", "stmt_4");
#line 160 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 160 "declare.pgc"
/* exec sql whenever not found continue ; */
#line 161 "declare.pgc"
printResult("testcase4", 2);
/*
* testcase5. using DECLARE STATEMENT without using AT clause,
* using PREPARE and EXECUTE statement without using AT clause
*/
reset();
/* declare \"stmt_5\" as an SQL identifier */
#line 171 "declare.pgc"
{ ECPGprepare(__LINE__, NULL, 0, "stmt_5", selectString);
#line 172 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 172 "declare.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, "stmt_5", ECPGt_EOIT,
ECPGt_int,(f1),(long)1,(long)ARRAY_SZIE,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,(f2),(long)1,(long)ARRAY_SZIE,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(f3),(long)20,(long)ARRAY_SZIE,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 173 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 173 "declare.pgc"
{ ECPGdeallocate(__LINE__, 0, NULL, "stmt_5");
#line 175 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 175 "declare.pgc"
printResult("testcase5", 2);
}
void commitTable()
{
{ ECPGtrans(__LINE__, "con1", "commit");
#line 182 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 182 "declare.pgc"
{ ECPGtrans(__LINE__, "con2", "commit");
#line 183 "declare.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 183 "declare.pgc"
}
/*
* reset all the output variables
*/
void reset()
{
memset(f1, 0, sizeof(f1));
memset(f2, 0, sizeof(f2));
memset(f3, 0, sizeof(f3));
}
void printResult(char *tc_name, int loop)
{
int i;
if (tc_name)
printf("****%s test results:****\n", tc_name);
for (i = 0; i < loop; i++)
printf("f1=%d, f2=%d, f3=%s\n", f1[i], f2[i], f3[i]);
printf("\n");
}

View File

@ -0,0 +1,286 @@
[NO_PID]: ECPGdebug: set to 1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGconnect: opening database ecpg2_regression on <DEFAULT> port <DEFAULT>
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 32: query: create table source ( f1 integer , f2 integer , f3 varchar ( 20 ) ); with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 32: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 32: OK: CREATE TABLE
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 33: query: create table source ( f1 integer , f2 integer , f3 varchar ( 20 ) ); with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 33: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 33: OK: CREATE TABLE
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 35: query: insert into source values ( 1 , 10 , 'db on con1' ); with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 35: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 35: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 36: query: insert into source values ( 2 , 20 , 'db on con1' ); with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 36: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 36: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 38: query: insert into source values ( 1 , 10 , 'db on con2' ); with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 38: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 38: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 39: query: insert into source values ( 2 , 20 , 'db on con2' ); with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 39: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 39: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans on line 182: action "commit"; connection "con1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans on line 183: action "commit"; connection "con2"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: prepare_common on line 74: name stmt_1; query: "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 76: query: declare cur_1 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 76: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 76: OK: DECLARE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: query: fetch cur_1; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 82: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: 1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: 10 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: query: fetch cur_1; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 82: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: 2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: 20 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 82: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: query: fetch cur_1; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 82: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 82: correctly got 0 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode 100 on line 82: no data found on line 82
[NO_PID]: sqlca: code: 100, state: 02000
[NO_PID]: ecpg_execute on line 85: query: close cur_1; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 85: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 85: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: deallocate_one on line 86: name stmt_1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: prepare_common on line 99: name stmt_2; query: "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 101: query: declare cur_2 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 101: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 101: OK: DECLARE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: query: fetch cur_2; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 107: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: 1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: 10 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: db on con1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: query: fetch cur_2; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 107: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: 2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: 20 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 107: RESULT: db on con1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: query: fetch cur_2; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 107: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 107: correctly got 0 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode 100 on line 107: no data found on line 107
[NO_PID]: sqlca: code: 100, state: 02000
[NO_PID]: ecpg_execute on line 110: query: close cur_2; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 110: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 110: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode -230 on line 111: invalid statement name "stmt_2" on line 111
[NO_PID]: sqlca: code: -230, state: 26000
SQL error: invalid statement name "stmt_2" on line 111
[NO_PID]: prepare_common on line 123: name stmt_3; query: "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 125: query: declare cur_3 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 125: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 125: OK: DECLARE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: query: fetch cur_3; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 131: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: 1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: 10 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: db on con1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: query: fetch cur_3; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 131: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: 2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: 20 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 131: RESULT: db on con1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: query: fetch cur_3; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 131: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 131: correctly got 0 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode 100 on line 131: no data found on line 131
[NO_PID]: sqlca: code: 100, state: 02000
[NO_PID]: ecpg_execute on line 134: query: close cur_3; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 134: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 134: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode -230 on line 135: invalid statement name "stmt_3" on line 135
[NO_PID]: sqlca: code: -230, state: 26000
SQL error: invalid statement name "stmt_3" on line 135
[NO_PID]: prepare_common on line 148: name stmt_4; query: "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 150: query: declare cur_4 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 150: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 150: OK: DECLARE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: query: fetch cur_4; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 156: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: 1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: 10 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: query: fetch cur_4; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 156: correctly got 1 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: 2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: 20 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 156: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: query: fetch cur_4; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 156: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 156: correctly got 0 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: raising sqlcode 100 on line 156: no data found on line 156
[NO_PID]: sqlca: code: 100, state: 02000
[NO_PID]: ecpg_execute on line 159: query: close cur_4; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 159: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 159: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: deallocate_one on line 160: name stmt_4
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: prepare_common on line 172: name stmt_5; query: "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 173: query: SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 173: using PQexecPrepared for "SELECT f1,f2,f3 FROM source"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 173: correctly got 2 tuples with 3 fields
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: 1 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: 2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: 10 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: 20 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 173: RESULT: db on con2 offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: deallocate_one on line 175: name stmt_5
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 45: query: drop table if exists source; with 0 parameter(s) on connection con1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 45: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 45: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 46: query: drop table if exists source; with 0 parameter(s) on connection con2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 46: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_process_output on line 46: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans on line 182: action "commit"; connection "con1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans on line 183: action "commit"; connection "con2"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: connection con2 closed
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: deallocate_one on line 0: name stmt_3
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: deallocate_one on line 0: name stmt_2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: connection con1 closed
[NO_PID]: sqlca: code: 0, state: 00000

View File

@ -0,0 +1,20 @@
****testcase1 test results:****
f1=1, f2=10, f3=db on con2
f1=2, f2=20, f3=db on con2
****testcase2 test results:****
f1=1, f2=10, f3=db on con1
f1=2, f2=20, f3=db on con1
****testcase3 test results:****
f1=1, f2=10, f3=db on con1
f1=2, f2=20, f3=db on con1
****testcase4 test results:****
f1=1, f2=10, f3=db on con2
f1=2, f2=20, f3=db on con2
****testcase5 test results:****
f1=1, f2=10, f3=db on con2
f1=2, f2=20, f3=db on con2

View File

@ -10,6 +10,8 @@
/copystdout.c
/createtableas
/createtableas.c
/declare
/declare.c
/define
/define.c
/desc

View File

@ -26,6 +26,7 @@ TESTS = array array.c \
insupd insupd.c \
twophase twophase.c \
insupd insupd.c \
declare declare.c \
bytea bytea.c \
prepareas prepareas.c

View File

@ -0,0 +1,207 @@
#include <locale.h>
#include <string.h>
#include <stdlib.h>
EXEC SQL WHENEVER SQLERROR SQLPRINT;
EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE ../regression;
#define ARRAY_SZIE 20
void execute_test(void);
void commitTable(void);
void reset(void);
void printResult(char *tc_name, int loop);
EXEC SQL BEGIN DECLARE SECTION;
int f1[ARRAY_SZIE];
int f2[ARRAY_SZIE];
char f3[ARRAY_SZIE][20];
EXEC SQL END DECLARE SECTION;
int main(void)
{
setlocale(LC_ALL, "C");
ECPGdebug(1, stderr);
EXEC SQL CONNECT TO REGRESSDB1 AS con1;
EXEC SQL CONNECT TO REGRESSDB2 AS con2;
EXEC SQL AT con1 CREATE TABLE source(f1 integer, f2 integer, f3 varchar(20));
EXEC SQL AT con2 CREATE TABLE source(f1 integer, f2 integer, f3 varchar(20));
EXEC SQL AT con1 INSERT INTO source VALUES(1, 10, 'db on con1');
EXEC SQL AT con1 INSERT INTO source VALUES(2, 20, 'db on con1');
EXEC SQL AT con2 INSERT INTO source VALUES(1, 10, 'db on con2');
EXEC SQL AT con2 INSERT INTO source VALUES(2, 20, 'db on con2');
commitTable();
execute_test();
EXEC SQL AT con1 DROP TABLE IF EXISTS source;
EXEC SQL AT con2 DROP TABLE IF EXISTS source;
commitTable();
EXEC SQL DISCONNECT ALL;
return 0;
}
/*
* default connection: con2
* Non-default connection: con1
*
*/
void execute_test(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int i;
char *selectString = "SELECT f1,f2,f3 FROM source";
EXEC SQL END DECLARE SECTION;
/*
* testcase1. using DECLARE STATEMENT without using AT clause,
* using PREPARE and CURSOR statement without using AT clause
*/
reset();
EXEC SQL DECLARE stmt_1 STATEMENT;
EXEC SQL PREPARE stmt_1 FROM :selectString;
EXEC SQL DECLARE cur_1 CURSOR FOR stmt_1;
EXEC SQL OPEN cur_1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
i = 0;
while (1)
{
EXEC SQL FETCH cur_1 INTO :f1[i], :f2[i], :f3[i];
i++;
}
EXEC SQL CLOSE cur_1;
EXEC SQL DEALLOCATE PREPARE stmt_1;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
printResult("testcase1", 2);
/*
* testcase2. using DECLARE STATEMENT at con1,
* using PREPARE and CURSOR statement without using AT clause
*/
reset();
EXEC SQL AT con1 DECLARE stmt_2 STATEMENT;
EXEC SQL PREPARE stmt_2 FROM :selectString;
EXEC SQL DECLARE cur_2 CURSOR FOR stmt_2;
EXEC SQL OPEN cur_2;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
i = 0;
while (1)
{
EXEC SQL FETCH cur_2 INTO :f1[i], :f2[i], :f3[i];
i++;
}
EXEC SQL CLOSE cur_2;
EXEC SQL DEALLOCATE PREPARE stmt_2;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
printResult("testcase2", 2);
/*
* testcase3. using DECLARE STATEMENT at con1,
* using PREPARE and CURSOR statement at con2
*/
reset();
EXEC SQL AT con1 DECLARE stmt_3 STATEMENT;
EXEC SQL AT con2 PREPARE stmt_3 FROM :selectString;
EXEC SQL AT con2 DECLARE cur_3 CURSOR FOR stmt_3;
EXEC SQL AT con2 OPEN cur_3;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
i = 0;
while (1)
{
EXEC SQL AT con2 FETCH cur_3 INTO :f1[i], :f2[i], :f3[i];
i++;
}
EXEC SQL AT con2 CLOSE cur_3;
EXEC SQL AT con2 DEALLOCATE PREPARE stmt_3;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
printResult("testcase3", 2);
/*
* testcase4. using DECLARE STATEMENT without using AT clause,
* using PREPARE and CURSOR statement at con2
*/
reset();
EXEC SQL DECLARE stmt_4 STATEMENT;
EXEC SQL AT con2 PREPARE stmt_4 FROM :selectString;
EXEC SQL AT con2 DECLARE cur_4 CURSOR FOR stmt_4;
EXEC SQL AT con2 OPEN cur_4;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
i = 0;
while (1)
{
EXEC SQL AT con2 FETCH cur_4 INTO :f1[i], :f2[i], :f3[i];
i++;
}
EXEC SQL AT con2 CLOSE cur_4;
EXEC SQL AT con2 DEALLOCATE PREPARE stmt_4;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
printResult("testcase4", 2);
/*
* testcase5. using DECLARE STATEMENT without using AT clause,
* using PREPARE and EXECUTE statement without using AT clause
*/
reset();
EXEC SQL DECLARE stmt_5 STATEMENT;
EXEC SQL PREPARE stmt_5 FROM :selectString;
EXEC SQL EXECUTE stmt_5 INTO :f1, :f2, :f3;
EXEC SQL DEALLOCATE PREPARE stmt_5;
printResult("testcase5", 2);
}
void commitTable()
{
EXEC SQL AT con1 COMMIT;
EXEC SQL AT con2 COMMIT;
}
/*
* reset all the output variables
*/
void reset()
{
memset(f1, 0, sizeof(f1));
memset(f2, 0, sizeof(f2));
memset(f3, 0, sizeof(f3));
}
void printResult(char *tc_name, int loop)
{
int i;
if (tc_name)
printf("****%s test results:****\n", tc_name);
for (i = 0; i < loop; i++)
printf("f1=%d, f2=%d, f3=%s\n", f1[i], f2[i], f3[i]);
printf("\n");
}