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

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          bind.c
  2.  *
  3.  * Description:     This module contains routines related to binding 
  4.  *                  columns and parameters.
  5.  *
  6.  * Classes:         BindInfoClass, ParameterInfoClass
  7.  *
  8.  * API functions:   SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
  9.  *                  SQLParamOptions(NI)
  10.  *
  11.  * Comments:        See "notice.txt" for copyright and license information.
  12.  *
  13.  */
  14. #ifdef HAVE_CONFIG_H
  15. #include "config.h"
  16. #endif
  17. #include "bind.h"
  18. #include "environ.h"
  19. #include "statement.h"
  20. #include "qresult.h"
  21. #include "pgtypes.h"
  22. #include <stdlib.h>
  23. #include <malloc.h>
  24. #ifndef WIN32
  25. #include "iodbc.h"
  26. #include "isql.h"
  27. #include "isqlext.h"
  28. #else
  29. #include <sql.h>
  30. #include <sqlext.h>
  31. #endif
  32. //      Bind parameters on a statement handle
  33. RETCODE SQL_API SQLBindParameter(
  34.         HSTMT      hstmt,
  35.         UWORD      ipar,
  36.         SWORD      fParamType,
  37.         SWORD      fCType,
  38.         SWORD      fSqlType,
  39.         UDWORD     cbColDef,
  40.         SWORD      ibScale,
  41.         PTR        rgbValue,
  42.         SDWORD     cbValueMax,
  43.         SDWORD FAR *pcbValue)
  44. {
  45. StatementClass *stmt = (StatementClass *) hstmt;
  46. static char *func="SQLBindParameter";
  47. mylog( "%s: entering...n", func);
  48. if( ! stmt) {
  49. SC_log_error(func, "", NULL);
  50. return SQL_INVALID_HANDLE;
  51. }
  52. if(stmt->parameters_allocated < ipar) {
  53. ParameterInfoClass *old_parameters;
  54. int i, old_parameters_allocated;
  55. old_parameters = stmt->parameters;
  56. old_parameters_allocated = stmt->parameters_allocated;
  57. stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass)*(ipar));
  58. if ( ! stmt->parameters) {
  59. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  60. stmt->errormsg = "Could not allocate memory for statement parameters";
  61. SC_log_error(func, "", stmt);
  62. return SQL_ERROR;
  63. }
  64. stmt->parameters_allocated = ipar;
  65. // copy the old parameters over
  66. for(i = 0; i < old_parameters_allocated; i++) {
  67. // a structure copy should work
  68. stmt->parameters[i] = old_parameters[i];
  69. }
  70. // get rid of the old parameters, if there were any
  71. if(old_parameters)
  72. free(old_parameters);
  73. // zero out the newly allocated parameters (in case they skipped some,
  74. // so we don't accidentally try to use them later)
  75. for(; i < stmt->parameters_allocated; i++) {
  76. stmt->parameters[i].buflen = 0;
  77. stmt->parameters[i].buffer = 0;
  78. stmt->parameters[i].used = 0;
  79. stmt->parameters[i].paramType = 0;
  80. stmt->parameters[i].CType = 0;
  81. stmt->parameters[i].SQLType = 0;
  82. stmt->parameters[i].precision = 0;
  83. stmt->parameters[i].scale = 0;
  84. stmt->parameters[i].data_at_exec = FALSE;
  85. stmt->parameters[i].lobj_oid = 0;
  86. stmt->parameters[i].EXEC_used = NULL;
  87. stmt->parameters[i].EXEC_buffer = NULL;
  88. }
  89. }
  90. ipar--; /* use zero based column numbers for the below part */
  91. // store the given info
  92. stmt->parameters[ipar].buflen = cbValueMax;
  93. stmt->parameters[ipar].buffer = rgbValue;
  94. stmt->parameters[ipar].used = pcbValue;
  95. stmt->parameters[ipar].paramType = fParamType;
  96. stmt->parameters[ipar].CType = fCType;
  97. stmt->parameters[ipar].SQLType = fSqlType;
  98. stmt->parameters[ipar].precision = cbColDef;
  99. stmt->parameters[ipar].scale = ibScale;
  100. /* If rebinding a parameter that had data-at-exec stuff in it,
  101. then free that stuff
  102. */
  103. if (stmt->parameters[ipar].EXEC_used) {
  104. free(stmt->parameters[ipar].EXEC_used);
  105. stmt->parameters[ipar].EXEC_used = NULL;
  106. }
  107. if (stmt->parameters[ipar].EXEC_buffer) {
  108. free(stmt->parameters[ipar].EXEC_buffer);
  109. stmt->parameters[ipar].EXEC_buffer = NULL;
  110. }
  111. /* Data at exec macro only valid for C char/binary data */
  112. if ((fSqlType == SQL_LONGVARBINARY || fSqlType == SQL_LONGVARCHAR) && pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
  113. stmt->parameters[ipar].data_at_exec = TRUE;
  114. else
  115. stmt->parameters[ipar].data_at_exec = FALSE;
  116. mylog("SQLBindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %dn", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue: -777, stmt->parameters[ipar].data_at_exec);
  117. return SQL_SUCCESS;
  118. }
  119. //      -       -       -       -       -       -       -       -       -
  120. //      Associate a user-supplied buffer with a database column.
  121. RETCODE SQL_API SQLBindCol(
  122.         HSTMT      hstmt,
  123.         UWORD      icol,
  124.         SWORD      fCType,
  125.         PTR        rgbValue,
  126.         SDWORD     cbValueMax,
  127.         SDWORD FAR *pcbValue)
  128. {
  129. StatementClass *stmt = (StatementClass *) hstmt;
  130. static char *func="SQLBindCol";
  131. mylog( "%s: entering...n", func);
  132.     
  133. mylog("**** SQLBindCol: stmt = %u, icol = %dn", stmt, icol);
  134. if ( ! stmt) {
  135. SC_log_error(func, "", NULL);
  136. return SQL_INVALID_HANDLE;
  137. }
  138. SC_clear_error(stmt);
  139.     
  140. if( stmt->status == STMT_EXECUTING) {
  141. stmt->errormsg = "Can't bind columns while statement is still executing.";
  142. stmt->errornumber = STMT_SEQUENCE_ERROR;
  143. SC_log_error(func, "", stmt);
  144. return SQL_ERROR;
  145. }
  146. /* If the bookmark column is being bound, then just save it */
  147. if (icol == 0) {
  148. if (rgbValue == NULL) {
  149. stmt->bookmark.buffer = NULL;
  150. stmt->bookmark.used = NULL;
  151. }
  152. else {
  153. /* Make sure it is the bookmark data type */
  154. if ( fCType != SQL_C_BOOKMARK) {
  155. stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
  156. stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
  157. SC_log_error(func, "", stmt);
  158. return SQL_ERROR;
  159. }
  160. stmt->bookmark.buffer = rgbValue;
  161. stmt->bookmark.used = pcbValue;
  162. }
  163. return SQL_SUCCESS;
  164. }
  165. // allocate enough bindings if not already done
  166. // Most likely, execution of a statement would have setup the 
  167. // necessary bindings. But some apps call BindCol before any
  168. // statement is executed.
  169. if ( icol > stmt->bindings_allocated)
  170. extend_bindings(stmt, icol);
  171. // check to see if the bindings were allocated
  172. if ( ! stmt->bindings) {
  173. stmt->errormsg = "Could not allocate memory for bindings.";
  174. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  175. SC_log_error(func, "", stmt);
  176. return SQL_ERROR;
  177. }
  178. icol--; /* use zero based col numbers from here out */
  179. /* Reset for SQLGetData */
  180. stmt->bindings[icol].data_left = -1;
  181. if (rgbValue == NULL) {
  182. /* we have to unbind the column */
  183. stmt->bindings[icol].buflen = 0;
  184. stmt->bindings[icol].buffer = NULL;
  185. stmt->bindings[icol].used =   NULL;
  186. stmt->bindings[icol].returntype = SQL_C_CHAR;
  187. } else {
  188. /* ok, bind that column */
  189. stmt->bindings[icol].buflen     = cbValueMax;
  190. stmt->bindings[icol].buffer     = rgbValue;
  191. stmt->bindings[icol].used       = pcbValue;
  192. stmt->bindings[icol].returntype = fCType;
  193. mylog("       bound buffer[%d] = %un", icol, stmt->bindings[icol].buffer);
  194. }
  195. return SQL_SUCCESS;
  196. }
  197. //      -       -       -       -       -       -       -       -       -
  198. //  Returns the description of a parameter marker.
  199. // This function is listed as not being supported by SQLGetFunctions() because it is 
  200. // used to describe "parameter markers" (not bound parameters), in which case, 
  201. // the dbms should return info on the markers.  Since Postgres doesn't support that,
  202. // it is best to say this function is not supported and let the application assume a 
  203. // data type (most likely varchar).
  204. RETCODE SQL_API SQLDescribeParam(
  205.         HSTMT      hstmt,
  206.         UWORD      ipar,
  207.         SWORD  FAR *pfSqlType,
  208.         UDWORD FAR *pcbColDef,
  209.         SWORD  FAR *pibScale,
  210.         SWORD  FAR *pfNullable)
  211. {
  212. StatementClass *stmt = (StatementClass *) hstmt;
  213. static char *func = "SQLDescribeParam";
  214. mylog( "%s: entering...n", func);
  215. if( ! stmt) {
  216. SC_log_error(func, "", NULL);
  217. return SQL_INVALID_HANDLE;
  218. }
  219. if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) {
  220. stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
  221. stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
  222. SC_log_error(func, "", stmt);
  223. return SQL_ERROR;
  224. }
  225. ipar--;
  226. // This implementation is not very good, since it is supposed to describe
  227. // parameter markers, not bound parameters. 
  228. if(pfSqlType)
  229. *pfSqlType = stmt->parameters[ipar].SQLType;
  230. if(pcbColDef)
  231. *pcbColDef = stmt->parameters[ipar].precision;
  232. if(pibScale)
  233. *pibScale = stmt->parameters[ipar].scale;
  234. if(pfNullable)
  235. *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
  236. return SQL_SUCCESS;
  237. }
  238. //      -       -       -       -       -       -       -       -       -
  239. //      Sets multiple values (arrays) for the set of parameter markers.
  240. RETCODE SQL_API SQLParamOptions(
  241.         HSTMT      hstmt,
  242.         UDWORD     crow,
  243.         UDWORD FAR *pirow)
  244. {
  245. static char *func = "SQLParamOptions";
  246. mylog( "%s: entering...n", func);
  247. SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
  248. return SQL_ERROR;
  249. }
  250. //      -       -       -       -       -       -       -       -       -
  251. // This function should really talk to the dbms to determine the number of 
  252. // "parameter markers" (not bound parameters) in the statement.  But, since
  253. // Postgres doesn't support that, the driver should just count the number of markers
  254. // and return that.  The reason the driver just can't say this function is unsupported
  255. // like it does for SQLDescribeParam is that some applications don't care and try 
  256. // to call it anyway.
  257. // If the statement does not have parameters, it should just return 0.
  258. RETCODE SQL_API SQLNumParams(
  259.         HSTMT      hstmt,
  260.         SWORD  FAR *pcpar)
  261. {
  262. StatementClass *stmt = (StatementClass *) hstmt;
  263. char in_quote = FALSE;
  264. unsigned int i;
  265. static char *func = "SQLNumParams";
  266. mylog( "%s: entering...n", func);
  267. if(!stmt) {
  268. SC_log_error(func, "", NULL);
  269. return SQL_INVALID_HANDLE;
  270. }
  271. if (pcpar)
  272. *pcpar = 0;
  273. else {
  274. SC_log_error(func, "pcpar was null", stmt);
  275. return SQL_ERROR;
  276. }
  277. if(!stmt->statement) {
  278. // no statement has been allocated
  279. stmt->errormsg = "SQLNumParams called with no statement ready.";
  280. stmt->errornumber = STMT_SEQUENCE_ERROR;
  281. SC_log_error(func, "", stmt);
  282. return SQL_ERROR;
  283. } else {
  284. for(i=0; i < strlen(stmt->statement); i++) {
  285. if(stmt->statement[i] == '?' && !in_quote)
  286. (*pcpar)++;
  287. else {
  288. if (stmt->statement[i] == ''')
  289. in_quote = (in_quote ? FALSE : TRUE);
  290. }
  291. }
  292. return SQL_SUCCESS;
  293. }
  294. }
  295. /********************************************************************
  296.  *   Bindings Implementation
  297.  */
  298. BindInfoClass *
  299. create_empty_bindings(int num_columns)
  300. {
  301. BindInfoClass *new_bindings;
  302. int i;
  303. new_bindings = (BindInfoClass *)malloc(num_columns * sizeof(BindInfoClass));
  304. if(!new_bindings) {
  305. return 0;
  306. }
  307. for(i=0; i < num_columns; i++) {
  308. new_bindings[i].buflen = 0;
  309. new_bindings[i].buffer = NULL;
  310. new_bindings[i].used = NULL;
  311. new_bindings[i].data_left = -1;
  312. }
  313. return new_bindings;
  314. }
  315. void
  316. extend_bindings(StatementClass *stmt, int num_columns)
  317. {
  318. static char *func="extend_bindings";
  319. BindInfoClass *new_bindings;
  320. int i;
  321. mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%dn", func, stmt, stmt->bindings_allocated, num_columns);
  322. /* if we have too few, allocate room for more, and copy the old */
  323. /* entries into the new structure */
  324. if(stmt->bindings_allocated < num_columns) {
  325. new_bindings = create_empty_bindings(num_columns);
  326. if ( ! new_bindings) {
  327.            mylog("%s: unable to create %d new bindings from %d old bindingsn", func, num_columns, stmt->bindings_allocated);
  328. if (stmt->bindings) {
  329. free(stmt->bindings);
  330. stmt->bindings = NULL;
  331. }
  332. stmt->bindings_allocated = 0;
  333. return;
  334. }
  335. if(stmt->bindings) {
  336. for(i=0; i<stmt->bindings_allocated; i++)
  337. new_bindings[i] = stmt->bindings[i];
  338. free(stmt->bindings);
  339. }
  340. stmt->bindings = new_bindings;
  341. stmt->bindings_allocated = num_columns;
  342.     } 
  343. // There is no reason to zero out extra bindings if there are
  344. // more than needed.  If an app has allocated extra bindings, 
  345. // let it worry about it by unbinding those columns.
  346. // SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings
  347. // SQLExecDirect(...)  # returns 5 cols
  348. // SQLExecDirect(...) # returns 10 cols  (now OK)
  349. mylog("exit extend_bindingsn");
  350. }