提交 b3b35e98 编写于 作者: M Michael Meskes

*** empty log message ***

上级 3ca3bb7d
......@@ -23,8 +23,9 @@ indicator-error?
Add a semantic check level, e.g. check if a table really exists.
It would be nice if there was a alternative library using SPI functions
instead of libpq so we can write backend functions using ecpg.
Missing statements:
- exec sql ifdef
- exec sql allocate
- exec sql deallocate
- SQLSTATE
descriptor statements have the following shortcomings
- up to now the only reasonable statement is
FETCH ... INTO SQL DESCRIPTOR <name>
no input variables allowed!
Reason: to fully support dynamic SQL the frontend/backend communication
should change to recognize input parameters.
Since this is not likely to happen in the near future and you
can cover the same functionality with the existing infrastructure
I'll leave the work to someone else.
- string buffer overflow does not always generate warnings
(beware: terminating 0 may be missing because strncpy is used)
:var=data sets sqlwarn accordingly (but not indicator)
- char variables pointing to NULL are not allocated on demand
- string truncation does not show up in indicator
......@@ -2,26 +2,11 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.1 2000/02/16 16:18:12 meskes Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.2 2000/02/17 19:48:41 meskes Exp $
*/
/* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include <libpq-fe.h>
#include <libpq/pqcomm.h>
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>
#endif
#include <sql3types.h>
static struct descriptor
......
......@@ -10,8 +10,7 @@ CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DINCLUDE_PATH=\"$(HEADERDIR)\" -g
OBJ=preproc.o pgc.o type.o ecpg.o ecpg_keywords.o \
keywords.o c_keywords.o ../lib/typename.o
#../../../backend/parser/scansup.o
keywords.o c_keywords.o ../lib/typename.o descriptor.o variable.o
all:: ecpg
......
/*
* functions needed for descriptor handling
*/
#include "postgres.h"
#include "extern.h"
/*
* assignment handling function (descriptor)
*/
struct assignment *assignments;
void push_assignment(char *var,char *value)
{
struct assignment *new=(struct assignment *)mm_alloc(sizeof(struct assignment));
new->next=assignments;
new->variable=mm_alloc(strlen(var)+1);
strcpy(new->variable,var);
new->value=mm_alloc(strlen(value)+1);
strcpy(new->value,value);
assignments=new;
}
static void
drop_assignments(void)
{ while (assignments)
{ struct assignment *old_head=assignments;
assignments=old_head->next;
free(old_head->variable);
free(old_head->value);
free(old_head);
}
}
/* XXX: these should be more accurate (consider ECPGdump_a_* ) */
static void ECPGnumeric_lvalue(FILE *f,char *name)
{ const struct variable *v=find_variable(name);
switch(v->type->typ)
{
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
fputs(name,yyout);
break;
default:
snprintf(errortext,sizeof errortext,"variable %s: numeric type needed"
,name);
mmerror(ET_ERROR,errortext);
break;
}
}
static void ECPGstring_buffer(FILE *f,char *name)
{
const struct variable *v=find_variable(name);
switch(v->type->typ)
{
case ECPGt_varchar:
fprintf(yyout,"%s.arr",name);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
fputs(name,yyout);
break;
default:
snprintf(errortext,sizeof errortext,"variable %s: character type needed"
,name);
mmerror(ET_ERROR,errortext);
break;
}
}
static void ECPGstring_length(FILE *f,char *name)
{
const struct variable *v=find_variable(name);
switch(v->type->typ)
{ case ECPGt_varchar:
case ECPGt_char:
case ECPGt_unsigned_char:
if (!v->type->size)
{ snprintf(errortext,sizeof errortext,"zero length char variable %s for assignment",
v->name);
mmerror(ET_ERROR,errortext);
}
fprintf(yyout,"%ld",v->type->size);
break;
default:
snprintf(errortext,sizeof errortext,"variable %s: character type needed"
,name);
mmerror(ET_ERROR,errortext);
break;
}
}
static void ECPGdata_assignment(char *variable,char *index_plus_1)
{
const struct variable *v=find_variable(variable);
fprintf(yyout,"\t\t\tif (!PQgetisnull(ECPGresult,0,(%s)-1))\n",index_plus_1);
switch(v->type->typ)
{
case ECPGt_short:
case ECPGt_int: /* use the same conversion as ecpglib does */
case ECPGt_long:
fprintf(yyout,"\t\t\t\t%s=strtol(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
,variable,index_plus_1);
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
fprintf(yyout,"\t\t\t\t%s=strtoul(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
,variable,index_plus_1);
break;
case ECPGt_float:
case ECPGt_double:
fprintf(yyout,"\t\t\t\t%s=strtod(PQgetvalue(ECPGresult,0,(%s)-1),NULL);\n"
,variable,index_plus_1);
break;
case ECPGt_bool:
fprintf(yyout,"\t\t\t\t%s=PQgetvalue(ECPGresult,0,(%s)-1)[0]=='t';\n"
,variable,index_plus_1);
break;
case ECPGt_varchar:
fprintf(yyout,"\t\t\t{\tstrncpy(%s.arr,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
,variable,index_plus_1,v->type->size);
fprintf(yyout,"\t\t\t\t%s.len=strlen(PQgetvalue(ECPGresult,0,(%s)-1)\n"
,variable,index_plus_1);
fprintf(yyout,"\t\t\t\tif (%s.len>%ld) { %s.len=%ld; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
,variable,v->type->size,variable,v->type->size);
fputs("\t\t\t}\n",yyout);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
if (!v->type->size)
{
snprintf(errortext,sizeof errortext,"zero length char variable %s for DATA assignment",
v->name);
mmerror(ET_ERROR,errortext);
}
fprintf(yyout,"\t\t\t{\tstrncpy(%s,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
,variable,index_plus_1,v->type->size);
fprintf(yyout,"\t\t\t\tif (strlen(PQgetvalue(ECPGresult,0,(%s)-1))>=%ld)\n"
"\t\t\t\t{ %s[%ld]=0; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
,index_plus_1,v->type->size,variable,v->type->size-1);
fputs("\t\t\t}\n",yyout);
break;
default:
snprintf(errortext,sizeof errortext,"unknown variable type %d for DATA assignment"
,v->type->typ);
mmerror(ET_ERROR,errortext);
break;
}
}
void
output_get_descr_header(char *desc_name)
{
struct assignment *results;
fprintf(yyout,"{\tPGresult *ECPGresult=ECPGresultByDescriptor(%d, \"%s\");\n" ,yylineno,desc_name);
fputs("\tif (ECPGresult)\n\t{",yyout);
for (results=assignments;results!=NULL;results=results->next)
{
if (!strcasecmp(results->value,"count"))
{
fputs("\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fputs("=PQnfields(ECPGresult);\n",yyout);
}
else
{ snprintf(errortext,sizeof errortext,"unknown descriptor header item '%s'",results->value);
mmerror(ET_WARN,errortext);
}
}
drop_assignments();
fputs("}",yyout);
whenever_action(2|1);
}
void
output_get_descr(char *desc_name)
{
struct assignment *results;
int flags=0;
const int DATA_SEEN=1;
const int INDICATOR_SEEN=2;
fprintf(yyout,"{\tPGresult *ECPGresult=ECPGresultByDescriptor(%d, \"%s\");\n"
,yylineno,desc_name);
fputs("\tif (ECPGresult)\n\t{",yyout);
fprintf(yyout,"\tif (PQntuples(ECPGresult)<1) ECPGraise(%d,ECPG_NOT_FOUND);\n",yylineno);
fprintf(yyout,"\t\telse if (%s<1 || %s>PQnfields(ECPGresult))\n"
"\t\t\tECPGraise(%d,ECPG_INVALID_DESCRIPTOR_INDEX);\n"
,descriptor_index,descriptor_index,yylineno);
fputs("\t\telse\n\t\t{\n",yyout);
for (results=assignments;results!=NULL;results=results->next)
{
if (!strcasecmp(results->value,"type"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=ECPGDynamicType(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
}
else if (!strcasecmp(results->value,"datetime_interval_code"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=ECPGDynamicType_DDT(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
}
else if (!strcasecmp(results->value,"length"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)-VARHDRSZ;\n",descriptor_index);
}
else if (!strcasecmp(results->value,"octet_length"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=PQfsize(ECPGresult,(%s)-1);\n",descriptor_index);
}
else if (!strcasecmp(results->value,"returned_length")
|| !strcasecmp(results->value,"returned_octet_length"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=PQgetlength(ECPGresult,0,(%s)-1);\n",descriptor_index);
}
else if (!strcasecmp(results->value,"precision"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)>>16;\n",descriptor_index);
}
else if (!strcasecmp(results->value,"scale"))
{
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=(PQfmod(ECPGresult,(%s)-1)-VARHDRSZ)&0xffff;\n",descriptor_index);
}
else if (!strcasecmp(results->value,"nullable"))
{
mmerror(ET_WARN,"nullable is always 1");
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=1;\n");
}
else if (!strcasecmp(results->value,"key_member"))
{
mmerror(ET_WARN,"key_member is always 0");
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=0;\n");
}
else if (!strcasecmp(results->value,"name"))
{
fputs("\t\t\tstrncpy(",yyout);
ECPGstring_buffer(yyout,results->variable);
fprintf(yyout,",PQfname(ECPGresult,(%s)-1),",descriptor_index);
ECPGstring_length(yyout,results->variable);
fputs(");\n",yyout);
}
else if (!strcasecmp(results->value,"indicator"))
{
flags|=INDICATOR_SEEN;
fputs("\t\t\t",yyout);
ECPGnumeric_lvalue(yyout,results->variable);
fprintf(yyout,"=-PQgetisnull(ECPGresult,0,(%s)-1);\n",descriptor_index);
}
else if (!strcasecmp(results->value,"data"))
{
flags|=DATA_SEEN;
ECPGdata_assignment(results->variable,descriptor_index);
}
else
{
snprintf(errortext,sizeof errortext,"unknown descriptor header item '%s'",results->value);
mmerror(ET_WARN,errortext);
}
}
if (flags==DATA_SEEN) /* no indicator */
{
fprintf(yyout,"\t\t\tif (PQgetisnull(ECPGresult,0,(%s)-1))\n"
"\t\t\t\tECPGraise(%d,ECPG_MISSING_INDICATOR);\n"
,descriptor_index,yylineno);
}
drop_assignments();
fputs("\t\t}\n\t}\n",yyout);
whenever_action(2|1);
}
/*
* descriptor name lookup
*/
static struct descriptor *descriptors;
void add_descriptor(char *name,char *connection)
{
struct descriptor *new=(struct descriptor *)mm_alloc(sizeof(struct descriptor));
new->next=descriptors;
new->name=mm_alloc(strlen(name)+1);
strcpy(new->name,name);
if (connection)
{ new->connection=mm_alloc(strlen(connection)+1);
strcpy(new->connection,connection);
}
else new->connection=connection;
descriptors=new;
}
void drop_descriptor(char *name,char *connection)
{
struct descriptor *i;
struct descriptor **lastptr=&descriptors;
for (i=descriptors;i;lastptr=&i->next,i=i->next)
{
if (!strcmp(name,i->name))
{
if ((!connection && !i->connection)
|| (connection && i->connection
&& !strcmp(connection,i->connection)))
{
*lastptr=i->next;
if (i->connection) free(i->connection);
free(i->name);
free(i);
return;
}
}
}
snprintf(errortext,sizeof errortext,"unknown descriptor %s",name);
mmerror(ET_WARN,errortext);
}
struct descriptor *lookup_descriptor(char *name,char *connection)
{
struct descriptor *i;
for (i=descriptors;i;i=i->next)
{
if (!strcmp(name,i->name))
{
if ((!connection && !i->connection)
|| (connection && i->connection
&& !strcmp(connection,i->connection)))
{
return i;
}
}
}
snprintf(errortext,sizeof errortext,"unknown descriptor %s",name);
mmerror(ET_WARN,errortext);
return NULL;
}
void
output_statement_desc(char * stmt, int mode)
{
int i, j=strlen(stmt);
fprintf(yyout, "{ ECPGdo_descriptor(__LINE__, %s, \"%s\", \"",
connection ? connection : "NULL", descriptor_name);
/* do this char by char as we have to filter '\"' */
for (i = 0;i < j; i++) {
if (stmt[i] != '\"')
fputc(stmt[i], yyout);
else
fputs("\\\"", yyout);
}
fputs("\");", yyout);
mode |= 2;
whenever_action(mode);
free(stmt);
if (connection != NULL)
free(connection);
free(descriptor_name);
}
......@@ -241,6 +241,10 @@ main(int argc, char *const argv[])
/* and structure member lists */
memset(struct_member_list, 0, sizeof(struct_member_list));
/* finally the actual connection */
connection = NULL;
/* initialize lex */
lex_init();
......
......@@ -18,6 +18,9 @@ extern int yylineno,
yyleng;
extern FILE *yyin,
*yyout;
extern char *descriptor_index;
extern char *descriptor_name;
extern char *connection;
extern struct _include_path *include_paths;
extern struct cursor *cur;
......@@ -42,9 +45,26 @@ extern void yyerror(char *);
extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
extern char *mm_strdup(const char *);
extern void mmerror(enum errortype, char * );
ScanKeyword *ScanECPGKeywordLookup(char *);
ScanKeyword *ScanCKeywordLookup(char *);
extern ScanKeyword *ScanECPGKeywordLookup(char *);
extern ScanKeyword *ScanCKeywordLookup(char *);
extern void output_get_descr_header(char *);
extern void output_get_descr(char *);
extern void push_assignment(char *, char *);
extern struct variable * find_variable(char *);
extern void whenever_action(int);
extern void add_descriptor(char *,char *);
extern void drop_descriptor(char *,char *);
extern struct descriptor *lookup_descriptor(char *,char *);
extern void output_statement_desc(char *, int);
extern void add_variable(struct arguments ** , struct variable * , struct variable *);
extern void dump_variables(struct arguments *, int);
extern struct typedefs *get_typedef(char *);
extern void adjust_array(enum ECPGttype, int *, int *, int, int, bool);
extern void reset_variables(void);
extern void check_indicator(struct ECPGtype *);
extern void remove_variables(int);
extern struct variable *new_variable(const char *, struct ECPGtype *);
/* return codes */
#define OK 0
......
......@@ -2,6 +2,7 @@
#include <string.h>
#include <stdlib.h>
#include "postgres.h"
#include "extern.h"
/* malloc + error check */
......
#include "postgres.h"
#include "extern.h"
struct variable * allvariables = NULL;
struct variable *
new_variable(const char * name, struct ECPGtype * type)
{
struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable));
p->name = mm_strdup(name);
p->type = type;
p->brace_level = braces_open;
p->next = allvariables;
allvariables = p;
return(p);
}
static struct variable *
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
{
char *next = strchr(++str, '.'), c = '\0';
if (next != NULL)
{
c = *next;
*next = '\0';
}
for (; members; members = members->next)
{
if (strcmp(members->name, str) == 0)
{
if (c == '\0')
{
/* found the end */
switch (members->typ->typ)
{
case ECPGt_array:
return(new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size)));
case ECPGt_struct:
case ECPGt_union:
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members, members->typ->typ)));
default:
return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size)));
}
}
else
{
*next = c;
if (c == '-')
{
next++;
return(find_struct_member(name, next, members->typ->u.element->u.members));
}
else return(find_struct_member(name, next, members->typ->u.members));
}
}
}
return(NULL);
}
static struct variable *
find_struct(char * name, char *next)
{
struct variable * p;
char c = *next;
/* first get the mother structure entry */
*next = '\0';
p = find_variable(name);
if (c == '-')
{
if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union)
{
sprintf(errortext, "variable %s is not a pointer", name);
mmerror(ET_FATAL, errortext);
}
if (p->type->u.element->typ != ECPGt_struct && p->type->u.element->typ != ECPGt_union)
{
sprintf(errortext, "variable %s is not a pointer to a structure or a union", name);
mmerror(ET_FATAL, errortext);
}
/* restore the name, we will need it later on */
*next = c;
next++;
return find_struct_member(name, next, p->type->u.element->u.members);
}
else
{
if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union)
{
sprintf(errortext, "variable %s is neither a structure nor a union", name);
mmerror(ET_FATAL, errortext);
}
/* restore the name, we will need it later on */
*next = c;
return find_struct_member(name, next, p->type->u.members);
}
}
static struct variable *
find_simple(char * name)
{
struct variable * p;
for (p = allvariables; p; p = p->next)
{
if (strcmp(p->name, name) == 0)
return p;
}
return(NULL);
}
/* Note that this function will end the program in case of an unknown */
/* variable */
struct variable *
find_variable(char * name)
{
char * next;
struct variable * p;
if ((next = strchr(name, '.')) != NULL)
p = find_struct(name, next);
else if ((next = strstr(name, "->")) != NULL)
p = find_struct(name, next);
else
p = find_simple(name);
if (p == NULL)
{
sprintf(errortext, "The variable %s is not declared", name);
mmerror(ET_FATAL, errortext);
}
return(p);
}
void
remove_variables(int brace_level)
{
struct variable * p, *prev;
for (p = prev = allvariables; p; p = p ? p->next : NULL)
{
if (p->brace_level >= brace_level)
{
/* remove it */
if (p == allvariables)
prev = allvariables = p->next;
else
prev->next = p->next;
ECPGfree_type(p->type);
free(p->name);
free(p);
p = prev;
}
else
prev = p;
}
}
/*
* Here are the variables that need to be handled on every request.
* These are of two kinds: input and output.
* I will make two lists for them.
*/
struct arguments * argsinsert = NULL;
struct arguments * argsresult = NULL;
void
reset_variables(void)
{
argsinsert = NULL;
argsresult = NULL;
}
/* Add a variable to a request. */
void
add_variable(struct arguments ** list, struct variable * var, struct variable * ind)
{
struct arguments * p = (struct arguments *)mm_alloc(sizeof(struct arguments));
p->variable = var;
p->indicator = ind;
p->next = *list;
*list = p;
}
/* Dump out a list of all the variable on this list.
This is a recursive function that works from the end of the list and
deletes the list as we go on.
*/
void
dump_variables(struct arguments * list, int mode)
{
if (list == NULL)
{
return;
}
/* The list is build up from the beginning so lets first dump the
end of the list:
*/
dump_variables(list->next, mode);
/* Then the current element and its indicator */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
/* Then release the list element. */
if (mode != 0)
free(list);
}
void
check_indicator(struct ECPGtype *var)
{
/* make sure this is a valid indicator variable */
switch (var->typ)
{
struct ECPGstruct_member *p;
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
break;
case ECPGt_struct:
case ECPGt_union:
for (p = var->u.members; p; p = p->next)
check_indicator(p->typ);
break;
case ECPGt_array:
check_indicator(var->u.element);
break;
default:
mmerror(ET_ERROR, "indicator variable must be integer type");
break;
}
}
struct typedefs *
get_typedef(char *name)
{
struct typedefs *this;
for (this = types; this && strcmp(this->name, name); this = this->next);
if (!this)
{
sprintf(errortext, "invalid datatype '%s'", name);
mmerror(ET_FATAL, errortext);
}
return(this);
}
void
adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dimension, int type_index, bool pointer)
{
if (type_index >= 0)
{
if (*length >= 0)
mmerror(ET_FATAL, "No multi-dimensional array support");
*length = type_index;
}
if (type_dimension >= 0)
{
if (*dimension >= 0 && *length >= 0)
mmerror(ET_FATAL, "No multi-dimensional array support");
if (*dimension >= 0)
*length = *dimension;
*dimension = type_dimension;
}
if (*length >= 0 && *dimension >= 0 && pointer)
mmerror(ET_FATAL, "No multi-dimensional array support");
switch (type_enum)
{
case ECPGt_struct:
case ECPGt_union:
/* pointer has to get dimension 0 */
if (pointer)
{
*length = *dimension;
*dimension = 0;
}
if (*length >= 0)
mmerror(ET_FATAL, "No multi-dimensional array support for structures");
break;
case ECPGt_varchar:
/* pointer has to get dimension 0 */
if (pointer)
*dimension = 0;
/* one index is the string length */
if (*length < 0)
{
*length = *dimension;
*dimension = -1;
}
break;
case ECPGt_char:
case ECPGt_unsigned_char:
/* pointer has to get length 0 */
if (pointer)
*length=0;
/* one index is the string length */
if (*length < 0)
{
*length = (*dimension < 0) ? 1 : *dimension;
*dimension = -1;
}
break;
default:
/* a pointer has dimension = 0 */
if (pointer) {
*length = *dimension;
*dimension = 0;
}
if (*length >= 0)
mmerror(ET_FATAL, "No multi-dimensional array support for simple data types");
break;
}
}
......@@ -27,4 +27,4 @@ stp.so: stp.c
clean:
-/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so
-/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so dyntest
......@@ -2,7 +2,7 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.1 2000/02/16 16:18:29 meskes Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.2 2000/02/17 19:48:58 meskes Exp $
*/
#include <stdio.h>
......@@ -37,7 +37,7 @@ int main(int argc,char **argv)
exec sql allocate descriptor MYDESC;
exec sql connect to test;
exec sql connect to mm;
exec sql prepare MYQUERY from :QUERY;
exec sql declare MYCURS cursor for MYQUERY;
......
......@@ -43,12 +43,13 @@ EXEC SQL END DECLARE SECTION;
printf("Found f=%f\n", f);
EXEC SQL SELECT i
INTO :i
EXEC SQL SELECT a
INTO :a
FROM test
WHERE f = :f;
printf("Found i=%d\n", i);
for (i = 0; i < 10; i++)
printf("Found a[%d] = %d\n", i, a[i]);
EXEC SQL DROP TABLE test;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册