00001
00002
00003
00004
00005
00006 #define POSTGRES_ECPG_INTERNAL
00007 #include "postgres_fe.h"
00008 #include "pg_type.h"
00009
00010 #include "ecpg-pthread-win32.h"
00011 #include "ecpgtype.h"
00012 #include "ecpglib.h"
00013 #include "ecpgerrno.h"
00014 #include "extern.h"
00015 #include "sqlca.h"
00016 #include "sqlda.h"
00017 #include "sql3types.h"
00018
00019 static void descriptor_free(struct descriptor * desc);
00020
00021
00022 #ifdef ENABLE_THREAD_SAFETY
00023 static pthread_key_t descriptor_key;
00024 static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT;
00025
00026 static void descriptor_deallocate_all(struct descriptor * list);
00027
00028 static void
00029 descriptor_destructor(void *arg)
00030 {
00031 descriptor_deallocate_all(arg);
00032 }
00033
00034 static void
00035 descriptor_key_init(void)
00036 {
00037 pthread_key_create(&descriptor_key, descriptor_destructor);
00038 }
00039
00040 static struct descriptor *
00041 get_descriptors(void)
00042 {
00043 pthread_once(&descriptor_once, descriptor_key_init);
00044 return (struct descriptor *) pthread_getspecific(descriptor_key);
00045 }
00046
00047 static void
00048 set_descriptors(struct descriptor * value)
00049 {
00050 pthread_setspecific(descriptor_key, value);
00051 }
00052 #else
00053 static struct descriptor *all_descriptors = NULL;
00054
00055 #define get_descriptors() (all_descriptors)
00056 #define set_descriptors(value) do { all_descriptors = (value); } while(0)
00057 #endif
00058
00059
00060 static PGresult *
00061 ecpg_result_by_descriptor(int line, const char *name)
00062 {
00063 struct descriptor *desc = ecpg_find_desc(line, name);
00064
00065 if (desc == NULL)
00066 return NULL;
00067 return desc->result;
00068 }
00069
00070 static unsigned int
00071 ecpg_dynamic_type_DDT(Oid type)
00072 {
00073 switch (type)
00074 {
00075 case DATEOID:
00076 return SQL3_DDT_DATE;
00077 case TIMEOID:
00078 return SQL3_DDT_TIME;
00079 case TIMESTAMPOID:
00080 return SQL3_DDT_TIMESTAMP;
00081 case TIMESTAMPTZOID:
00082 return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
00083 case TIMETZOID:
00084 return SQL3_DDT_TIME_WITH_TIME_ZONE;
00085 default:
00086 return SQL3_DDT_ILLEGAL;
00087 }
00088 }
00089
00090 bool
00091 ECPGget_desc_header(int lineno, const char *desc_name, int *count)
00092 {
00093 PGresult *ECPGresult;
00094 struct sqlca_t *sqlca = ECPGget_sqlca();
00095
00096 ecpg_init_sqlca(sqlca);
00097 ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
00098 if (!ECPGresult)
00099 return false;
00100
00101 *count = PQnfields(ECPGresult);
00102 sqlca->sqlerrd[2] = 1;
00103 ecpg_log("ECPGget_desc_header: found %d attributes\n", *count);
00104 return true;
00105 }
00106
00107 static bool
00108 get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
00109 {
00110 switch (vartype)
00111 {
00112 case ECPGt_short:
00113 *(short *) var = (short) value;
00114 break;
00115 case ECPGt_int:
00116 *(int *) var = (int) value;
00117 break;
00118 case ECPGt_long:
00119 *(long *) var = (long) value;
00120 break;
00121 case ECPGt_unsigned_short:
00122 *(unsigned short *) var = (unsigned short) value;
00123 break;
00124 case ECPGt_unsigned_int:
00125 *(unsigned int *) var = (unsigned int) value;
00126 break;
00127 case ECPGt_unsigned_long:
00128 *(unsigned long *) var = (unsigned long) value;
00129 break;
00130 #ifdef HAVE_LONG_LONG_INT
00131 case ECPGt_long_long:
00132 *(long long int *) var = (long long int) value;
00133 break;
00134 case ECPGt_unsigned_long_long:
00135 *(unsigned long long int *) var = (unsigned long long int) value;
00136 break;
00137 #endif
00138 case ECPGt_float:
00139 *(float *) var = (float) value;
00140 break;
00141 case ECPGt_double:
00142 *(double *) var = (double) value;
00143 break;
00144 default:
00145 ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
00146 return (false);
00147 }
00148
00149 return (true);
00150 }
00151
00152 static bool
00153 set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
00154 {
00155 switch (vartype)
00156 {
00157 case ECPGt_short:
00158 *target = *(const short *) var;
00159 break;
00160 case ECPGt_int:
00161 *target = *(const int *) var;
00162 break;
00163 case ECPGt_long:
00164 *target = *(const long *) var;
00165 break;
00166 case ECPGt_unsigned_short:
00167 *target = *(const unsigned short *) var;
00168 break;
00169 case ECPGt_unsigned_int:
00170 *target = *(const unsigned int *) var;
00171 break;
00172 case ECPGt_unsigned_long:
00173 *target = *(const unsigned long *) var;
00174 break;
00175 #ifdef HAVE_LONG_LONG_INT
00176 case ECPGt_long_long:
00177 *target = *(const long long int *) var;
00178 break;
00179 case ECPGt_unsigned_long_long:
00180 *target = *(const unsigned long long int *) var;
00181 break;
00182 #endif
00183 case ECPGt_float:
00184 *target = *(const float *) var;
00185 break;
00186 case ECPGt_double:
00187 *target = *(const double *) var;
00188 break;
00189 default:
00190 ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
00191 return (false);
00192 }
00193
00194 return true;
00195 }
00196
00197 static bool
00198 get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
00199 {
00200 switch (vartype)
00201 {
00202 case ECPGt_char:
00203 case ECPGt_unsigned_char:
00204 case ECPGt_string:
00205 strncpy((char *) var, value, varcharsize);
00206 break;
00207 case ECPGt_varchar:
00208 {
00209 struct ECPGgeneric_varchar *variable =
00210 (struct ECPGgeneric_varchar *) var;
00211
00212 if (varcharsize == 0)
00213 strncpy(variable->arr, value, strlen(value));
00214 else
00215 strncpy(variable->arr, value, varcharsize);
00216
00217 variable->len = strlen(value);
00218 if (varcharsize > 0 && variable->len > varcharsize)
00219 variable->len = varcharsize;
00220 }
00221 break;
00222 default:
00223 ecpg_raise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
00224 return (false);
00225 }
00226
00227 return (true);
00228 }
00229
00230 #define RETURN_IF_NO_DATA if (ntuples < 1) \
00231 { \
00232 va_end(args); \
00233 ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
00234 return (false); \
00235 }
00236
00237 bool
00238 ECPGget_desc(int lineno, const char *desc_name, int index,...)
00239 {
00240 va_list args;
00241 PGresult *ECPGresult;
00242 enum ECPGdtype type;
00243 int ntuples,
00244 act_tuple;
00245 struct variable data_var;
00246 struct sqlca_t *sqlca = ECPGget_sqlca();
00247
00248 va_start(args, index);
00249 ecpg_init_sqlca(sqlca);
00250 ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
00251 if (!ECPGresult)
00252 {
00253 va_end(args);
00254 return (false);
00255 }
00256
00257 ntuples = PQntuples(ECPGresult);
00258
00259 if (index < 1 || index > PQnfields(ECPGresult))
00260 {
00261 ecpg_raise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
00262 va_end(args);
00263 return (false);
00264 }
00265
00266 ecpg_log("ECPGget_desc: reading items for tuple %d\n", index);
00267 --index;
00268
00269 type = va_arg(args, enum ECPGdtype);
00270
00271 memset(&data_var, 0, sizeof data_var);
00272 data_var.type = ECPGt_EORT;
00273 data_var.ind_type = ECPGt_NO_INDICATOR;
00274
00275 while (type != ECPGd_EODT)
00276 {
00277 char type_str[20];
00278 long varcharsize;
00279 long offset;
00280 long arrsize;
00281 enum ECPGttype vartype;
00282 void *var;
00283
00284 vartype = va_arg(args, enum ECPGttype);
00285 var = va_arg(args, void *);
00286 varcharsize = va_arg(args, long);
00287 arrsize = va_arg(args, long);
00288 offset = va_arg(args, long);
00289
00290 switch (type)
00291 {
00292 case (ECPGd_indicator):
00293 RETURN_IF_NO_DATA;
00294 data_var.ind_type = vartype;
00295 data_var.ind_pointer = var;
00296 data_var.ind_varcharsize = varcharsize;
00297 data_var.ind_arrsize = arrsize;
00298 data_var.ind_offset = offset;
00299 if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
00300 data_var.ind_value = *((void **) (data_var.ind_pointer));
00301 else
00302 data_var.ind_value = data_var.ind_pointer;
00303 break;
00304
00305 case ECPGd_data:
00306 RETURN_IF_NO_DATA;
00307 data_var.type = vartype;
00308 data_var.pointer = var;
00309 data_var.varcharsize = varcharsize;
00310 data_var.arrsize = arrsize;
00311 data_var.offset = offset;
00312 if (data_var.arrsize == 0 || data_var.varcharsize == 0)
00313 data_var.value = *((void **) (data_var.pointer));
00314 else
00315 data_var.value = data_var.pointer;
00316 break;
00317
00318 case ECPGd_name:
00319 if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
00320 {
00321 va_end(args);
00322 return (false);
00323 }
00324
00325 ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
00326 break;
00327
00328 case ECPGd_nullable:
00329 if (!get_int_item(lineno, var, vartype, 1))
00330 {
00331 va_end(args);
00332 return (false);
00333 }
00334
00335 break;
00336
00337 case ECPGd_key_member:
00338 if (!get_int_item(lineno, var, vartype, 0))
00339 {
00340 va_end(args);
00341 return (false);
00342 }
00343
00344 break;
00345
00346 case ECPGd_scale:
00347 if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
00348 {
00349 va_end(args);
00350 return (false);
00351 }
00352
00353 ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
00354 break;
00355
00356 case ECPGd_precision:
00357 if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
00358 {
00359 va_end(args);
00360 return (false);
00361 }
00362
00363 ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
00364 break;
00365
00366 case ECPGd_octet:
00367 if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
00368 {
00369 va_end(args);
00370 return (false);
00371 }
00372
00373 ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
00374 break;
00375
00376 case ECPGd_length:
00377 if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
00378 {
00379 va_end(args);
00380 return (false);
00381 }
00382
00383 ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
00384 break;
00385
00386 case ECPGd_type:
00387 if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type(PQftype(ECPGresult, index))))
00388 {
00389 va_end(args);
00390 return (false);
00391 }
00392
00393 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult, index)));
00394 break;
00395
00396 case ECPGd_di_code:
00397 if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type_DDT(PQftype(ECPGresult, index))))
00398 {
00399 va_end(args);
00400 return (false);
00401 }
00402
00403 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult, index)));
00404 break;
00405
00406 case ECPGd_cardinality:
00407 if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
00408 {
00409 va_end(args);
00410 return (false);
00411 }
00412
00413 ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
00414 break;
00415
00416 case ECPGd_ret_length:
00417 case ECPGd_ret_octet:
00418
00419 RETURN_IF_NO_DATA;
00420
00421
00422
00423
00424 if (arrsize > 0 && ntuples > arrsize)
00425 {
00426 ecpg_log("ECPGget_desc on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
00427 lineno, ntuples, arrsize);
00428 ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
00429 va_end(args);
00430 return false;
00431 }
00432
00433 if (arrsize == 0 && *(void **) var == NULL)
00434 {
00435 void *mem = (void *) ecpg_alloc(offset * ntuples, lineno);
00436
00437 if (!mem)
00438 {
00439 va_end(args);
00440 return false;
00441 }
00442 *(void **) var = mem;
00443 ecpg_add_mem(mem, lineno);
00444 var = mem;
00445 }
00446
00447 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
00448 {
00449 if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
00450 {
00451 va_end(args);
00452 return (false);
00453 }
00454 var = (char *) var + offset;
00455 ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
00456 }
00457 break;
00458
00459 default:
00460 snprintf(type_str, sizeof(type_str), "%d", type);
00461 ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
00462 va_end(args);
00463 return (false);
00464 }
00465
00466 type = va_arg(args, enum ECPGdtype);
00467 }
00468
00469 if (data_var.type != ECPGt_EORT)
00470 {
00471 struct statement stmt;
00472 char *oldlocale;
00473
00474
00475
00476 oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
00477 setlocale(LC_NUMERIC, "C");
00478
00479 memset(&stmt, 0, sizeof stmt);
00480 stmt.lineno = lineno;
00481
00482
00483 stmt.connection = ecpg_get_connection(NULL);
00484 ecpg_store_result(ECPGresult, index, &stmt, &data_var);
00485
00486 setlocale(LC_NUMERIC, oldlocale);
00487 ecpg_free(oldlocale);
00488 }
00489 else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
00490
00491
00492
00493
00494
00495
00496 {
00497
00498
00499
00500
00501 if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
00502 {
00503 ecpg_log("ECPGget_desc on line %d: incorrect number of matches (indicator); %d don't fit into array of %ld\n",
00504 lineno, ntuples, data_var.ind_arrsize);
00505 ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
00506 va_end(args);
00507 return false;
00508 }
00509
00510
00511 if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL)
00512 {
00513 void *mem = (void *) ecpg_alloc(data_var.ind_offset * ntuples, lineno);
00514
00515 if (!mem)
00516 {
00517 va_end(args);
00518 return false;
00519 }
00520 *(void **) data_var.ind_pointer = mem;
00521 ecpg_add_mem(mem, lineno);
00522 data_var.ind_value = mem;
00523 }
00524
00525 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
00526 {
00527 if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
00528 {
00529 va_end(args);
00530 return (false);
00531 }
00532 data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
00533 ecpg_log("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
00534 }
00535 }
00536 sqlca->sqlerrd[2] = ntuples;
00537 va_end(args);
00538 return (true);
00539 }
00540
00541 #undef RETURN_IF_NO_DATA
00542
00543 bool
00544 ECPGset_desc_header(int lineno, const char *desc_name, int count)
00545 {
00546 struct descriptor *desc = ecpg_find_desc(lineno, desc_name);
00547
00548 if (desc == NULL)
00549 return false;
00550 desc->count = count;
00551 return true;
00552 }
00553
00554 bool
00555 ECPGset_desc(int lineno, const char *desc_name, int index,...)
00556 {
00557 va_list args;
00558 struct descriptor *desc;
00559 struct descriptor_item *desc_item;
00560 struct variable *var;
00561
00562 desc = ecpg_find_desc(lineno, desc_name);
00563 if (desc == NULL)
00564 return false;
00565
00566 for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
00567 {
00568 if (desc_item->num == index)
00569 break;
00570 }
00571
00572 if (desc_item == NULL)
00573 {
00574 desc_item = (struct descriptor_item *) ecpg_alloc(sizeof(*desc_item), lineno);
00575 if (!desc_item)
00576 return false;
00577 desc_item->num = index;
00578 if (desc->count < index)
00579 desc->count = index;
00580 desc_item->next = desc->items;
00581 desc->items = desc_item;
00582 }
00583
00584 if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
00585 return false;
00586
00587 va_start(args, index);
00588
00589 for (;;)
00590 {
00591 enum ECPGdtype itemtype;
00592 char *tobeinserted = NULL;
00593
00594 itemtype = va_arg(args, enum ECPGdtype);
00595
00596 if (itemtype == ECPGd_EODT)
00597 break;
00598
00599 var->type = va_arg(args, enum ECPGttype);
00600 var->pointer = va_arg(args, char *);
00601
00602 var->varcharsize = va_arg(args, long);
00603 var->arrsize = va_arg(args, long);
00604 var->offset = va_arg(args, long);
00605
00606 if (var->arrsize == 0 || var->varcharsize == 0)
00607 var->value = *((char **) (var->pointer));
00608 else
00609 var->value = var->pointer;
00610
00611
00612
00613
00614
00615 if (var->arrsize < 0)
00616 var->arrsize = 0;
00617 if (var->varcharsize < 0)
00618 var->varcharsize = 0;
00619
00620 var->next = NULL;
00621
00622 switch (itemtype)
00623 {
00624 case ECPGd_data:
00625 {
00626 if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
00627 {
00628 ecpg_free(var);
00629 va_end(args);
00630 return false;
00631 }
00632
00633 ecpg_free(desc_item->data);
00634
00635 desc_item->data = (char *) tobeinserted;
00636 tobeinserted = NULL;
00637 break;
00638 }
00639
00640 case ECPGd_indicator:
00641 set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
00642 break;
00643
00644 case ECPGd_length:
00645 set_int_item(lineno, &desc_item->length, var->pointer, var->type);
00646 break;
00647
00648 case ECPGd_precision:
00649 set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
00650 break;
00651
00652 case ECPGd_scale:
00653 set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
00654 break;
00655
00656 case ECPGd_type:
00657 set_int_item(lineno, &desc_item->type, var->pointer, var->type);
00658 break;
00659
00660 default:
00661 {
00662 char type_str[20];
00663
00664 snprintf(type_str, sizeof(type_str), "%d", itemtype);
00665 ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
00666 ecpg_free(var);
00667 va_end(args);
00668 return false;
00669 }
00670 }
00671 }
00672 ecpg_free(var);
00673 va_end(args);
00674
00675 return true;
00676 }
00677
00678
00679 static void
00680 descriptor_free(struct descriptor * desc)
00681 {
00682 struct descriptor_item *desc_item;
00683
00684 for (desc_item = desc->items; desc_item;)
00685 {
00686 struct descriptor_item *di;
00687
00688 ecpg_free(desc_item->data);
00689 di = desc_item;
00690 desc_item = desc_item->next;
00691 ecpg_free(di);
00692 }
00693
00694 ecpg_free(desc->name);
00695 PQclear(desc->result);
00696 ecpg_free(desc);
00697 }
00698
00699 bool
00700 ECPGdeallocate_desc(int line, const char *name)
00701 {
00702 struct descriptor *desc;
00703 struct descriptor *prev;
00704 struct sqlca_t *sqlca = ECPGget_sqlca();
00705
00706 ecpg_init_sqlca(sqlca);
00707 for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
00708 {
00709 if (strcmp(name, desc->name) == 0)
00710 {
00711 if (prev)
00712 prev->next = desc->next;
00713 else
00714 set_descriptors(desc->next);
00715 descriptor_free(desc);
00716 return true;
00717 }
00718 }
00719 ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
00720 return false;
00721 }
00722
00723 #ifdef ENABLE_THREAD_SAFETY
00724
00725
00726 static void
00727 descriptor_deallocate_all(struct descriptor * list)
00728 {
00729 while (list)
00730 {
00731 struct descriptor *next = list->next;
00732
00733 descriptor_free(list);
00734 list = next;
00735 }
00736 }
00737 #endif
00738
00739 bool
00740 ECPGallocate_desc(int line, const char *name)
00741 {
00742 struct descriptor *new;
00743 struct sqlca_t *sqlca = ECPGget_sqlca();
00744
00745 ecpg_init_sqlca(sqlca);
00746 new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
00747 if (!new)
00748 return false;
00749 new->next = get_descriptors();
00750 new->name = ecpg_alloc(strlen(name) + 1, line);
00751 if (!new->name)
00752 {
00753 ecpg_free(new);
00754 return false;
00755 }
00756 new->count = -1;
00757 new->items = NULL;
00758 new->result = PQmakeEmptyPGresult(NULL, 0);
00759 if (!new->result)
00760 {
00761 ecpg_free(new->name);
00762 ecpg_free(new);
00763 ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
00764 return false;
00765 }
00766 strcpy(new->name, name);
00767 set_descriptors(new);
00768 return true;
00769 }
00770
00771
00772 struct descriptor *
00773 ecpg_find_desc(int line, const char *name)
00774 {
00775 struct descriptor *desc;
00776
00777 for (desc = get_descriptors(); desc; desc = desc->next)
00778 {
00779 if (strcmp(name, desc->name) == 0)
00780 return desc;
00781 }
00782
00783 ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
00784 return NULL;
00785 }
00786
00787 bool
00788 ECPGdescribe(int line, int compat, bool input, const char *connection_name, const char *stmt_name,...)
00789 {
00790 bool ret = false;
00791 struct connection *con;
00792 struct prepared_statement *prep;
00793 PGresult *res;
00794 va_list args;
00795
00796
00797 if (input)
00798 {
00799 ecpg_raise(line, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, "DESCRIBE INPUT");
00800 return ret;
00801 }
00802
00803 con = ecpg_get_connection(connection_name);
00804 if (!con)
00805 {
00806 ecpg_raise(line, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
00807 connection_name ? connection_name : ecpg_gettext("NULL"));
00808 return ret;
00809 }
00810 prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
00811 if (!prep)
00812 {
00813 ecpg_raise(line, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt_name);
00814 return ret;
00815 }
00816
00817 va_start(args, stmt_name);
00818
00819 for (;;)
00820 {
00821 enum ECPGttype type;
00822 void *ptr;
00823
00824
00825 type = va_arg(args, enum ECPGttype);
00826
00827 if (type == ECPGt_EORT)
00828 break;
00829
00830
00831 ptr = va_arg(args, void *);
00832 (void) va_arg(args, long);
00833 (void) va_arg(args, long);
00834 (void) va_arg(args, long);
00835
00836
00837 (void) va_arg(args, enum ECPGttype);
00838 (void) va_arg(args, void *);
00839 (void) va_arg(args, long);
00840 (void) va_arg(args, long);
00841 (void) va_arg(args, long);
00842
00843 switch (type)
00844 {
00845 case ECPGt_descriptor:
00846 {
00847 char *name = ptr;
00848 struct descriptor *desc = ecpg_find_desc(line, name);
00849
00850 if (desc == NULL)
00851 break;
00852
00853 res = PQdescribePrepared(con->connection, stmt_name);
00854 if (!ecpg_check_PQresult(res, line, con->connection, compat))
00855 break;
00856
00857 if (desc->result != NULL)
00858 PQclear(desc->result);
00859
00860 desc->result = res;
00861 ret = true;
00862 break;
00863 }
00864 case ECPGt_sqlda:
00865 {
00866 if (INFORMIX_MODE(compat))
00867 {
00868 struct sqlda_compat **_sqlda = ptr;
00869 struct sqlda_compat *sqlda;
00870
00871 res = PQdescribePrepared(con->connection, stmt_name);
00872 if (!ecpg_check_PQresult(res, line, con->connection, compat))
00873 break;
00874
00875 sqlda = ecpg_build_compat_sqlda(line, res, -1, compat);
00876 if (sqlda)
00877 {
00878 struct sqlda_compat *sqlda_old = *_sqlda;
00879 struct sqlda_compat *sqlda_old1;
00880
00881 while (sqlda_old)
00882 {
00883 sqlda_old1 = sqlda_old->desc_next;
00884 free(sqlda_old);
00885 sqlda_old = sqlda_old1;
00886 }
00887
00888 *_sqlda = sqlda;
00889 ret = true;
00890 }
00891
00892 PQclear(res);
00893 }
00894 else
00895 {
00896 struct sqlda_struct **_sqlda = ptr;
00897 struct sqlda_struct *sqlda;
00898
00899 res = PQdescribePrepared(con->connection, stmt_name);
00900 if (!ecpg_check_PQresult(res, line, con->connection, compat))
00901 break;
00902
00903 sqlda = ecpg_build_native_sqlda(line, res, -1, compat);
00904 if (sqlda)
00905 {
00906 struct sqlda_struct *sqlda_old = *_sqlda;
00907 struct sqlda_struct *sqlda_old1;
00908
00909 while (sqlda_old)
00910 {
00911 sqlda_old1 = sqlda_old->desc_next;
00912 free(sqlda_old);
00913 sqlda_old = sqlda_old1;
00914 }
00915
00916 *_sqlda = sqlda;
00917 ret = true;
00918 }
00919
00920 PQclear(res);
00921 }
00922 break;
00923 }
00924 default:
00925
00926 ;
00927 }
00928 }
00929
00930 va_end(args);
00931
00932 return ret;
00933 }