ecpglib.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:33k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /* Copyright comment */
  2. /*
  3.  * The aim is to get a simpler inteface to the database routines.
  4.  * All the tidieous messing around with tuples is supposed to be hidden
  5.  * by this function.
  6.  */
  7. /* Author: Linus Tolke
  8.    (actually most if the code is "borrowed" from the distribution and just
  9.    slightly modified)
  10.  */
  11. /* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
  12.    on Feb. 5th, 1998 */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include <stdarg.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <libpq-fe.h>
  20. #include <libpq/pqcomm.h>
  21. #include <ecpgtype.h>
  22. #include <ecpglib.h>
  23. #include <sqlca.h>
  24. /* variables visible to the programs */
  25. static struct sqlca sqlca_init =
  26. {
  27. {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
  28. sizeof(struct sqlca),
  29. 0,
  30. {0, {0}},
  31. {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
  32. {0, 0, 0, 0, 0, 0},
  33. {0, 0, 0, 0, 0, 0, 0, 0},
  34. {0, 0, 0, 0, 0, 0, 0, 0}
  35. };
  36. struct sqlca sqlca =
  37. {
  38. {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
  39. sizeof(struct sqlca),
  40. 0,
  41. {0, {0}},
  42. {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
  43. {0, 0, 0, 0, 0, 0},
  44. {0, 0, 0, 0, 0, 0, 0, 0},
  45. {0, 0, 0, 0, 0, 0, 0, 0}
  46. };
  47. static struct connection
  48. {
  49. char    *name;
  50. PGconn    *connection;
  51. bool committed;
  52. int autocommit;
  53. struct connection *next;
  54. }    *all_connections = NULL, *actual_connection = NULL;
  55. struct variable
  56. {
  57. enum ECPGttype type;
  58. void    *value;
  59. void    *pointer;
  60. long varcharsize;
  61. long arrsize;
  62. long offset;
  63. enum ECPGttype ind_type;
  64. void    *ind_value;
  65. long ind_varcharsize;
  66. long ind_arrsize;
  67. long ind_offset;
  68. struct variable *next;
  69. };
  70. struct statement
  71. {
  72. int lineno;
  73. char    *command;
  74. struct connection *connection;
  75. struct variable *inlist;
  76. struct variable *outlist;
  77. };
  78. struct prepared_statement
  79. {
  80. char    *name;
  81. struct statement *stmt;
  82. struct prepared_statement *next;
  83. }    *prep_stmts = NULL;
  84. struct auto_mem
  85. {
  86. void    *pointer;
  87. struct auto_mem *next;
  88. }    *auto_allocs = NULL;
  89. static int simple_debug = 0;
  90. static FILE *debugstream = NULL;
  91. static void
  92. register_error(long code, char *fmt,...)
  93. {
  94. va_list args;
  95. struct auto_mem *am;
  96. sqlca.sqlcode = code;
  97. va_start(args, fmt);
  98. vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);
  99. va_end(args);
  100. sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
  101. /* free all memory we have allocated for the user */
  102. for (am = auto_allocs; am;)
  103. {
  104. struct auto_mem *act = am;
  105. am = am->next;
  106. free(act->pointer);
  107. free(act);
  108. }
  109. auto_allocs = NULL;
  110. }
  111. static struct connection *
  112. get_connection(const char *connection_name)
  113. {
  114. struct connection *con = all_connections;
  115. if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
  116. return actual_connection;
  117. for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
  118. if (con)
  119. return con;
  120. else
  121. return NULL;
  122. }
  123. static void
  124. ECPGfinish(struct connection * act)
  125. {
  126. if (act != NULL)
  127. {
  128. ECPGlog("ECPGfinish: finishing %s.n", act->name);
  129. PQfinish(act->connection);
  130. /* remove act from the list */
  131. if (act == all_connections)
  132. all_connections = act->next;
  133. else
  134. {
  135. struct connection *con;
  136. for (con = all_connections; con->next && con->next != act; con = con->next);
  137. if (con->next)
  138. con->next = act->next;
  139. }
  140. if (actual_connection == act)
  141. actual_connection = all_connections;
  142. free(act->name);
  143. free(act);
  144. }
  145. else
  146. ECPGlog("ECPGfinish: called an extra time.n");
  147. }
  148. static char *
  149. ecpg_alloc(long size, int lineno)
  150. {
  151. char    *new = (char *) calloc(1L, size);
  152. if (!new)
  153. {
  154. ECPGlog("out of memoryn");
  155. register_error(ECPG_OUT_OF_MEMORY, "Out of memory in line %d", lineno);
  156. return NULL;
  157. }
  158. memset(new, '', size);
  159. return (new);
  160. }
  161. static char *
  162. ecpg_strdup(const char *string, int lineno)
  163. {
  164. char    *new = strdup(string);
  165. if (!new)
  166. {
  167. ECPGlog("out of memoryn");
  168. register_error(ECPG_OUT_OF_MEMORY, "Out of memory in line %d", lineno);
  169. return NULL;
  170. }
  171. return (new);
  172. }
  173. static void
  174. add_mem(void *ptr, int lineno)
  175. {
  176. struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
  177. am->next = auto_allocs;
  178. auto_allocs = am;
  179. }
  180. /* This function returns a newly malloced string that has the ' and 
  181.    in the argument quoted with .
  182.  */
  183. static
  184. char *
  185. quote_postgres(char *arg, int lineno)
  186. {
  187. char    *res = (char *) ecpg_alloc(2 * strlen(arg) + 1, lineno);
  188. int i,
  189. ri;
  190. if (!res)
  191. return (res);
  192. for (i = 0, ri = 0; arg[i]; i++, ri++)
  193. {
  194. switch (arg[i])
  195. {
  196. case ''':
  197. case '\':
  198. res[ri++] = '\';
  199. default:
  200. ;
  201. }
  202. res[ri] = arg[i];
  203. }
  204. res[ri] = '';
  205. return res;
  206. }
  207. /*
  208.  * create a list of variables
  209.  * The variables are listed with input variables preceeding outputvariables
  210.  * The end of each group is marked by an end marker.
  211.  * per variable we list:
  212.  * type - as defined in ecpgtype.h
  213.  * value - where to store the data
  214.  * varcharsize - length of string in case we have a stringvariable, else 0
  215.  * arraysize - 0 for pointer (we don't know the size of the array),
  216.  * 1 for simple variable, size for arrays
  217.  * offset - offset between ith and (i+1)th entry in an array,
  218.  * normally that means sizeof(type)
  219.  * ind_type - type of indicator variable
  220.  * ind_value - pointer to indicator variable
  221.  * ind_varcharsize - empty
  222.  * ind_arraysize - arraysize of indicator array
  223.  * ind_offset - indicator offset
  224.  */
  225. static bool
  226. create_statement(int lineno, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
  227. {
  228. struct variable **list = &((*stmt)->inlist);
  229. enum ECPGttype type;
  230. if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
  231. return false;
  232. (*stmt)->command = query;
  233. (*stmt)->connection = connection;
  234. (*stmt)->lineno = lineno;
  235. list = &((*stmt)->inlist);
  236. type = va_arg(ap, enum ECPGttype);
  237. while (type != ECPGt_EORT)
  238. {
  239. if (type == ECPGt_EOIT)
  240. list = &((*stmt)->outlist);
  241. else
  242. {
  243. struct variable *var,
  244.    *ptr;
  245. if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
  246. return false;
  247. var->type = type;
  248. var->pointer = va_arg(ap, void *);
  249. /* if variable is NULL, the statement hasn't been prepared */
  250. if (var->pointer == NULL)
  251. {
  252. ECPGlog("create_statement: invalid statement namen");
  253. register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d.", lineno);
  254. free(var);
  255. return false;
  256. }
  257. var->varcharsize = va_arg(ap, long);
  258. var->arrsize = va_arg(ap, long);
  259. var->offset = va_arg(ap, long);
  260. if (var->arrsize == 0 || var->varcharsize == 0)
  261. var->value = *((void **) (var->pointer));
  262. else
  263. var->value = var->pointer;
  264. var->ind_type = va_arg(ap, enum ECPGttype);
  265. var->ind_value = va_arg(ap, void *);
  266. var->ind_varcharsize = va_arg(ap, long);
  267. var->ind_arrsize = va_arg(ap, long);
  268. var->ind_offset = va_arg(ap, long);
  269. var->next = NULL;
  270. for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
  271. if (ptr == NULL)
  272. *list = var;
  273. else
  274. ptr->next = var;
  275. }
  276. type = va_arg(ap, enum ECPGttype);
  277. }
  278. return (true);
  279. }
  280. static void
  281. free_variable(struct variable * var)
  282. {
  283. struct variable *var_next;
  284. if (var == (struct variable *) NULL)
  285. return;
  286. var_next = var->next;
  287. free(var);
  288. while (var_next)
  289. {
  290. var = var_next;
  291. var_next = var->next;
  292. free(var);
  293. }
  294. }
  295. static void
  296. free_statement(struct statement * stmt)
  297. {
  298. if (stmt == (struct statement *) NULL)
  299. return;
  300. free_variable(stmt->inlist);
  301. free_variable(stmt->outlist);
  302. free(stmt);
  303. }
  304. static char *
  305. next_insert(char *text)
  306. {
  307. char    *ptr = text;
  308. bool string = false;
  309. for (; *ptr != '' && (*ptr != '?' || string); ptr++)
  310. if (*ptr == ''')
  311. string = string ? false : true;
  312. return (*ptr == '') ? NULL : ptr;
  313. }
  314. static bool
  315. ECPGexecute(struct statement * stmt)
  316. {
  317. bool status = false;
  318. char    *copiedquery;
  319. PGresult   *results;
  320. PGnotify   *notify;
  321. struct variable *var;
  322. memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
  323. copiedquery = ecpg_strdup(stmt->command, stmt->lineno);
  324. /*
  325.  * Now, if the type is one of the fill in types then we take the
  326.  * argument and enter that in the string at the first %s position.
  327.  * Then if there are any more fill in types we fill in at the next and
  328.  * so on.
  329.  */
  330. var = stmt->inlist;
  331. while (var)
  332. {
  333. char    *newcopy;
  334. char    *mallocedval = NULL;
  335. char    *tobeinserted = NULL;
  336. char    *p;
  337. char buff[20];
  338. /*
  339.  * Some special treatment is needed for records since we want
  340.  * their contents to arrive in a comma-separated list on insert (I
  341.  * think).
  342.  */
  343. buff[0] = '';
  344. /* check for null value and set input buffer accordingly */
  345. switch (var->ind_type)
  346. {
  347. case ECPGt_short:
  348. case ECPGt_unsigned_short:
  349. if (*(short *) var->ind_value < 0)
  350. strcpy(buff, "null");
  351. break;
  352. case ECPGt_int:
  353. case ECPGt_unsigned_int:
  354. if (*(int *) var->ind_value < 0)
  355. strcpy(buff, "null");
  356. break;
  357. case ECPGt_long:
  358. case ECPGt_unsigned_long:
  359. if (*(long *) var->ind_value < 0L)
  360. strcpy(buff, "null");
  361. break;
  362. default:
  363. break;
  364. }
  365. if (*buff == '')
  366. {
  367. switch (var->type)
  368. {
  369. case ECPGt_short:
  370. sprintf(buff, "%d", *(short *) var->value);
  371. tobeinserted = buff;
  372. break;
  373. case ECPGt_int:
  374. sprintf(buff, "%d", *(int *) var->value);
  375. tobeinserted = buff;
  376. break;
  377. case ECPGt_unsigned_short:
  378. sprintf(buff, "%d", *(unsigned short *) var->value);
  379. tobeinserted = buff;
  380. break;
  381. case ECPGt_unsigned_int:
  382. sprintf(buff, "%d", *(unsigned int *) var->value);
  383. tobeinserted = buff;
  384. break;
  385. case ECPGt_long:
  386. sprintf(buff, "%ld", *(long *) var->value);
  387. tobeinserted = buff;
  388. break;
  389. case ECPGt_unsigned_long:
  390. sprintf(buff, "%ld", *(unsigned long *) var->value);
  391. tobeinserted = buff;
  392. break;
  393. case ECPGt_float:
  394. sprintf(buff, "%.14g", *(float *) var->value);
  395. tobeinserted = buff;
  396. break;
  397. case ECPGt_double:
  398. sprintf(buff, "%.14g", *(double *) var->value);
  399. tobeinserted = buff;
  400. break;
  401. case ECPGt_bool:
  402. sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
  403. tobeinserted = buff;
  404. break;
  405. case ECPGt_char:
  406. case ECPGt_unsigned_char:
  407. {
  408. /* set slen to string length if type is char * */
  409. int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
  410. char    *tmp;
  411. if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
  412. return false;
  413. strncpy(newcopy, (char *) var->value, slen);
  414. newcopy[slen] = '';
  415. if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
  416. return false;
  417. strcpy(mallocedval, "'");
  418. tmp = quote_postgres(newcopy, stmt->lineno);
  419. if (!tmp)
  420. return false;
  421. strcat(mallocedval, tmp);
  422. strcat(mallocedval, "'");
  423. free(newcopy);
  424. tobeinserted = mallocedval;
  425. }
  426. break;
  427. case ECPGt_char_variable:
  428. {
  429. int slen = strlen((char *) var->value);
  430. char    *tmp;
  431. if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
  432. return false;
  433. strncpy(newcopy, (char *) var->value, slen);
  434. newcopy[slen] = '';
  435. tobeinserted = newcopy;
  436. }
  437. break;
  438. case ECPGt_varchar:
  439. {
  440. struct ECPGgeneric_varchar *variable =
  441. (struct ECPGgeneric_varchar *) (var->value);
  442. char    *tmp;
  443. if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, stmt->lineno)))
  444. return false;
  445. strncpy(newcopy, variable->arr, variable->len);
  446. newcopy[variable->len] = '';
  447. if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
  448. return false;
  449. strcpy(mallocedval, "'");
  450. tmp = quote_postgres(newcopy, stmt->lineno);
  451. if (!tmp)
  452. return false;
  453. strcat(mallocedval, tmp);
  454. strcat(mallocedval, "'");
  455. free(newcopy);
  456. tobeinserted = mallocedval;
  457. }
  458. break;
  459. default:
  460. /* Not implemented yet */
  461. register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
  462.  ECPGtype_name(var->type), stmt->lineno);
  463. return false;
  464. break;
  465. }
  466. }
  467. else
  468. tobeinserted = buff;
  469. /*
  470.  * Now tobeinserted points to an area that is to be inserted at
  471.  * the first %s
  472.  */
  473. if (!(newcopy = (char *) ecpg_alloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
  474. return false;
  475. strcpy(newcopy, copiedquery);
  476. if ((p = next_insert(newcopy)) == NULL)
  477. {
  478. /*
  479.  * We have an argument but we dont have the matched up string
  480.  * in the string
  481.  */
  482. register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
  483. return false;
  484. }
  485. else
  486. {
  487. strcpy(p, tobeinserted);
  488. /*
  489.  * The strange thing in the second argument is the rest of the
  490.  * string from the old string
  491.  */
  492. strcat(newcopy,
  493.    copiedquery
  494.    + (p - newcopy)
  495.    + sizeof("?") - 1 /* don't count the '' */ );
  496. }
  497. /*
  498.  * Now everything is safely copied to the newcopy. Lets free the
  499.  * oldcopy and let the copiedquery get the var->value from the
  500.  * newcopy.
  501.  */
  502. if (mallocedval != NULL)
  503. {
  504. free(mallocedval);
  505. mallocedval = NULL;
  506. }
  507. free(copiedquery);
  508. copiedquery = newcopy;
  509. var = var->next;
  510. }
  511. /* Check if there are unmatched things left. */
  512. if (next_insert(copiedquery) != NULL)
  513. {
  514. register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
  515. return false;
  516. }
  517. /* Now the request is built. */
  518. if (stmt->connection->committed && !stmt->connection->autocommit)
  519. {
  520. if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
  521. {
  522. register_error(ECPG_TRANS, "Error in transaction processing line %d.", stmt->lineno);
  523. return false;
  524. }
  525. PQclear(results);
  526. stmt->connection->committed = false;
  527. }
  528. ECPGlog("ECPGexecute line %d: QUERY: %s on connection %sn", stmt->lineno, copiedquery, stmt->connection->name);
  529. results = PQexec(stmt->connection->connection, copiedquery);
  530. free(copiedquery);
  531. if (results == NULL)
  532. {
  533. ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
  534. PQerrorMessage(stmt->connection->connection));
  535. register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
  536.  PQerrorMessage(stmt->connection->connection), stmt->lineno);
  537. }
  538. else
  539. {
  540. sqlca.sqlerrd[2] = 0;
  541. var = stmt->outlist;
  542. switch (PQresultStatus(results))
  543. {
  544. int nfields,
  545. ntuples,
  546. act_tuple,
  547. act_field;
  548. case PGRES_TUPLES_OK:
  549. nfields = PQnfields(results);
  550. sqlca.sqlerrd[2] = ntuples = PQntuples(results);
  551. status = true;
  552. if (ntuples < 1)
  553. {
  554. ECPGlog("ECPGexecute line %d: Incorrect number of matches: %dn",
  555. stmt->lineno, ntuples);
  556. register_error(ECPG_NOT_FOUND, "No data found line %d.", stmt->lineno);
  557. status = false;
  558. break;
  559. }
  560. for (act_field = 0; act_field < nfields && status; act_field++)
  561. {
  562. char    *pval;
  563. char    *scan_length;
  564. if (var == NULL)
  565. {
  566. ECPGlog("ECPGexecute line %d: Too few arguments.n", stmt->lineno);
  567. register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
  568. return (false);
  569. }
  570. /*
  571.  * if we don't have enough space, we cannot read all
  572.  * tuples
  573.  */
  574. if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
  575. {
  576. ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %dn",
  577. stmt->lineno, ntuples, var->arrsize);
  578. register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", stmt->lineno);
  579. status = false;
  580. break;
  581. }
  582. /*
  583.  * allocate memory for NULL pointers
  584.  */
  585. if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
  586. {
  587. int len = 0;
  588. switch (var->type)
  589. {
  590. case ECPGt_char:
  591. case ECPGt_unsigned_char:
  592. var->varcharsize = 0;
  593. /* check strlen for each tuple */
  594. for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
  595. {
  596. int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
  597. if (len > var->varcharsize)
  598. var->varcharsize = len;
  599. }
  600. var->offset *= var->varcharsize;
  601. len = var->offset * ntuples;
  602. break;
  603. case ECPGt_varchar:
  604. len = ntuples * (var->varcharsize + sizeof(int));
  605. break;
  606. default:
  607. len = var->offset * ntuples;
  608. break;
  609. }
  610. var->value = (void *) ecpg_alloc(len, stmt->lineno);
  611. *((void **) var->pointer) = var->value;
  612. add_mem(var->value, stmt->lineno);
  613. }
  614. for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
  615. {
  616. pval = PQgetvalue(results, act_tuple, act_field);
  617. ECPGlog("ECPGexecute line %d: RESULT: %sn", stmt->lineno, pval ? pval : "");
  618. /* Now the pval is a pointer to the value. */
  619. /* We will have to decode the value */
  620. /*
  621.  * check for null value and set indicator
  622.  * accordingly
  623.  */
  624. switch (var->ind_type)
  625. {
  626. case ECPGt_short:
  627. case ECPGt_unsigned_short:
  628. ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
  629. break;
  630. case ECPGt_int:
  631. case ECPGt_unsigned_int:
  632. ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
  633. break;
  634. case ECPGt_long:
  635. case ECPGt_unsigned_long:
  636. ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
  637. break;
  638. default:
  639. break;
  640. }
  641. switch (var->type)
  642. {
  643. long res;
  644. unsigned long ures;
  645. double dres;
  646. case ECPGt_short:
  647. case ECPGt_int:
  648. case ECPGt_long:
  649. if (pval)
  650. {
  651. res = strtol(pval, &scan_length, 10);
  652. if (*scan_length != '') /* Garbage left */
  653. {
  654. register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
  655.  pval, stmt->lineno);
  656. status = false;
  657. res = 0L;
  658. }
  659. }
  660. else
  661. res = 0L;
  662. /* Again?! Yes */
  663. switch (var->type)
  664. {
  665. case ECPGt_short:
  666. ((short *) var->value)[act_tuple] = (short) res;
  667. break;
  668. case ECPGt_int:
  669. ((int *) var->value)[act_tuple] = (int) res;
  670. break;
  671. case ECPGt_long:
  672. ((long *) var->value)[act_tuple] = res;
  673. break;
  674. default:
  675. /* Cannot happen */
  676. break;
  677. }
  678. break;
  679. case ECPGt_unsigned_short:
  680. case ECPGt_unsigned_int:
  681. case ECPGt_unsigned_long:
  682. if (pval)
  683. {
  684. ures = strtoul(pval, &scan_length, 10);
  685. if (*scan_length != '') /* Garbage left */
  686. {
  687. register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
  688.  pval, stmt->lineno);
  689. status = false;
  690. ures = 0L;
  691. }
  692. }
  693. else
  694. ures = 0L;
  695. /* Again?! Yes */
  696. switch (var->type)
  697. {
  698. case ECPGt_unsigned_short:
  699. ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
  700. break;
  701. case ECPGt_unsigned_int:
  702. ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
  703. break;
  704. case ECPGt_unsigned_long:
  705. ((unsigned long *) var->value)[act_tuple] = ures;
  706. break;
  707. default:
  708. /* Cannot happen */
  709. break;
  710. }
  711. break;
  712. case ECPGt_float:
  713. case ECPGt_double:
  714. if (pval)
  715. {
  716. dres = strtod(pval, &scan_length);
  717. if (*scan_length != '') /* Garbage left */
  718. {
  719. register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
  720.  pval, stmt->lineno);
  721. status = false;
  722. dres = 0.0;
  723. }
  724. }
  725. else
  726. dres = 0.0;
  727. /* Again?! Yes */
  728. switch (var->type)
  729. {
  730. case ECPGt_float:
  731. ((float *) var->value)[act_tuple] = dres;
  732. break;
  733. case ECPGt_double:
  734. ((double *) var->value)[act_tuple] = dres;
  735. break;
  736. default:
  737. /* Cannot happen */
  738. break;
  739. }
  740. break;
  741. case ECPGt_bool:
  742. if (pval)
  743. {
  744. if (pval[0] == 'f' && pval[1] == '')
  745. {
  746. ((char *) var->value)[act_tuple] = false;
  747. break;
  748. }
  749. else if (pval[0] == 't' && pval[1] == '')
  750. {
  751. ((char *) var->value)[act_tuple] = true;
  752. break;
  753. }
  754. }
  755. register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
  756.    (pval ? pval : "NULL"),
  757.    stmt->lineno);
  758. status = false;
  759. break;
  760. case ECPGt_char:
  761. case ECPGt_unsigned_char:
  762. {
  763. strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize);
  764. if (var->varcharsize && var->varcharsize < strlen(pval))
  765. {
  766. /* truncation */
  767. switch (var->ind_type)
  768. {
  769. case ECPGt_short:
  770. case ECPGt_unsigned_short:
  771. ((short *) var->ind_value)[act_tuple] = var->varcharsize;
  772. break;
  773. case ECPGt_int:
  774. case ECPGt_unsigned_int:
  775. ((int *) var->ind_value)[act_tuple] = var->varcharsize;
  776. break;
  777. case ECPGt_long:
  778. case ECPGt_unsigned_long:
  779. ((long *) var->ind_value)[act_tuple] = var->varcharsize;
  780. break;
  781. default:
  782. break;
  783. }
  784. sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
  785. }
  786. }
  787. break;
  788. case ECPGt_varchar:
  789. {
  790. struct ECPGgeneric_varchar *variable =
  791. (struct ECPGgeneric_varchar *) ((long) var->value + var->offset * act_tuple);
  792. if (var->varcharsize == 0)
  793. strncpy(variable->arr, pval, strlen(pval));
  794. else
  795. strncpy(variable->arr, pval, var->varcharsize);
  796. variable->len = strlen(pval);
  797. if (var->varcharsize > 0 && variable->len > var->varcharsize)
  798. {
  799. /* truncation */
  800. switch (var->ind_type)
  801. {
  802. case ECPGt_short:
  803. case ECPGt_unsigned_short:
  804. ((short *) var->ind_value)[act_tuple] = var->varcharsize;
  805. break;
  806. case ECPGt_int:
  807. case ECPGt_unsigned_int:
  808. ((int *) var->ind_value)[act_tuple] = var->varcharsize;
  809. break;
  810. case ECPGt_long:
  811. case ECPGt_unsigned_long:
  812. ((long *) var->ind_value)[act_tuple] = var->varcharsize;
  813. break;
  814. default:
  815. break;
  816. }
  817. sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
  818. variable->len = var->varcharsize;
  819. }
  820. }
  821. break;
  822. default:
  823. register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", ECPGtype_name(var->type), stmt->lineno);
  824. status = false;
  825. break;
  826. }
  827. }
  828. var = var->next;
  829. }
  830. if (status && var != NULL)
  831. {
  832. register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
  833. status = false;
  834. }
  835. break;
  836. case PGRES_EMPTY_QUERY:
  837. /* do nothing */
  838. register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
  839. break;
  840. case PGRES_COMMAND_OK:
  841. status = true;
  842. sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
  843. ECPGlog("ECPGexecute line %d Ok: %sn", stmt->lineno, PQcmdStatus(results));
  844. break;
  845. case PGRES_NONFATAL_ERROR:
  846. case PGRES_FATAL_ERROR:
  847. case PGRES_BAD_RESPONSE:
  848. ECPGlog("ECPGexecute line %d: Error: %s",
  849. stmt->lineno, PQerrorMessage(stmt->connection->connection));
  850. register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
  851.    PQerrorMessage(stmt->connection->connection), stmt->lineno);
  852. status = false;
  853. break;
  854. case PGRES_COPY_OUT:
  855. ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.n", stmt->lineno);
  856. PQendcopy(stmt->connection->connection);
  857. break;
  858. case PGRES_COPY_IN:
  859. ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.n", stmt->lineno);
  860. PQendcopy(stmt->connection->connection);
  861. break;
  862. default:
  863. ECPGlog("ECPGexecute line %d: Got something else, postgres error.n",
  864. stmt->lineno);
  865. register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
  866.    PQerrorMessage(stmt->connection->connection), stmt->lineno);
  867. status = false;
  868. break;
  869. }
  870. PQclear(results);
  871. }
  872. /* check for asynchronous returns */
  873. notify = PQnotifies(stmt->connection->connection);
  874. if (notify)
  875. {
  876. ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' receivedn",
  877. stmt->lineno, notify->relname, notify->be_pid);
  878. free(notify);
  879. }
  880. return status;
  881. }
  882. bool
  883. ECPGdo(int lineno, const char *connection_name, char *query,...)
  884. {
  885. va_list args;
  886. struct statement *stmt;
  887. struct connection *con = get_connection(connection_name);
  888. bool status;
  889. if (con == NULL)
  890. {
  891. register_error(ECPG_NO_CONN, "No such connection %s in line %d.", connection_name ? connection_name : "NULL", lineno);
  892. return (false);
  893. }
  894. va_start(args, query);
  895. if (create_statement(lineno, con, &stmt, query, args) == false)
  896. return (false);
  897. va_end(args);
  898. /* are we connected? */
  899. if (con == NULL || con->connection == NULL)
  900. {
  901. ECPGlog("ECPGdo: not connected to %sn", con->name);
  902. register_error(ECPG_NOT_CONN, "Not connected in line %d.", lineno);
  903. return false;
  904. }
  905. status = ECPGexecute(stmt);
  906. free_statement(stmt);
  907. return (status);
  908. }
  909. bool
  910. ECPGstatus(int lineno, const char *connection_name)
  911. {
  912. struct connection *con = get_connection(connection_name);
  913. if (con == NULL)
  914. {
  915. register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name ? connection_name : "NULL", lineno);
  916. return (false);
  917. }
  918. /* are we connected? */
  919. if (con->connection == NULL)
  920. {
  921. ECPGlog("ECPGdo: not connected to %sn", con->name);
  922. register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
  923. return false;
  924. }
  925. return (true);
  926. }
  927. bool
  928. ECPGtrans(int lineno, const char *connection_name, const char *transaction)
  929. {
  930. PGresult   *res;
  931. struct connection *con = get_connection(connection_name);
  932. if (con == NULL)
  933. {
  934. register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name ? connection_name : "NULL", lineno);
  935. return (false);
  936. }
  937. ECPGlog("ECPGtrans line %d action = %s connection = %sn", lineno, transaction, con->name);
  938. /* if we have no connection we just simulate the command */
  939. if (con && con->connection)
  940. {
  941. if ((res = PQexec(con->connection, transaction)) == NULL)
  942. {
  943. register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
  944. return FALSE;
  945. }
  946. PQclear(res);
  947. }
  948. if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
  949. {
  950. struct prepared_statement *this;
  951. con->committed = true;
  952. /* deallocate all prepared statements */
  953. for (this = prep_stmts; this != NULL; this = this->next)
  954. {
  955. bool b = ECPGdeallocate(lineno, this->name);
  956. if (!b)
  957. return false;
  958. }
  959. }
  960. return true;
  961. }
  962. bool
  963. ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
  964. {
  965. struct connection *con = get_connection(connection_name);
  966. PGresult   *results;
  967. if (con)
  968. {
  969. if (con->autocommit == true && strncmp(mode, "OFF", strlen("OFF")) == 0)
  970. {
  971. if (con->committed)
  972. {
  973. if ((results = PQexec(con->connection, "begin transaction")) == NULL)
  974. {
  975. register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
  976. return false;
  977. }
  978. PQclear(results);
  979. con->committed = false;
  980. }
  981. con->autocommit = false;
  982. }
  983. else if (con->autocommit == false && strncmp(mode, "ON", strlen("ON")) == 0)
  984. {
  985. if (!con->committed)
  986. {
  987. if ((results = PQexec(con->connection, "commit")) == NULL)
  988. {
  989. register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
  990. return false;
  991. }
  992. PQclear(results);
  993. con->committed = true;
  994. }
  995. con->autocommit = true;
  996. }
  997. }
  998. else
  999. {
  1000. register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name ? connection_name : "NULL", lineno);
  1001. return false;
  1002. }
  1003. return true;
  1004. }
  1005. bool
  1006. ECPGsetconn(int lineno, const char *connection_name)
  1007. {
  1008. struct connection *con = get_connection(connection_name);
  1009. if (con)
  1010. {
  1011. actual_connection = con;
  1012. return true;
  1013. }
  1014. else
  1015. {
  1016. register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name ? connection_name : "NULL", lineno);
  1017. return false;
  1018. }
  1019. }
  1020. bool
  1021. ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char *connection_name, int autocommit)
  1022. {
  1023. struct connection *this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno);
  1024. if (!this)
  1025. return false;
  1026. if (dbname == NULL && connection_name == NULL)
  1027. connection_name = "DEFAULT";
  1028. /* add connection to our list */
  1029. if (connection_name != NULL)
  1030. this->name = ecpg_strdup(connection_name, lineno);
  1031. else
  1032. this->name = ecpg_strdup(dbname, lineno);
  1033. if (all_connections == NULL)
  1034. this->next = NULL;
  1035. else
  1036. this->next = all_connections;
  1037. actual_connection = all_connections = this;
  1038. ECPGlog("ECPGconnect: opening database %s %s%sn", dbname ? dbname : "<DEFAULT>", user ? "for user " : "", user ? user : "");
  1039. sqlca.sqlcode = 0;
  1040. this->connection = PQsetdbLogin(NULL, NULL, NULL, NULL, dbname, user, passwd);
  1041. if (PQstatus(this->connection) == CONNECTION_BAD)
  1042. {
  1043. ECPGfinish(this);
  1044. ECPGlog("connect: could not open database %s %s%s in line %dn", dbname ? dbname : "<DEFAULT>", user ? "for user " : "", user ? user : "", lineno);
  1045. register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "<DEFAULT>");
  1046. return false;
  1047. }
  1048. this->committed = true;
  1049. this->autocommit = autocommit;
  1050. return true;
  1051. }
  1052. bool
  1053. ECPGdisconnect(int lineno, const char *connection_name)
  1054. {
  1055. struct connection *con;
  1056. if (strcmp(connection_name, "ALL") == 0)
  1057. {
  1058. for (con = all_connections; con;)
  1059. {
  1060. struct connection *f = con;
  1061. con = con->next;
  1062. ECPGfinish(f);
  1063. }
  1064. }
  1065. else
  1066. {
  1067. con = get_connection(connection_name);
  1068. if (con == NULL)
  1069. {
  1070. ECPGlog("disconnect: not connected to connection %sn", connection_name ? connection_name : "NULL");
  1071. register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name ? connection_name : "NULL", lineno);
  1072. return false;
  1073. }
  1074. else
  1075. ECPGfinish(con);
  1076. }
  1077. return true;
  1078. }
  1079. void
  1080. ECPGdebug(int n, FILE *dbgs)
  1081. {
  1082. simple_debug = n;
  1083. debugstream = dbgs;
  1084. ECPGlog("ECPGdebug: set to %dn", simple_debug);
  1085. }
  1086. void
  1087. ECPGlog(const char *format,...)
  1088. {
  1089. va_list ap;
  1090. if (simple_debug)
  1091. {
  1092. char    *f = (char *) malloc(strlen(format) + 100);
  1093. if (!f)
  1094. return;
  1095. sprintf(f, "[%d]: %s", (int) getpid(), format);
  1096. va_start(ap, format);
  1097. vfprintf(debugstream, f, ap);
  1098. va_end(ap);
  1099. free(f);
  1100. }
  1101. }
  1102. /* print out an error message */
  1103. void
  1104. sqlprint(void)
  1105. {
  1106. sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '';
  1107. printf("sql error %sn", sqlca.sqlerrm.sqlerrmc);
  1108. }
  1109. static bool
  1110. isvarchar(unsigned char c)
  1111. {
  1112. if (isalnum(c))
  1113. return true;
  1114. if (c == '_' || c == '>' || c == '-' || c == '.')
  1115. return true;
  1116. if (c >= 128)
  1117. return true;
  1118. return (false);
  1119. }
  1120. static void
  1121. replace_variables(char *text)
  1122. {
  1123. char    *ptr = text;
  1124. bool string = false;
  1125. for (; *ptr != ''; ptr++)
  1126. {
  1127. if (*ptr == ''')
  1128. string = string ? false : true;
  1129. if (!string && *ptr == ':')
  1130. {
  1131. *ptr = '?';
  1132. for (++ptr; *ptr && isvarchar(*ptr); ptr++)
  1133. *ptr = ' ';
  1134. }
  1135. }
  1136. }
  1137. /* handle the EXEC SQL PREPARE statement */
  1138. bool
  1139. ECPGprepare(int lineno, char *name, char *variable)
  1140. {
  1141. struct statement *stmt;
  1142. struct prepared_statement *this;
  1143. /* check if we already have prepared this statement */
  1144. for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
  1145. if (this)
  1146. {
  1147. bool b = ECPGdeallocate(lineno, name);
  1148. if (!b)
  1149. return false;
  1150. }
  1151. this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
  1152. if (!this)
  1153. return false;
  1154. stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
  1155. if (!stmt)
  1156. {
  1157. free(this);
  1158. return false;
  1159. }
  1160. /* create statement */
  1161. stmt->lineno = lineno;
  1162. stmt->connection = NULL;
  1163. stmt->command = ecpg_strdup(variable, lineno);
  1164. stmt->inlist = stmt->outlist = NULL;
  1165. /* if we have C variables in our statment replace them with '?' */
  1166. replace_variables(stmt->command);
  1167. /* add prepared statement to our list */
  1168. this->name = ecpg_strdup(name, lineno);
  1169. this->stmt = stmt;
  1170. if (prep_stmts == NULL)
  1171. this->next = NULL;
  1172. else
  1173. this->next = prep_stmts;
  1174. prep_stmts = this;
  1175. return true;
  1176. }
  1177. /* handle the EXEC SQL DEALLOCATE PREPARE statement */
  1178. bool
  1179. ECPGdeallocate(int lineno, char *name)
  1180. {
  1181. struct prepared_statement *this,
  1182.    *prev;
  1183. /* check if we really have prepared this statement */
  1184. for (this = prep_stmts, prev = NULL; this != NULL && strcmp(this->name, name) != 0; prev = this, this = this->next);
  1185. if (this)
  1186. {
  1187. /* okay, free all the resources */
  1188. free(this->name);
  1189. free(this->stmt->command);
  1190. free(this->stmt);
  1191. if (prev != NULL)
  1192. prev->next = this->next;
  1193. else
  1194. prep_stmts = this->next;
  1195. return true;
  1196. }
  1197. ECPGlog("deallocate_prepare: invalid statement name %sn", name);
  1198. register_error(ECPG_INVALID_STMT, "Invalid statement name %s in line %d", name, lineno);
  1199. return false;
  1200. }
  1201. /* return the prepared statement */
  1202. char *
  1203. ECPGprepared_statement(char *name)
  1204. {
  1205. struct prepared_statement *this;
  1206. for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
  1207. return (this) ? this->stmt->command : NULL;
  1208. }