Skip to content

Commit 90326c0

Browse files
author
Michael Meskes
committed
Added SET DESCRIPTOR command.
Note that this still has some bugs. The functionality is there though, it's just a matter of fixing the bugs now. Cleaned up error handling in preprocessor.
1 parent c7beffc commit 90326c0

File tree

11 files changed

+682
-287
lines changed

11 files changed

+682
-287
lines changed

src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* dynamic SQL support routines
22
*
3-
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.7 2003/11/29 19:52:08 pgsql Exp $
3+
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.8 2004/06/30 15:01:56 meskes Exp $
44
*/
55

66
#define POSTGRES_ECPG_INTERNAL
@@ -110,6 +110,51 @@ get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
110110
return (true);
111111
}
112112

113+
static bool
114+
set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
115+
{
116+
switch (vartype)
117+
{
118+
case ECPGt_short:
119+
*target = *(short *) var;
120+
break;
121+
case ECPGt_int:
122+
*target = *(int *) var;
123+
break;
124+
case ECPGt_long:
125+
*target = *(long *) var;
126+
break;
127+
case ECPGt_unsigned_short:
128+
*target = *(unsigned short *) var;
129+
break;
130+
case ECPGt_unsigned_int:
131+
*target = *(unsigned int *) var;
132+
break;
133+
case ECPGt_unsigned_long:
134+
*target = *(unsigned long *) var;
135+
break;
136+
#ifdef HAVE_LONG_LONG_INT_64
137+
case ECPGt_long_long:
138+
*target = *(long long int *) var;
139+
break;
140+
case ECPGt_unsigned_long_long:
141+
*target = *(unsigned long long int *) var;
142+
break;
143+
#endif /* HAVE_LONG_LONG_INT_64 */
144+
case ECPGt_float:
145+
*target = *(float *) var;
146+
break;
147+
case ECPGt_double:
148+
*target = *(double *) var;
149+
break;
150+
default:
151+
ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
152+
return (false);
153+
}
154+
155+
return true;
156+
}
157+
113158
static bool
114159
get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
115160
{
@@ -385,6 +430,124 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
385430
return (true);
386431
}
387432

