Commit 6d4a351f authored by Michael Meskes's avatar Michael Meskes

Applied patch by Boszormenyi Zoltan <zb@cybertec.at> to add sqlda support to

ecpg in both native and compatiblity mode.
parent af322a8a
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group # Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California # Portions Copyright (c) 1994, Regents of the University of California
# #
# $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.65 2010/01/02 16:58:11 momjian Exp $ # $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.66 2010/01/05 16:38:23 meskes Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -24,7 +24,7 @@ override CFLAGS += $(PTHREAD_CFLAGS) ...@@ -24,7 +24,7 @@ override CFLAGS += $(PTHREAD_CFLAGS)
# Need to recompile any libpgport object files # Need to recompile any libpgport object files
LIBS := $(filter-out -lpgport, $(LIBS)) LIBS := $(filter-out -lpgport, $(LIBS))
OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \ OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
connect.o misc.o path.o pgstrcasecmp.o \ connect.o misc.o path.o pgstrcasecmp.o \
$(filter snprintf.o strlcpy.o, $(LIBOBJS)) $(filter snprintf.o strlcpy.o, $(LIBOBJS))
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.87 2009/09/03 10:24:48 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.88 2010/01/05 16:38:23 meskes Exp $ */
/* /*
* The aim is to get a simpler inteface to the database routines. * The aim is to get a simpler inteface to the database routines.
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "ecpgerrno.h" #include "ecpgerrno.h"
#include "extern.h" #include "extern.h"
#include "sqlca.h" #include "sqlca.h"
#include "sqlda-native.h"
#include "sqlda-compat.h"
#include "sql3types.h" #include "sql3types.h"
#include "pgtypes_numeric.h" #include "pgtypes_numeric.h"
#include "pgtypes_date.h" #include "pgtypes_date.h"
...@@ -1033,6 +1035,7 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari ...@@ -1033,6 +1035,7 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
break; break;
case ECPGt_descriptor: case ECPGt_descriptor:
case ECPGt_sqlda:
break; break;
default: default:
...@@ -1172,6 +1175,120 @@ ecpg_execute(struct statement * stmt) ...@@ -1172,6 +1175,120 @@ ecpg_execute(struct statement * stmt)
if (desc->count == desc_counter) if (desc->count == desc_counter)
desc_counter = 0; desc_counter = 0;
} }
else if (var->type == ECPGt_sqlda)
{
if (INFORMIX_MODE(stmt->compat))
{
struct sqlda_compat *sqlda = *(struct sqlda_compat **)var->pointer;
struct variable desc_inlist;
int i;
if (sqlda == NULL)
return false;
desc_counter++;
for (i = 0; i < sqlda->sqld; i++)
{
if (i + 1 == desc_counter)
{
desc_inlist.type = sqlda->sqlvar[i].sqltype;
desc_inlist.value = sqlda->sqlvar[i].sqldata;
desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
switch (desc_inlist.type)
{
case ECPGt_char:
case ECPGt_varchar:
desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
break;
default:
desc_inlist.varcharsize = 0;
break;
}
desc_inlist.arrsize = 1;
desc_inlist.offset = 0;
if (sqlda->sqlvar[i].sqlind)
{
desc_inlist.ind_type = ECPGt_short;
/* ECPG expects indicator value < 0 */
if (*(sqlda->sqlvar[i].sqlind))
*(sqlda->sqlvar[i].sqlind) = -1;
desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
desc_inlist.ind_offset = 0;
}
else
{
desc_inlist.ind_type = ECPGt_NO_INDICATOR;
desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
}
if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
return false;
break;
}
}
if (sqlda->sqld == desc_counter)
desc_counter = 0;
}
else
{
struct sqlda_struct *sqlda = *(struct sqlda_struct **)var->pointer;
struct variable desc_inlist;
int i;
if (sqlda == NULL)
return false;
desc_counter++;
for (i = 0; i < sqlda->sqln; i++)
{
if (i + 1 == desc_counter)
{
desc_inlist.type = sqlda->sqlvar[i].sqltype;
desc_inlist.value = sqlda->sqlvar[i].sqldata;
desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
switch (desc_inlist.type)
{
case ECPGt_char:
case ECPGt_varchar:
desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
break;
default:
desc_inlist.varcharsize = 0;
break;
}
desc_inlist.arrsize = 1;
desc_inlist.offset = 0;
if (sqlda->sqlvar[i].sqlind)
{
desc_inlist.ind_type = ECPGt_short;
/* ECPG expects indicator value < 0 */
if (*(sqlda->sqlvar[i].sqlind))
*(sqlda->sqlvar[i].sqlind) = -1;
desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
desc_inlist.ind_offset = 0;
}
else
{
desc_inlist.ind_type = ECPGt_NO_INDICATOR;
desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
}
if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
return false;
break;
}
}
if (sqlda->sqln == desc_counter)
desc_counter = 0;
}
}
else else
{ {
if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false)) if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
...@@ -1353,6 +1470,111 @@ ecpg_execute(struct statement * stmt) ...@@ -1353,6 +1470,111 @@ ecpg_execute(struct statement * stmt)
} }
var = var->next; var = var->next;
} }
else if (var != NULL && var->type == ECPGt_sqlda)
{
if (INFORMIX_MODE(stmt->compat))
{
struct sqlda_compat **_sqlda = (struct sqlda_compat **)var->pointer;
struct sqlda_compat *sqlda = *_sqlda;
struct sqlda_compat *sqlda_new;
int i;
/* If we are passed in a previously existing sqlda (chain) then free it. */
while (sqlda)
{
sqlda_new = sqlda->desc_next;
free(sqlda);
sqlda = sqlda_new;
}
*_sqlda = sqlda = sqlda_new = NULL;
for (i = ntuples - 1; i >= 0; i--)
{
/* Build a new sqlda structure. Note that only fetching 1 record is supported */
sqlda_new = ecpg_build_compat_sqlda(stmt->lineno, results, i, stmt->compat);
if (!sqlda_new)
{
/* cleanup all SQLDAs we created up */
while (sqlda)
{
sqlda_new = sqlda->desc_next;
free(sqlda);
sqlda = sqlda_new;
}
*_sqlda = NULL;
ecpg_log("ecpg_execute on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
status = false;
break;
}
else
{
ecpg_log("ecpg_execute on line %d: new sqlda was built\n", stmt->lineno);
*_sqlda = sqlda_new;
ecpg_set_compat_sqlda(stmt->lineno, _sqlda, results, i, stmt->compat);
ecpg_log("ecpg_execute on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
stmt->lineno, PQnfields(results));
sqlda_new->desc_next = sqlda;
sqlda = sqlda_new;
}
}
}
else
{
struct sqlda_struct **_sqlda = (struct sqlda_struct **)var->pointer;
struct sqlda_struct *sqlda = *_sqlda;
struct sqlda_struct *sqlda_new;
int i;
/* If we are passed in a previously existing sqlda (chain) then free it. */
while (sqlda)
{
sqlda_new = sqlda->desc_next;
free(sqlda);
sqlda = sqlda_new;
}
*_sqlda = sqlda = sqlda_new = NULL;
for (i = ntuples - 1; i >= 0; i--)
{
/* Build a new sqlda structure. Note that only fetching 1 record is supported */
sqlda_new = ecpg_build_native_sqlda(stmt->lineno, results, i, stmt->compat);
if (!sqlda_new)
{
/* cleanup all SQLDAs we created up */
while (sqlda)
{
sqlda_new = sqlda->desc_next;
free(sqlda);
sqlda = sqlda_new;
}
*_sqlda = NULL;
ecpg_log("ecpg_execute on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
status = false;
break;
}
else
{
ecpg_log("ecpg_execute on line %d: new sqlda was built\n", stmt->lineno);
*_sqlda = sqlda_new;
ecpg_set_native_sqlda(stmt->lineno, _sqlda, results, i, stmt->compat);
ecpg_log("ecpg_execute on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
stmt->lineno, PQnfields(results));
sqlda_new->desc_next = sqlda;
sqlda = sqlda_new;
}
}
}
var = var->next;
}
else else
for (act_field = 0; act_field < nfields && status; act_field++) for (act_field = 0; act_field < nfields && status; act_field++)
{ {
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.35 2009/05/20 16:13:18 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.36 2010/01/05 16:38:23 meskes Exp $ */
#ifndef _ECPG_LIB_EXTERN_H #ifndef _ECPG_LIB_EXTERN_H
#define _ECPG_LIB_EXTERN_H #define _ECPG_LIB_EXTERN_H
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "postgres_fe.h" #include "postgres_fe.h"
#include "libpq-fe.h" #include "libpq-fe.h"
#include "sqlca.h" #include "sqlca.h"
#include "sqlda-native.h"
#include "sqlda-compat.h"
#include "ecpg_config.h" #include "ecpg_config.h"
#ifndef CHAR_BIT #ifndef CHAR_BIT
#include <limits.h> #include <limits.h>
...@@ -129,6 +131,7 @@ bool ecpg_init(const struct connection *, const char *, const int); ...@@ -129,6 +131,7 @@ bool ecpg_init(const struct connection *, const char *, const int);
char *ecpg_strdup(const char *, int); char *ecpg_strdup(const char *, int);
const char *ecpg_type_name(enum ECPGttype); const char *ecpg_type_name(enum ECPGttype);
int ecpg_dynamic_type(Oid); int ecpg_dynamic_type(Oid);
int sqlda_dynamic_type(Oid, enum COMPAT_MODE);
void ecpg_free_auto_mem(void); void ecpg_free_auto_mem(void);
void ecpg_clear_auto_mem(void); void ecpg_clear_auto_mem(void);
...@@ -149,6 +152,11 @@ void ecpg_log(const char *format,...); ...@@ -149,6 +152,11 @@ void ecpg_log(const char *format,...);
bool ecpg_auto_prepare(int, const char *, const int, char **, const char *); bool ecpg_auto_prepare(int, const char *, const int, char **, const char *);
void ecpg_init_sqlca(struct sqlca_t * sqlca); void ecpg_init_sqlca(struct sqlca_t * sqlca);
struct sqlda_compat *ecpg_build_compat_sqlda(int, PGresult *, int, enum COMPAT_MODE);
void ecpg_set_compat_sqlda(int, struct sqlda_compat **, const PGresult *, int, enum COMPAT_MODE);
struct sqlda_struct *ecpg_build_native_sqlda(int, PGresult *, int, enum COMPAT_MODE);
void ecpg_set_native_sqlda(int, struct sqlda_struct **, const PGresult *, int, enum COMPAT_MODE);
/* SQLSTATE values generated or processed by ecpglib (intentionally /* SQLSTATE values generated or processed by ecpglib (intentionally
* not exported -- users should refer to the codes directly) */ * not exported -- users should refer to the codes directly) */
......
This diff is collapsed.
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.15 2009/08/07 10:51:20 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.16 2010/01/05 16:38:23 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL #define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ecpgtype.h" #include "ecpgtype.h"
#include "ecpglib.h" #include "ecpglib.h"
#include "extern.h" #include "extern.h"
#include "sqltypes.h"
#include "sql3types.h" #include "sql3types.h"
#include "pg_type.h" #include "pg_type.h"
...@@ -100,3 +101,42 @@ ecpg_dynamic_type(Oid type) ...@@ -100,3 +101,42 @@ ecpg_dynamic_type(Oid type)
return -(int) type; return -(int) type;
} }
} }
int
sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
{
switch (type)
{
case CHAROID:
case VARCHAROID:
case BPCHAROID:
case TEXTOID:
return ECPGt_char;
case INT2OID:
return ECPGt_short;
case INT4OID:
return ECPGt_int;
case FLOAT8OID:
return ECPGt_double;
case FLOAT4OID:
return ECPGt_float;
case NUMERICOID:
return INFORMIX_MODE(compat) ? ECPGt_decimal : ECPGt_numeric;
case DATEOID:
return ECPGt_date;
case TIMESTAMPOID:
case TIMESTAMPTZOID:
return ECPGt_timestamp;
case INTERVALOID:
return ECPGt_interval;
case INT8OID:
#ifdef HAVE_LONG_LONG_INT_64
return ECPGt_long_long;
#endif
#ifdef HAVE_LONG_INT_64
return ECPGt_long;
#endif
default:
return (-type);
}
}
...@@ -14,8 +14,9 @@ install: all installdirs install-headers ...@@ -14,8 +14,9 @@ install: all installdirs install-headers
.PHONY: install-headers .PHONY: install-headers
ecpg_headers = ecpgerrno.h ecpglib.h ecpgtype.h sqlca.h sql3types.h ecpg_informix.h \ ecpg_headers = ecpgerrno.h ecpglib.h ecpgtype.h sqlca.h sql3types.h ecpg_informix.h \
pgtypes_error.h pgtypes_numeric.h pgtypes_timestamp.h pgtypes_date.h pgtypes_interval.h pgtypes_error.h pgtypes_numeric.h pgtypes_timestamp.h pgtypes_date.h pgtypes_interval.h \
informix_headers = datetime.h decimal.h sqltypes.h sqlda.h sqlda.h sqlda-compat.h sqlda-native.h
informix_headers = datetime.h decimal.h sqltypes.h
install-headers: $(ecpg_headers) $(informix_headers) install-headers: $(ecpg_headers) $(informix_headers)
$(INSTALL_DATA) $(addprefix $(srcdir)/,$(ecpg_headers)) '$(DESTDIR)$(includedir)/' $(INSTALL_DATA) $(addprefix $(srcdir)/,$(ecpg_headers)) '$(DESTDIR)$(includedir)/'
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* All types that can be handled for host variable declarations has to * All types that can be handled for host variable declarations has to
* be handled eventually. * be handled eventually.
* *
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpgtype.h,v 1.38 2009/08/07 10:51:20 meskes Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpgtype.h,v 1.39 2010/01/05 16:38:23 meskes Exp $
*/ */
/* /*
...@@ -62,7 +62,8 @@ enum ECPGttype ...@@ -62,7 +62,8 @@ enum ECPGttype
ECPGt_EOIT, /* End of insert types. */ ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */ ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR, /* no indicator */ ECPGt_NO_INDICATOR, /* no indicator */
ECPGt_string /* trimmed (char *) type */ ECPGt_string, /* trimmed (char *) type */
ECPGt_sqlda /* C struct descriptor */
}; };
/* descriptor items */ /* descriptor items */
......
/*
* pgsql/src/interfaces/ecpg/include/sqlda-infx-compat.h
*/
#ifndef ECPG_SQLDA_COMPAT_H
#define ECPG_SQLDA_COMPAT_H
struct sqlvar_compat
{
short sqltype; /* variable type */
int sqllen; /* length in bytes */
char *sqldata; /* pointer to data */
short *sqlind; /* pointer to indicator */
char *sqlname; /* variable name */
char *sqlformat; /* reserved for future use */
short sqlitype; /* ind variable type */
short sqlilen; /* ind length in bytes */
char *sqlidata; /* ind data pointer */
int sqlxid; /* extended id type */
char *sqltypename; /* extended type name */
short sqltypelen; /* length of extended type name */
short sqlownerlen; /* length of owner name */
short sqlsourcetype; /* source type for distinct of built-ins */
char *sqlownername; /* owner name */
int sqlsourceid; /* extended id of source type */
/*
* sqlilongdata is new. It supports data that exceeds the 32k
* limit. sqlilen and sqlidata are for backward compatibility
* and they have maximum value of <32K.
*/
char *sqlilongdata; /* for data field beyond 32K */
int sqlflags; /* for internal use only */
void *sqlreserved; /* reserved for future use */
};
struct sqlda_compat
{
short sqld;
struct sqlvar_compat *sqlvar;
char desc_name[19]; /* descriptor name */
short desc_occ; /* size of sqlda structure */
struct sqlda_compat *desc_next; /* pointer to next sqlda struct */
void *reserved; /* reserved for future use */
};
#endif /* ECPG_SQLDA_COMPAT_H */
/*
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda-native.h,v 1.1 2010/01/05 16:38:23 meskes Exp $
*/
#ifndef ECPG_SQLDA_NATIVE_H
#define ECPG_SQLDA_NATIVE_H
#include "postgres_fe.h"
struct sqlname
{
short length;
char data[NAMEDATALEN];
};
struct sqlvar_struct
{
short sqltype;
short sqllen;
char *sqldata;
short *sqlind;
struct sqlname sqlname;
};
struct sqlda_struct
{
char sqldaid[8];
long sqldabc;
short sqln;
short sqld;
struct sqlda_struct *desc_next;
struct sqlvar_struct sqlvar[1];
};
#endif /* ECPG_SQLDA_NATIVE_H */
/* /*
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda.h,v 1.4 2009/06/11 14:49:13 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda.h,v 1.5 2010/01/05 16:38:23 meskes Exp $
*/ */
#ifndef ECPG_SQLDA_H
#define ECPG_SQLDA_H
#ifdef _ECPG_INFORMIX_H
#include "sqlda-compat.h"
typedef struct sqlvar_compat sqlvar_t;
typedef struct sqlda_compat sqlda_t;
#else
#include "sqlda-native.h"
typedef struct sqlvar_struct sqlvar_t;
typedef struct sqlda_struct sqlda_t;
#endif
#endif /* ECPG_SQLDA_H */
/* /*
* $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqltypes.h,v 1.9 2009/06/11 14:49:13 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqltypes.h,v 1.10 2010/01/05 16:38:23 meskes Exp $
*/ */
#ifndef ECPG_SQLTYPES_H #ifndef ECPG_SQLTYPES_H
#define ECPG_SQLTYPES_H #define ECPG_SQLTYPES_H
#include <limits.h>
#define CCHARTYPE ECPGt_char #define CCHARTYPE ECPGt_char
#define CSHORTTYPE ECPGt_short #define CSHORTTYPE ECPGt_short
#define CINTTYPE ECPGt_int #define CINTTYPE ECPGt_int
...@@ -30,4 +32,29 @@ ...@@ -30,4 +32,29 @@
#define CLVCHARPTRTYPE 124 #define CLVCHARPTRTYPE 124
#define CTYPEMAX 25 #define CTYPEMAX 25
/*
* Values used in sqlda->sqlvar[i]->sqltype
*/
#define SQLCHAR ECPGt_char
#define SQLSMINT ECPGt_short
#define SQLINT ECPGt_int
#define SQLFLOAT ECPGt_double
#define SQLSMFLOAT ECPGt_float
#define SQLDECIMAL ECPGt_decimal
#define SQLSERIAL ECPGt_int
#define SQLDATE ECPGt_date
#define SQLDTIME ECPGt_timestamp
#define SQLTEXT ECPGt_char
#define SQLVCHAR ECPGt_char
#define SQLINTERVAL ECPGt_interval
#define SQLNCHAR ECPGt_char
#define SQLNVCHAR ECPGt_char
#ifdef HAVE_LONG_LONG_INT_64
#define SQLINT8 ECPGt_long_long
#define SQLSERIAL8 ECPGt_long_long
#else
#define SQLINT8 ECPGt_long
#define SQLSERIAL8 ECPGt_long
#endif
#endif /* ndef ECPG_SQLTYPES_H */ #endif /* ndef ECPG_SQLTYPES_H */
/* /*
* functions needed for descriptor handling * functions needed for descriptor handling
* *
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/descriptor.c,v 1.28 2009/01/23 12:43:32 petere Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/descriptor.c,v 1.29 2010/01/05 16:38:23 meskes Exp $
* *
* since descriptor might be either a string constant or a string var * since descriptor might be either a string constant or a string var
* we need to check for a constant if we expect a constant * we need to check for a constant if we expect a constant
...@@ -326,3 +326,22 @@ descriptor_variable(const char *name, int input) ...@@ -326,3 +326,22 @@ descriptor_variable(const char *name, int input)
strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input])); strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
return (struct variable *) & varspace[input]; return (struct variable *) & varspace[input];
} }
struct variable *
sqlda_variable(const char *name)
{
struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
p->name = mm_strdup(name);
p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
p->type->type = ECPGt_sqlda;
p->type->size = NULL;
p->type->struct_sizeof = NULL;
p->type->u.element = NULL;
p->type->lineno = 0;
p->brace_level = 0;
p->next = NULL;
return p;
}
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.12 2009/12/16 10:15:06 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.13 2010/01/05 16:38:23 meskes Exp $ */
ECPG: stmtClosePortalStmt block ECPG: stmtClosePortalStmt block
{ {
if (INFORMIX_MODE) if (INFORMIX_MODE)
...@@ -409,29 +409,29 @@ ECPG: VariableShowStmtSHOWALL block ...@@ -409,29 +409,29 @@ ECPG: VariableShowStmtSHOWALL block
$$ = EMPTY; $$ = EMPTY;
} }
ECPG: FetchStmtMOVEfetch_args rule ECPG: FetchStmtMOVEfetch_args rule
| FETCH fetch_args ecpg_into | FETCH fetch_args ecpg_fetch_into
{ {
$$ = cat2_str(make_str("fetch"), $2); $$ = cat2_str(make_str("fetch"), $2);
} }
| FETCH FORWARD cursor_name opt_ecpg_into | FETCH FORWARD cursor_name opt_ecpg_fetch_into
{ {
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3; char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false); add_additional_variables($3, false);
$$ = cat_str(2, make_str("fetch forward"), cursor_marker); $$ = cat_str(2, make_str("fetch forward"), cursor_marker);
} }
| FETCH FORWARD from_in cursor_name opt_ecpg_into | FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into
{ {
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4; char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false); add_additional_variables($4, false);
$$ = cat_str(2, make_str("fetch forward from"), cursor_marker); $$ = cat_str(2, make_str("fetch forward from"), cursor_marker);
} }
| FETCH BACKWARD cursor_name opt_ecpg_into | FETCH BACKWARD cursor_name opt_ecpg_fetch_into
{ {
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3; char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false); add_additional_variables($3, false);
$$ = cat_str(2, make_str("fetch backward"), cursor_marker); $$ = cat_str(2, make_str("fetch backward"), cursor_marker);
} }
| FETCH BACKWARD from_in cursor_name opt_ecpg_into | FETCH BACKWARD from_in cursor_name opt_ecpg_fetch_into
{ {
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4; char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false); add_additional_variables($4, false);
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.16 2009/11/26 15:06:47 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.17 2010/01/05 16:38:23 meskes Exp $ */
statements: /*EMPTY*/ statements: /*EMPTY*/
| statements statement | statements statement
...@@ -970,22 +970,30 @@ ecpg_using: USING using_list { $$ = EMPTY; } ...@@ -970,22 +970,30 @@ ecpg_using: USING using_list { $$ = EMPTY; }
| using_descriptor { $$ = $1; } | using_descriptor { $$ = $1; }
; ;
using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar using_descriptor: USING SQL_SQL SQL_DESCRIPTOR quoted_ident_stringvar
{ {
add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator); add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
$$ = EMPTY; $$ = EMPTY;
} }
| USING SQL_DESCRIPTOR name
{
add_variable_to_head(&argsinsert, sqlda_variable($3), &no_indicator);
$$ = EMPTY;
}
; ;
into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar into_descriptor: INTO SQL_SQL SQL_DESCRIPTOR quoted_ident_stringvar
{ {
add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator); add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
$$ = EMPTY; $$ = EMPTY;
} }
| INTO SQL_DESCRIPTOR name
{
add_variable_to_head(&argsresult, sqlda_variable($3), &no_indicator);
$$ = EMPTY;
}
; ;
opt_sql: /*EMPTY*/ | SQL_SQL;
using_list: UsingValue | UsingValue ',' using_list; using_list: UsingValue | UsingValue ',' using_list;
UsingValue: UsingConst UsingValue: UsingConst
...@@ -1806,8 +1814,20 @@ ecpg_into: INTO into_list { $$ = EMPTY; } ...@@ -1806,8 +1814,20 @@ ecpg_into: INTO into_list { $$ = EMPTY; }
| into_descriptor { $$ = $1; } | into_descriptor { $$ = $1; }
; ;
opt_ecpg_into: /* EMPTY */ { $$ = EMPTY; } ecpg_fetch_into: ecpg_into { $$ = $1; }
| ecpg_into { $$ = $1; } | using_descriptor
{
struct variable *var;
var = argsinsert->variable;
remove_variable_from_list(&argsinsert, var);
add_variable_to_head(&argsresult, var, &no_indicator);
$$ = $1;
}
;
opt_ecpg_fetch_into: /* EMPTY */ { $$ = EMPTY; }
| ecpg_fetch_into { $$ = $1; }
; ;
%% %%
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.4 2009/11/26 15:06:47 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.5 2010/01/05 16:38:23 meskes Exp $ */
%type <str> ECPGAllocateDescr %type <str> ECPGAllocateDescr
%type <str> ECPGCKeywords %type <str> ECPGCKeywords
%type <str> ECPGColId %type <str> ECPGColId
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
%type <str> ecpg_ident %type <str> ecpg_ident
%type <str> ecpg_interval %type <str> ecpg_interval
%type <str> ecpg_into %type <str> ecpg_into
%type <str> ecpg_fetch_into
%type <str> ecpg_param %type <str> ecpg_param
%type <str> ecpg_sconst %type <str> ecpg_sconst
%type <str> ecpg_using %type <str> ecpg_using
...@@ -76,7 +77,7 @@ ...@@ -76,7 +77,7 @@
%type <str> opt_bit_field %type <str> opt_bit_field
%type <str> opt_connection_name %type <str> opt_connection_name
%type <str> opt_database_name %type <str> opt_database_name
%type <str> opt_ecpg_into %type <str> opt_ecpg_fetch_into
%type <str> opt_ecpg_using %type <str> opt_ecpg_using
%type <str> opt_initializer %type <str> opt_initializer
%type <str> opt_options %type <str> opt_options
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.76 2009/11/26 15:06:47 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.77 2010/01/05 16:38:23 meskes Exp $ */
#ifndef _ECPG_PREPROC_EXTERN_H #ifndef _ECPG_PREPROC_EXTERN_H
#define _ECPG_PREPROC_EXTERN_H #define _ECPG_PREPROC_EXTERN_H
...@@ -88,6 +88,7 @@ extern void add_descriptor(char *, char *); ...@@ -88,6 +88,7 @@ extern void add_descriptor(char *, char *);
extern void drop_descriptor(char *, char *); extern void drop_descriptor(char *, char *);
extern struct descriptor *lookup_descriptor(char *, char *); extern struct descriptor *lookup_descriptor(char *, char *);
extern struct variable *descriptor_variable(const char *name, int input); extern struct variable *descriptor_variable(const char *name, int input);
extern struct variable *sqlda_variable(const char *name);
extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *); extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *); extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments ** list, struct variable * var); extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.85 2009/09/03 09:59:20 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.86 2010/01/05 16:38:23 meskes Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -194,6 +194,9 @@ get_type(enum ECPGttype type) ...@@ -194,6 +194,9 @@ get_type(enum ECPGttype type)
case ECPGt_descriptor: case ECPGt_descriptor:
return ("ECPGt_descriptor"); return ("ECPGt_descriptor");
break; break;
case ECPGt_sqlda:
return ("ECPGt_sqlda");
break;
case ECPGt_date: case ECPGt_date:
return ("ECPGt_date"); return ("ECPGt_date");
break; break;
...@@ -328,6 +331,8 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type, ...@@ -328,6 +331,8 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
else if (type == ECPGt_descriptor) else if (type == ECPGt_descriptor)
/* remember that name here already contains quotes (if needed) */ /* remember that name here already contains quotes (if needed) */
fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name); fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name);
else if (type == ECPGt_sqlda)
fprintf(o, "\n\tECPGt_sqlda, &%s, 0L, 0L, 0L, ", name);
else else
{ {
char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4); char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
......
...@@ -16,6 +16,7 @@ TESTS = test_informix test_informix.c \ ...@@ -16,6 +16,7 @@ TESTS = test_informix test_informix.c \
rfmtdate rfmtdate.c \ rfmtdate rfmtdate.c \
rfmtlong rfmtlong.c \ rfmtlong rfmtlong.c \
rnull rnull.c \ rnull rnull.c \
sqlda sqlda.c \
charfuncs charfuncs.c charfuncs charfuncs.c
all: $(TESTS) all: $(TESTS)
...@@ -26,6 +27,9 @@ test_informix.c: test_informix.pgc ../regression.h ...@@ -26,6 +27,9 @@ test_informix.c: test_informix.pgc ../regression.h
test_informix2.c: test_informix2.pgc ../regression.h test_informix2.c: test_informix2.pgc ../regression.h
$(ECPG) -o $@ -I$(srcdir) $< $(ECPG) -o $@ -I$(srcdir) $<
sqlda.c: sqlda.pgc ../regression.h
$(ECPG) -o $@ -I$(srcdir) $<
dec_test.c: dec_test.pgc ../regression.h dec_test.c: dec_test.pgc ../regression.h
$(ECPG) -o $@ -I$(srcdir) $< $(ECPG) -o $@ -I$(srcdir) $<
......
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
exec sql include ../regression;
exec sql include sqlda.h;
exec sql include sqltypes.h;
exec sql whenever sqlerror stop;
/* These shouldn't be under DECLARE SECTION */
sqlda_t *inp_sqlda, *outp_sqlda;
static void
dump_sqlda(sqlda_t *sqlda)
{
int i;
if (sqlda == NULL)
{
printf("dump_sqlda called with NULL sqlda\n");
return;
}
for (i = 0; i < sqlda->sqld; i++)
{
if (sqlda->sqlvar[i].sqlind && *(sqlda->sqlvar[i].sqlind) == -1)
printf("name sqlda descriptor: '%s' value NULL'\n", sqlda->sqlvar[i].sqlname);
else
switch (sqlda->sqlvar[i].sqltype)
{
case SQLCHAR:
printf("name sqlda descriptor: '%s' value '%s'\n", sqlda->sqlvar[i].sqlname, sqlda->sqlvar[i].sqldata);
break;
case SQLINT:
printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqlname, *(int *)sqlda->sqlvar[i].sqldata);
break;
case SQLINT8:
printf("name sqlda descriptor: '%s' value %" PRId64 "\n", sqlda->sqlvar[i].sqlname, *(int64_t *)sqlda->sqlvar[i].sqldata);
break;
case SQLFLOAT:
printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sqlname, *(double *)sqlda->sqlvar[i].sqldata);
break;
case SQLDECIMAL:
{
char val[64];
dectoasc((dec_t *)sqlda->sqlvar[i].sqldata, val, 64, -1);
printf("name sqlda descriptor: '%s' value DECIMAL '%s'\n", sqlda->sqlvar[i].sqlname, val);
break;
}
}
}
}
int
main (void)
{
exec sql begin declare section;
char *stmt1 = "SELECT * FROM t1";
char *stmt2 = "SELECT * FROM t1 WHERE id = ?";
int rec;
int id;
exec sql end declare section;
char msg[128];
ECPGdebug(1, stderr);
strcpy(msg, "connect");
exec sql connect to REGRESSDB1 as regress1;
strcpy(msg, "set");
exec sql set datestyle to iso;
strcpy(msg, "create");
exec sql create table t1(
id integer,
t text,
d1 numeric,
d2 float8,
c char(10));
strcpy(msg, "insert");
exec sql insert into t1 values
(1, 'a', 1.0, 1, 'a'),
(2, null, null, null, null),
(3, '"c"', -3, 'nan'::float8, 'c'),
(4, 'd', 4.0, 4, 'd');
strcpy(msg, "commit");
exec sql commit;
/* SQLDA test for getting all records from a table */
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id1 from :stmt1;
strcpy(msg, "declare");
exec sql declare mycur1 cursor for st_id1;
strcpy(msg, "open");
exec sql open mycur1;
exec sql whenever not found do break;
rec = 0;
while (1)
{
strcpy(msg, "fetch");
exec sql fetch 1 from mycur1 into descriptor outp_sqlda;
printf("FETCH RECORD %d\n", ++rec);
dump_sqlda(outp_sqlda);
}
exec sql whenever not found continue;
strcpy(msg, "close");
exec sql close mycur1;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id1;
free(outp_sqlda);
/* SQLDA test for getting all records from a table
using the Informix-specific FETCH ... USING DESCRIPTOR
*/
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id2 from :stmt1;
strcpy(msg, "declare");
exec sql declare mycur2 cursor for st_id2;
strcpy(msg, "open");
exec sql open mycur2;
exec sql whenever not found do break;
rec = 0;
while (1)
{
strcpy(msg, "fetch");
exec sql fetch from mycur2 using descriptor outp_sqlda;
printf("FETCH RECORD %d\n", ++rec);
dump_sqlda(outp_sqlda);
}
exec sql whenever not found continue;
strcpy(msg, "close");
exec sql close mycur2;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id2;
free(outp_sqlda);
/* SQLDA test for getting one record using an input descriptor */
/* Input sqlda has to be built manually */
inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
memset(inp_sqlda, 0, sizeof(sqlda_t));
inp_sqlda->sqld = 1;
inp_sqlda->sqlvar = malloc(sizeof(sqlvar_t));
memset(inp_sqlda->sqlvar, 0, sizeof(sqlvar_t));
inp_sqlda->sqlvar[0].sqltype = SQLINT;
inp_sqlda->sqlvar[0].sqldata = (char *)&id;
printf("EXECUTE RECORD 4\n");
id = 4;
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id3 FROM :stmt2;
strcpy(msg, "execute");
exec sql execute st_id3 using descriptor inp_sqlda into descriptor outp_sqlda;
dump_sqlda(outp_sqlda);
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id3;
free(inp_sqlda->sqlvar);
free(inp_sqlda);
free(outp_sqlda);
/* SQLDA test for getting one record using an input descriptor
* on a named connection
*/
exec sql connect to REGRESSDB1 as con2;
/* Input sqlda has to be built manually */
inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
memset(inp_sqlda, 0, sizeof(sqlda_t));
inp_sqlda->sqld = 1;
inp_sqlda->sqlvar = malloc(sizeof(sqlvar_t));
memset(inp_sqlda->sqlvar, 0, sizeof(sqlvar_t));
inp_sqlda->sqlvar[0].sqltype = SQLINT;
inp_sqlda->sqlvar[0].sqldata = (char *)&id;
printf("EXECUTE RECORD 4\n");
id = 4;
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql at con2 prepare st_id4 FROM :stmt2;
strcpy(msg, "execute");
exec sql at con2 execute st_id4 using descriptor inp_sqlda into descriptor outp_sqlda;
dump_sqlda(outp_sqlda);
strcpy(msg, "commit");
exec sql at con2 commit;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id4;
free(inp_sqlda->sqlvar);
free(inp_sqlda);
free(outp_sqlda);
strcpy(msg, "disconnect");
exec sql disconnect con2;
/* End test */
strcpy(msg, "drop");
exec sql drop table t1;
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "disconnect");
exec sql disconnect;
return (0);
}
...@@ -3,6 +3,7 @@ test: compat_informix/charfuncs ...@@ -3,6 +3,7 @@ test: compat_informix/charfuncs
test: compat_informix/rfmtdate test: compat_informix/rfmtdate
test: compat_informix/rfmtlong test: compat_informix/rfmtlong
test: compat_informix/rnull test: compat_informix/rnull
test: compat_informix/sqlda
test: compat_informix/test_informix test: compat_informix/test_informix
test: compat_informix/test_informix2 test: compat_informix/test_informix2
test: connect/test2 test: connect/test2
...@@ -29,6 +30,7 @@ test: sql/code100 ...@@ -29,6 +30,7 @@ test: sql/code100
test: sql/copystdout test: sql/copystdout
test: sql/define test: sql/define
test: sql/desc test: sql/desc
test: sql/sqlda
test: sql/dynalloc test: sql/dynalloc
test: sql/dynalloc2 test: sql/dynalloc2
test: sql/dyntest test: sql/dyntest
......
...@@ -3,6 +3,7 @@ test: compat_informix/charfuncs ...@@ -3,6 +3,7 @@ test: compat_informix/charfuncs
test: compat_informix/rfmtdate test: compat_informix/rfmtdate
test: compat_informix/rfmtlong test: compat_informix/rfmtlong
test: compat_informix/rnull test: compat_informix/rnull
test: compat_informix/sqlda
test: compat_informix/test_informix test: compat_informix/test_informix
test: compat_informix/test_informix2 test: compat_informix/test_informix2
test: connect/test2 test: connect/test2
...@@ -29,6 +30,7 @@ test: sql/code100 ...@@ -29,6 +30,7 @@ test: sql/code100
test: sql/copystdout test: sql/copystdout
test: sql/define test: sql/define
test: sql/desc test: sql/desc
test: sql/sqlda
test: sql/dynalloc test: sql/dynalloc
test: sql/dynalloc2 test: sql/dynalloc2
test: sql/dyntest test: sql/dyntest
......
This diff is collapsed.
This diff is collapsed.
FETCH RECORD 1
name sqlda descriptor: 'id' value 1
name sqlda descriptor: 't' value 'a'
name sqlda descriptor: 'd1' value DECIMAL '1.0'
name sqlda descriptor: 'd2' value 1.000000
name sqlda descriptor: 'c' value 'a '
FETCH RECORD 2
name sqlda descriptor: 'id' value 2
name sqlda descriptor: 't' value NULL'
name sqlda descriptor: 'd1' value NULL'
name sqlda descriptor: 'd2' value NULL'
name sqlda descriptor: 'c' value NULL'
FETCH RECORD 3
name sqlda descriptor: 'id' value 3
name sqlda descriptor: 't' value '"c"'
name sqlda descriptor: 'd1' value DECIMAL '-3'
name sqlda descriptor: 'd2' value nan
name sqlda descriptor: 'c' value 'c '
FETCH RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value DECIMAL '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
FETCH RECORD 1
name sqlda descriptor: 'id' value 1
name sqlda descriptor: 't' value 'a'
name sqlda descriptor: 'd1' value DECIMAL '1.0'
name sqlda descriptor: 'd2' value 1.000000
name sqlda descriptor: 'c' value 'a '
FETCH RECORD 2
name sqlda descriptor: 'id' value 2
name sqlda descriptor: 't' value NULL'
name sqlda descriptor: 'd1' value NULL'
name sqlda descriptor: 'd2' value NULL'
name sqlda descriptor: 'c' value NULL'
FETCH RECORD 3
name sqlda descriptor: 'id' value 3
name sqlda descriptor: 't' value '"c"'
name sqlda descriptor: 'd1' value DECIMAL '-3'
name sqlda descriptor: 'd2' value nan
name sqlda descriptor: 'c' value 'c '
FETCH RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value DECIMAL '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value DECIMAL '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value DECIMAL '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
This diff is collapsed.
This diff is collapsed.
FETCH RECORD 1
name sqlda descriptor: 'id' value 1
name sqlda descriptor: 't' value 'a'
name sqlda descriptor: 'd1' value NUMERIC '1.0'
name sqlda descriptor: 'd2' value 1.000000
name sqlda descriptor: 'c' value 'a '
FETCH RECORD 2
name sqlda descriptor: 'id' value 2
name sqlda descriptor: 't' value NULL'
name sqlda descriptor: 'd1' value NULL'
name sqlda descriptor: 'd2' value NULL'
name sqlda descriptor: 'c' value NULL'
FETCH RECORD 3
name sqlda descriptor: 'id' value 3
name sqlda descriptor: 't' value '"c"'
name sqlda descriptor: 'd1' value NUMERIC '-3'
name sqlda descriptor: 'd2' value nan
name sqlda descriptor: 'c' value 'c '
FETCH RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
FETCH RECORD 1
name sqlda descriptor: 'id' value 1
name sqlda descriptor: 't' value 'a'
name sqlda descriptor: 'd1' value NUMERIC '1.0'
name sqlda descriptor: 'd2' value 1.000000
name sqlda descriptor: 'c' value 'a '
FETCH RECORD 2
name sqlda descriptor: 'id' value 2
name sqlda descriptor: 't' value NULL'
name sqlda descriptor: 'd1' value NULL'
name sqlda descriptor: 'd2' value NULL'
name sqlda descriptor: 'c' value NULL'
FETCH RECORD 3
name sqlda descriptor: 'id' value 3
name sqlda descriptor: 't' value '"c"'
name sqlda descriptor: 'd1' value NUMERIC '-3'
name sqlda descriptor: 'd2' value nan
name sqlda descriptor: 'c' value 'c '
FETCH RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
EXECUTE RECORD 4
name sqlda descriptor: 'id' value 4
name sqlda descriptor: 't' value 'd'
name sqlda descriptor: 'd1' value NUMERIC '4.0'
name sqlda descriptor: 'd2' value 4.000000
name sqlda descriptor: 'c' value 'd '
...@@ -20,6 +20,7 @@ TESTS = array array.c \ ...@@ -20,6 +20,7 @@ TESTS = array array.c \
parser parser.c \ parser parser.c \
quote quote.c \ quote quote.c \
show show.c \ show show.c \
sqlda sqlda.c \
insupd insupd.c insupd insupd.c
all: $(TESTS) all: $(TESTS)
......
...@@ -32,30 +32,30 @@ main(void) ...@@ -32,30 +32,30 @@ main(void)
EXEC SQL PREPARE foo2 FROM :stmt2; EXEC SQL PREPARE foo2 FROM :stmt2;
EXEC SQL PREPARE foo3 FROM :stmt3; EXEC SQL PREPARE foo3 FROM :stmt3;
EXEC SQL EXECUTE foo1 USING DESCRIPTOR indesc; EXEC SQL EXECUTE foo1 USING SQL DESCRIPTOR indesc;
EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2;
EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2null, DATA = :val2; EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2null, DATA = :val2;
EXEC SQL EXECUTE foo1 USING DESCRIPTOR indesc; EXEC SQL EXECUTE foo1 USING SQL DESCRIPTOR indesc;
EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 3; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 3;
EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val1, DATA = 'this is a long test'; EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val1, DATA = 'this is a long test';
EXEC SQL EXECUTE "Foo-1" USING DESCRIPTOR indesc; EXEC SQL EXECUTE "Foo-1" USING SQL DESCRIPTOR indesc;
EXEC SQL DEALLOCATE "Foo-1"; EXEC SQL DEALLOCATE "Foo-1";
EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = :val1; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = :val1;
EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2i, DATA = :val2; EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2i, DATA = :val2;
EXEC SQL EXECUTE foo2 USING DESCRIPTOR indesc INTO DESCRIPTOR outdesc; EXEC SQL EXECUTE foo2 USING SQL DESCRIPTOR indesc INTO SQL DESCRIPTOR outdesc;
EXEC SQL GET DESCRIPTOR outdesc VALUE 1 :val2output = DATA; EXEC SQL GET DESCRIPTOR outdesc VALUE 1 :val2output = DATA;
printf("output = %s\n", val2output); printf("output = %s\n", val2output);
EXEC SQL DECLARE c1 CURSOR FOR foo2; EXEC SQL DECLARE c1 CURSOR FOR foo2;
EXEC SQL OPEN c1 USING DESCRIPTOR indesc; EXEC SQL OPEN c1 USING SQL DESCRIPTOR indesc;
EXEC SQL FETCH next FROM c1 INTO :val1output:ind1, :val2output:ind2; EXEC SQL FETCH next FROM c1 INTO :val1output:ind1, :val2output:ind2;
printf("val1=%d (ind1: %d) val2=%s (ind2: %d)\n", printf("val1=%d (ind1: %d) val2=%s (ind2: %d)\n",
...@@ -67,7 +67,7 @@ main(void) ...@@ -67,7 +67,7 @@ main(void)
EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2;
EXEC SQL DECLARE c2 CURSOR FOR foo3; EXEC SQL DECLARE c2 CURSOR FOR foo3;
EXEC SQL OPEN c2 USING DESCRIPTOR indesc; EXEC SQL OPEN c2 USING SQL DESCRIPTOR indesc;
EXEC SQL FETCH next FROM c2 INTO :val1output, :val2output :val2i; EXEC SQL FETCH next FROM c2 INTO :val1output, :val2output :val2i;
printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output); printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output);
......
...@@ -39,7 +39,7 @@ int main(void) ...@@ -39,7 +39,7 @@ int main(void)
exec sql insert into test (b, c, d, e, f, g, h, i) values (2.446456, NULL, 'v', 'c', '2003-03-03 12:33:07 PDT', false, NULL, NULL); exec sql insert into test (b, c, d, e, f, g, h, i) values (2.446456, NULL, 'v', 'c', '2003-03-03 12:33:07 PDT', false, NULL, NULL);
exec sql allocate descriptor mydesc; exec sql allocate descriptor mydesc;
exec sql select a,b,c,d,e,f,g,h,i into descriptor mydesc from test order by a; exec sql select a,b,c,d,e,f,g,h,i into sql descriptor mydesc from test order by a;
exec sql get descriptor mydesc value 1 :d1=DATA, :i1=INDICATOR; exec sql get descriptor mydesc value 1 :d1=DATA, :i1=INDICATOR;
exec sql get descriptor mydesc value 2 :d2=DATA, :i2=INDICATOR; exec sql get descriptor mydesc value 2 :d2=DATA, :i2=INDICATOR;
exec sql get descriptor mydesc value 3 :d3=DATA, :i3=INDICATOR; exec sql get descriptor mydesc value 3 :d3=DATA, :i3=INDICATOR;
......
...@@ -30,7 +30,7 @@ int main(void) ...@@ -30,7 +30,7 @@ int main(void)
exec sql insert into test values (NULL, NULL); exec sql insert into test values (NULL, NULL);
exec sql allocate descriptor mydesc; exec sql allocate descriptor mydesc;
exec sql select * into descriptor mydesc from test; exec sql select * into sql descriptor mydesc from test;
exec sql get descriptor mydesc :colnum=COUNT; exec sql get descriptor mydesc :colnum=COUNT;
exec sql get descriptor mydesc value 1 :ip1=DATA, :ipointer1=INDICATOR; exec sql get descriptor mydesc value 1 :ip1=DATA, :ipointer1=INDICATOR;
exec sql get descriptor mydesc value 2 :cp2=DATA, :ipointer2=INDICATOR; exec sql get descriptor mydesc value 2 :cp2=DATA, :ipointer2=INDICATOR;
......
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <limits.h>
exec sql include ../regression;
exec sql include sqlda.h;
exec sql include pgtypes_numeric.h;
exec sql whenever sqlerror stop;
/* These shouldn't be under DECLARE SECTION */
sqlda_t *inp_sqlda, *outp_sqlda, *outp_sqlda1;
static void
dump_sqlda(sqlda_t *sqlda)
{
int i;
if (sqlda == NULL)
{
printf("dump_sqlda called with NULL sqlda\n");
return;
}
for (i = 0; i < sqlda->sqld; i++)
{
if (sqlda->sqlvar[i].sqlind && *(sqlda->sqlvar[i].sqlind) == -1)
printf("name sqlda descriptor: '%s' value NULL'\n", sqlda->sqlvar[i].sqlname.data);
else
switch (sqlda->sqlvar[i].sqltype)
{
case ECPGt_char:
printf("name sqlda descriptor: '%s' value '%s'\n", sqlda->sqlvar[i].sqlname.data, sqlda->sqlvar[i].sqldata);
break;
case ECPGt_int:
printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqlname.data, *(int *)sqlda->sqlvar[i].sqldata);
break;
#ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long:
#else
case ECPGt_long:
#endif
printf("name sqlda descriptor: '%s' value " INT64_FORMAT "\n", sqlda->sqlvar[i].sqlname.data, *(int64_t *)sqlda->sqlvar[i].sqldata);
break;
case ECPGt_double:
printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sqlname.data, *(double *)sqlda->sqlvar[i].sqldata);
break;
case ECPGt_numeric:
{
char *val;
val = PGTYPESnumeric_to_asc((numeric*)sqlda->sqlvar[i].sqldata, -1);
printf("name sqlda descriptor: '%s' value NUMERIC '%s'\n", sqlda->sqlvar[i].sqlname.data, val);
free(val);
break;
}
}
}
}
int
main (void)
{
exec sql begin declare section;
char *stmt1 = "SELECT * FROM t1";
char *stmt2 = "SELECT * FROM t1 WHERE id = ?";
int rec;
int id;
exec sql end declare section;
char msg[128];
ECPGdebug(1, stderr);
strcpy(msg, "connect");
exec sql connect to REGRESSDB1 as regress1;
strcpy(msg, "set");
exec sql set datestyle to iso;
strcpy(msg, "create");
exec sql create table t1(
id integer,
t text,
d1 numeric,
d2 float8,
c char(10));
strcpy(msg, "insert");
exec sql insert into t1 values
(1, 'a', 1.0, 1, 'a'),
(2, null, null, null, null),
(3, '"c"', -3, 'nan'::float8, 'c'),
(4, 'd', 4.0, 4, 'd');
strcpy(msg, "commit");
exec sql commit;
/* SQLDA test for getting all records from a table */
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id1 from :stmt1;
strcpy(msg, "declare");
exec sql declare mycur1 cursor for st_id1;
strcpy(msg, "open");
exec sql open mycur1;
exec sql whenever not found do break;
rec = 0;
while (1)
{
strcpy(msg, "fetch");
exec sql fetch 1 from mycur1 into descriptor outp_sqlda;
printf("FETCH RECORD %d\n", ++rec);
dump_sqlda(outp_sqlda);
}
exec sql whenever not found continue;
strcpy(msg, "close");
exec sql close mycur1;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id1;
free(outp_sqlda);
/* SQLDA test for getting ALL records into the sqlda list */
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id2 from :stmt1;
strcpy(msg, "declare");
exec sql declare mycur2 cursor for st_id2;
strcpy(msg, "open");
exec sql open mycur2;
strcpy(msg, "fetch");
exec sql fetch all from mycur2 into descriptor outp_sqlda;
outp_sqlda1 = outp_sqlda;
rec = 0;
while (outp_sqlda1)
{
sqlda_t *ptr;
printf("FETCH RECORD %d\n", ++rec);
dump_sqlda(outp_sqlda1);
ptr = outp_sqlda1;
outp_sqlda1 = outp_sqlda1->desc_next;
free(ptr);
}
strcpy(msg, "close");
exec sql close mycur2;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id2;
/* SQLDA test for getting one record using an input descriptor */
/*
* Input sqlda has to be built manually
* sqlda_t contains 1 sqlvar_t structure already.
*/
inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
memset(inp_sqlda, 0, sizeof(sqlda_t));
inp_sqlda->sqln = 1;
inp_sqlda->sqlvar[0].sqltype = ECPGt_int;
inp_sqlda->sqlvar[0].sqldata = (char *)&id;
printf("EXECUTE RECORD 4\n");
id = 4;
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql prepare st_id3 FROM :stmt2;
strcpy(msg, "execute");
exec sql execute st_id3 using descriptor inp_sqlda into descriptor outp_sqlda;
dump_sqlda(outp_sqlda);
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id3;
free(inp_sqlda);
free(outp_sqlda);
/* SQLDA test for getting one record using an input descriptor
* on a named connection
*/
exec sql connect to REGRESSDB1 as con2;
/*
* Input sqlda has to be built manually
* sqlda_t contains 1 sqlvar_t structure already.
*/
inp_sqlda = (sqlda_t *)malloc(sizeof(sqlda_t));
memset(inp_sqlda, 0, sizeof(sqlda_t));
inp_sqlda->sqln = 1;
inp_sqlda->sqlvar[0].sqltype = ECPGt_int;
inp_sqlda->sqlvar[0].sqldata = (char *)&id;
printf("EXECUTE RECORD 4\n");
id = 4;
outp_sqlda = NULL;
strcpy(msg, "prepare");
exec sql at con2 prepare st_id4 FROM :stmt2;
strcpy(msg, "execute");
exec sql at con2 execute st_id4 using descriptor inp_sqlda into descriptor outp_sqlda;
dump_sqlda(outp_sqlda);
strcpy(msg, "commit");
exec sql at con2 commit;
strcpy(msg, "deallocate");
exec sql deallocate prepare st_id4;
free(inp_sqlda);
free(outp_sqlda);
strcpy(msg, "disconnect");
exec sql disconnect con2;
/* End test */
strcpy(msg, "drop");
exec sql drop table t1;
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "disconnect");
exec sql disconnect;
return (0);
}
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