433+
bool
434+
ECPGset_desc(int lineno, char *desc_name, int index,...)
435+
{
436+
va_list args;
437+
struct descriptor *desc;
438+
struct descriptor_item *desc_item, *last_di;
439+
440+
for (desc = all_descriptors; desc; desc = desc->next)
441+
{
442+
if (strcmp(desc_name, desc->name)==0)
443+
break;
444+
}
445+
446+
if (desc == NULL)
447+
{
448+
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
449+
return false;
450+
}
451+
452+
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
453+
{
454+
if (desc_item->num == index)
455+
break;
456+
}
457+
458+
if (desc_item == NULL)
459+
{
460+
desc_item = ECPGalloc(sizeof(*desc_item), lineno);
461+
desc_item->num = index;
462+
desc_item->next = desc->items;
463+
desc->items = desc_item;
464+
}
465+
466+
va_start(args, index);
467+
468+
do
469+
{
470+
enum ECPGdtype itemtype;
471+
long varcharsize;
472+
long offset;
473+
long arrsize;
474+
enum ECPGttype vartype;
475+
void *var;
476+
477+
itemtype = va_arg(args, enum ECPGdtype);
478+
479+
if (itemtype == ECPGd_EODT)
480+
break;
481+
482+
vartype = va_arg(args, enum ECPGttype);
483+
var = va_arg(args, void *);
484+
varcharsize = va_arg(args, long);
485+
arrsize = va_arg(args, long);
486+
offset = va_arg(args, long);
487+
488+
switch (itemtype)
489+
{
490+
case ECPGd_data:
491+
{
492+
// FIXME: how to do this in general?
493+
switch (vartype)
494+
{
495+
case ECPGt_char:
496+
desc_item->data = strdup((char *)var);
497+
break;
498+
case ECPGt_int:
499+
{
500+
char buf[20];
501+
snprintf(buf, 20, "%d", *(int *)var);
502+
desc_item->data = strdup(buf);
503+
break;
504+
}
505+
default:
506+
abort();
507+
}
508+
break;
509+
}
510+
511+
case ECPGd_indicator:
512+
set_int_item(lineno, &desc_item->indicator, var, vartype);
513+
break;
514+
515+
case ECPGd_length:
516+
set_int_item(lineno, &desc_item->length, var, vartype);
517+
break;
518+
519+
case ECPGd_precision:
520+
set_int_item(lineno, &desc_item->precision, var, vartype);
521+
break;
522+
523+
case ECPGd_scale:
524+
set_int_item(lineno, &desc_item->scale, var, vartype);
525+
break;
526+
527+
case ECPGd_type:
528+
set_int_item(lineno, &desc_item->type, var, vartype);
529+
break;
530+
531+
default:
532+
{
533+
char type_str[20];
534+
snprintf(type_str, sizeof(type_str), "%d", itemtype);
535+
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
536+
return false;
537+
}
538+
}
539+
540+
/*if (itemtype == ECPGd_data)
541+
{
542+
free(desc_item->data);
543+
desc_item->data = NULL;
544+
}*/
545+
}
546+
while (true);
547+
548+
return true;
549+
}
550+
388551
bool
389552
ECPGdeallocate_desc(int line, const char *name)
390553
{
@@ -425,6 +588,7 @@ ECPGallocate_desc(int line, const char *name)
425588
ECPGfree(new);
426589
return false;
427590
}
591+
new->items = NULL;
428592
new->result = PQmakeEmptyPGresult(NULL, 0);
429593
if (!new->result)
430594
{

src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 101 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.34 2004/06/27 12:28:40 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.35 2004/06/30 15:01:56 meskes Exp $ */
22

33
/*
44
* The aim is to get a simpler inteface to the database routines.
@@ -1026,6 +1026,9 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
10261026
free(str);
10271027
}
10281028
break;
1029+
1030+
case ECPGt_descriptor:
1031+
break;
10291032

10301033
default:
10311034
/* Not implemented yet */
@@ -1046,6 +1049,7 @@ ECPGexecute(struct statement * stmt)
10461049
PGresult *results;
10471050
PGnotify *notify;
10481051
struct variable *var;
1052+
int desc_counter = 0;
10491053

10501054
copiedquery = ECPGstrdup(stmt->command, stmt->lineno);
10511055

@@ -1056,64 +1060,116 @@ ECPGexecute(struct statement * stmt)
10561060
* so on.
10571061
*/
10581062
var = stmt->inlist;
1063+
10591064
while (var)
10601065
{
10611066
char *newcopy = NULL;
1062-
const char *tobeinserted = NULL;
1067+
const char *tobeinserted;
10631068
char *p;
1064-
bool malloced = FALSE;
1065-
int hostvarl = 0;
1066-
1067-
if (!ECPGstore_input(stmt, var, &tobeinserted, &malloced))
1068-
return false;
1069+
bool malloced = FALSE;
1070+
int hostvarl = 0;
10691071

1070-
/*
1071-
* Now tobeinserted points to an area that is to be inserted at
1072-
* the first %s
1073-
*/
1074-
if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
1075-
return false;
1076-
1077-
strcpy(newcopy, copiedquery);
1078-
if ((p = next_insert(newcopy + hostvarl)) == NULL)
1072+
tobeinserted = NULL;
1073+
/* A descriptor is a special case since it contains many variables but is listed only once. */
1074+
if (var->type == ECPGt_descriptor)
10791075
{
1080-
/*
1081-
* We have an argument but we dont have the matched up string
1082-
* in the string
1083-
*/
1084-
ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1085-
return false;
1076+
/* We create an additional variable list here, so the same logic applies. */
1077+
struct variable desc_inlist;
1078+
struct descriptor *desc;
1079+
struct descriptor_item *desc_item;
1080+
for (desc = all_descriptors; desc; desc = desc->next)
1081+
{
1082+
if (strcmp(var->pointer, desc->name) == 0)
1083+
break;
1084+
}
1085+
1086+
if (desc == NULL)
1087+
{
1088+
ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
1089+
return false;
1090+
}
1091+
1092+
desc_counter++;
1093+
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
1094+
{
1095+
if (desc_item->num == desc_counter)
1096+
{
1097+
desc_inlist.type = ECPGt_char;
1098+
desc_inlist.value = desc_item->data;
1099+
desc_inlist.pointer = &(desc_item->data);
1100+
desc_inlist.varcharsize = strlen(desc_item->data);
1101+
desc_inlist.arrsize = 1;
1102+
desc_inlist.offset = 0;
1103+
desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1104+
desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1105+
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1106+
1107+
if (!ECPGstore_input(stmt, &desc_inlist, &tobeinserted, &malloced))
1108+
return false;
1109+
1110+
break;
1111+
}
1112+
}
1113+
1114+
if (!desc_item) /* no more entries found in descriptor */
1115+
desc_counter = 0;
10861116
}
10871117
else
10881118
{
1089-
strcpy(p, tobeinserted);
1090-
hostvarl = strlen(newcopy);
1091-
1119+
if (!ECPGstore_input(stmt, var, &tobeinserted, &malloced))
1120+
return false;
1121+
}
1122+
if (tobeinserted)
1123+
{
10921124
/*
1093-
* The strange thing in the second argument is the rest of the
1094-
* string from the old string
1125+
* Now tobeinserted points to an area that is to be inserted at
1126+
* the first %s
10951127
*/
1096-
strcat(newcopy,
1097-
copiedquery
1098-
+ (p - newcopy)
1099-
+ sizeof("?") - 1 /* don't count the '\0' */ );
1100-
}
1128+
if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
1129+
return false;
11011130

1102-
/*
1103-
* Now everything is safely copied to the newcopy. Lets free the
1104-
* oldcopy and let the copiedquery get the var->value from the
1105-
* newcopy.
1106-
*/
1107-
if (malloced)
1108-
{
1109-
ECPGfree((char *) tobeinserted);
1110-
tobeinserted = NULL;
1111-
}
1131+
strcpy(newcopy, copiedquery);
1132+
if ((p = next_insert(newcopy + hostvarl)) == NULL)
1133+
{
1134+
/*
1135+
* We have an argument but we dont have the matched up string
1136+
* in the string
1137+
*/
1138+
ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1139+
return false;
1140+
}
1141+
else
1142+
{
1143+
strcpy(p, tobeinserted);
1144+
hostvarl = strlen(newcopy);
1145+
1146+
/*
1147+
* The strange thing in the second argument is the rest of the
1148+
* string from the old string
1149+
*/
1150+
strcat(newcopy,
1151+
copiedquery
1152+
+ (p - newcopy)
1153+
+ sizeof("?") - 1 /* don't count the '\0' */ );
1154+
}
11121155

1113-
ECPGfree(copiedquery);
1114-
copiedquery = newcopy;
1156+
/*
1157+
* Now everything is safely copied to the newcopy. Lets free the
1158+
* oldcopy and let the copiedquery get the var->value from the
1159+
* newcopy.
1160+
*/
1161+
if (malloced)
1162+
{
1163+
ECPGfree((char *) tobeinserted);
1164+
tobeinserted = NULL;
1165+
}
11151166

1116-
var = var->next;
1167+
ECPGfree(copiedquery);
1168+
copiedquery = newcopy;
1169+
}
1170+
1171+
if (desc_counter == 0)
1172+
var = var->next;
11171173
}
11181174

11191175
/* Check if there are unmatched things left. */

0 commit comments

Comments
 (0)