You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

703 lines
19 KiB

19 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
22 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2007 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Ard Biesheuvel <abies@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/info.h"
  25. #include "pdo/php_pdo.h"
  26. #include "pdo/php_pdo_driver.h"
  27. #include "php_pdo_firebird.h"
  28. #include "php_pdo_firebird_int.h"
  29. #include <time.h>
  30. #define RECORD_ERROR(stmt) _firebird_error(NULL, stmt, __FILE__, __LINE__ TSRMLS_CC)
  31. /* free the allocated space for passing field values to the db and back */
  32. static void free_sqlda(XSQLDA const *sqlda) /* {{{ */
  33. {
  34. int i;
  35. for (i = 0; i < sqlda->sqld; ++i) {
  36. XSQLVAR const *var = &sqlda->sqlvar[i];
  37. if (var->sqlind) {
  38. efree(var->sqlind);
  39. }
  40. }
  41. }
  42. /* }}} */
  43. /* called by PDO to clean up a statement handle */
  44. static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
  45. {
  46. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  47. int result = 1, i;
  48. /* release the statement */
  49. if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
  50. RECORD_ERROR(stmt);
  51. result = 0;
  52. }
  53. /* clean up the fetch buffers if they have been used */
  54. for (i = 0; i < S->out_sqlda.sqld; ++i) {
  55. if (S->fetch_buf[i]) {
  56. efree(S->fetch_buf[i]);
  57. }
  58. }
  59. efree(S->fetch_buf);
  60. zend_hash_destroy(S->named_params);
  61. FREE_HASHTABLE(S->named_params);
  62. /* clean up the input descriptor */
  63. if (S->in_sqlda) {
  64. free_sqlda(S->in_sqlda);
  65. efree(S->in_sqlda);
  66. }
  67. free_sqlda(&S->out_sqlda);
  68. efree(S);
  69. return result;
  70. }
  71. /* }}} */
  72. /* called by PDO to execute a prepared query */
  73. static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
  74. {
  75. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  76. pdo_firebird_db_handle *H = S->H;
  77. do {
  78. /* named cursors should be closed first */
  79. if (*S->name && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) {
  80. break;
  81. }
  82. /* assume all params have been bound */
  83. if ((S->statement_type == isc_info_sql_stmt_exec_procedure &&
  84. isc_dsql_execute2(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
  85. S->in_sqlda, &S->out_sqlda))
  86. || isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION,
  87. S->in_sqlda)) {
  88. break;
  89. }
  90. /* commit? */
  91. if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
  92. break;
  93. }
  94. *S->name = 0;
  95. S->exhausted = 0;
  96. return 1;
  97. } while (0);
  98. RECORD_ERROR(stmt);
  99. return 0;
  100. }
  101. /* }}} */
  102. /* called by PDO to fetch the next row from a statement */
  103. static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
  104. enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
  105. {
  106. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  107. pdo_firebird_db_handle *H = S->H;
  108. if (!stmt->executed) {
  109. strcpy(stmt->error_code, "HY000");
  110. H->last_app_error = "Cannot fetch from a closed cursor";
  111. } else if (!S->exhausted) {
  112. /* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because
  113. * the result was returned in the execute call */
  114. if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
  115. S->exhausted = 1;
  116. } else {
  117. if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
  118. if (H->isc_status[0] && H->isc_status[1]) {
  119. RECORD_ERROR(stmt);
  120. }
  121. S->exhausted = 1;
  122. return 0;
  123. }
  124. }
  125. return 1;
  126. }
  127. return 0;
  128. }
  129. /* }}} */
  130. /* called by PDO to retrieve information about the fields being returned */
  131. static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
  132. {
  133. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  134. struct pdo_column_data *col = &stmt->columns[colno];
  135. XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
  136. /* allocate storage for the column */
  137. var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
  138. var->sqldata = &((char*)var->sqlind)[sizeof(short)];
  139. col->precision = -var->sqlscale;
  140. col->maxlen = var->sqllen;
  141. col->namelen = var->aliasname_length;
  142. col->name = estrndup(var->aliasname,var->aliasname_length);
  143. return 1;
  144. }
  145. /* }}} */
  146. #if abies_0
  147. /* internal function to override return types of parameters */
  148. static void set_param_type(enum pdo_param_type *param_type, XSQLVAR const *var) /* {{{ */
  149. {
  150. /* set the param type after the field type */
  151. switch (var->sqltype & ~1) {
  152. case SQL_INT64:
  153. #if SIZEOF_LONG < 8
  154. if (0) /* always a string if its size exceeds native long */
  155. #endif
  156. case SQL_SHORT:
  157. case SQL_LONG:
  158. if (var->sqlscale == 0) {
  159. *param_type = PDO_PARAM_INT;
  160. break;
  161. }
  162. case SQL_TEXT:
  163. case SQL_VARYING:
  164. case SQL_TYPE_DATE:
  165. case SQL_TYPE_TIME:
  166. case SQL_TIMESTAMP:
  167. case SQL_BLOB:
  168. *param_type = PDO_PARAM_STR;
  169. break;
  170. case SQL_FLOAT:
  171. case SQL_DOUBLE:
  172. *param_type = PDO_PARAM_DBL;
  173. break;
  174. }
  175. }
  176. /* }}} */
  177. #endif
  178. #define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \
  179. emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type))))
  180. #define CHAR_BUF_LEN 24
  181. /* fetch a blob into a fetch buffer */
  182. static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
  183. unsigned long *len, ISC_QUAD *blob_id TSRMLS_DC)
  184. {
  185. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  186. pdo_firebird_db_handle *H = S->H;
  187. isc_blob_handle blobh = NULL;
  188. char const bl_item = isc_info_blob_total_length;
  189. char bl_info[20];
  190. unsigned short i;
  191. int result = *len = 0;
  192. if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
  193. RECORD_ERROR(stmt);
  194. return 0;
  195. }
  196. if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item),
  197. sizeof(bl_info), bl_info)) {
  198. RECORD_ERROR(stmt);
  199. goto fetch_blob_end;
  200. }
  201. /* find total length of blob's data */
  202. for (i = 0; i < sizeof(bl_info); ) {
  203. unsigned short item_len;
  204. char item = bl_info[i++];
  205. if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
  206. || i >= sizeof(bl_info)) {
  207. H->last_app_error = "Couldn't determine BLOB size";
  208. goto fetch_blob_end;
  209. }
  210. item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
  211. if (item == isc_info_blob_total_length) {
  212. *len = isc_vax_integer(&bl_info[i+2], item_len);
  213. break;
  214. }
  215. i += item_len+2;
  216. }
  217. /* we've found the blob's length, now fetch! */
  218. if (*len) {
  219. unsigned long cur_len;
  220. unsigned short seg_len;
  221. ISC_STATUS stat;
  222. *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
  223. for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
  224. unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX
  225. : (unsigned short)(*len-cur_len);
  226. stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]);
  227. }
  228. (*ptr)[*len++] = '\0';
  229. if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
  230. H->last_app_error = "Error reading from BLOB";
  231. goto fetch_blob_end;
  232. }
  233. }
  234. result = 1;
  235. fetch_blob_end:
  236. if (isc_close_blob(H->isc_status, &blobh)) {
  237. RECORD_ERROR(stmt);
  238. return 0;
  239. }
  240. return result;
  241. }
  242. /* }}} */
  243. static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
  244. unsigned long *len, int *caller_frees TSRMLS_DC)
  245. {
  246. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  247. XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
  248. if (*var->sqlind == -1) {
  249. /* A NULL value */
  250. *ptr = NULL;
  251. *len = 0;
  252. } else {
  253. /* override the column param type */
  254. /* set_param_type(&stmt->columns[colno].param_type,var); */
  255. stmt->columns[colno].param_type = PDO_PARAM_STR;
  256. if (var->sqlscale < 0) {
  257. static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
  258. 100000000, 1000000000, 1000000000, LL_LIT(10000000000),LL_LIT(100000000000),
  259. LL_LIT(10000000000000), LL_LIT(100000000000000),LL_LIT(1000000000000000),
  260. LL_LIT(1000000000000000),LL_LIT(1000000000000000000) };
  261. ISC_INT64 n, f = scales[-var->sqlscale];
  262. switch (var->sqltype & ~1) {
  263. case SQL_SHORT:
  264. n = *(short*)var->sqldata;
  265. break;
  266. case SQL_LONG:
  267. n = *(ISC_LONG*)var->sqldata;
  268. break;
  269. case SQL_INT64:
  270. n = *(ISC_INT64*)var->sqldata;
  271. }
  272. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  273. if (n >= 0) {
  274. *len = snprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
  275. n / f, -var->sqlscale, n % f);
  276. } else if (n < -f) {
  277. *len = snprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
  278. n / f, -var->sqlscale, -n % f);
  279. } else {
  280. *len = snprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
  281. }
  282. } else {
  283. switch (var->sqltype & ~1) {
  284. struct tm t;
  285. char *fmt;
  286. /**
  287. * For the time being, this code has been changed to convert every returned value to a string
  288. * before passing it back up to the PDO driver.
  289. */
  290. case SQL_VARYING:
  291. *ptr = &var->sqldata[2];
  292. *len = *(short*)var->sqldata;
  293. break;
  294. case SQL_TEXT:
  295. *ptr = var->sqldata;
  296. *len = var->sqllen;
  297. break;
  298. /* --- cut here --- */
  299. case SQL_SHORT:
  300. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  301. *len = snprintf(*ptr, CHAR_BUF_LEN, "%d", *(short*)var->sqldata);
  302. break;
  303. case SQL_LONG:
  304. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  305. *len = snprintf(*ptr, CHAR_BUF_LEN, "%ld", *(ISC_LONG*)var->sqldata);
  306. break;
  307. case SQL_INT64:
  308. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  309. *len = snprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
  310. break;
  311. case SQL_FLOAT:
  312. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  313. *len = snprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
  314. break;
  315. case SQL_DOUBLE:
  316. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  317. *len = snprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
  318. break;
  319. /* --- cut here --- */
  320. #if abies_0
  321. case SQL_SHORT:
  322. *ptr = FETCH_BUF(S->fetch_buf[colno], long, 0, *len);
  323. *(long*)*ptr = *(short*)var->sqldata;
  324. break;
  325. case SQL_LONG:
  326. #if SIZEOF_LONG == 8
  327. *ptr = FETCH_BUF(S->fetch_buf[colno], long, 0, *len);
  328. *(long*)*ptr = *(ISC_LONG*)var->sqldata;
  329. #else
  330. *ptr = var->sqldata;
  331. #endif
  332. break;
  333. case SQL_INT64:
  334. *len = sizeof(long);
  335. #if SIZEOF_LONG == 8
  336. *ptr = var->sqldata;
  337. #else
  338. *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
  339. *len = snprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
  340. #endif
  341. break;
  342. case SQL_FLOAT:
  343. *ptr = FETCH_BUF(S->fetch_buf[colno], double, 0, *len);
  344. *(double*)*ptr = *(float*)var->sqldata;
  345. break;
  346. case SQL_DOUBLE:
  347. *ptr = var->sqldata;
  348. *len = sizeof(double);
  349. break;
  350. #endif
  351. case SQL_TYPE_DATE:
  352. isc_decode_sql_date((ISC_DATE*)var->sqldata, &t);
  353. fmt = INI_STR("ibase.dateformat");
  354. if (0) {
  355. case SQL_TYPE_TIME:
  356. isc_decode_sql_time((ISC_TIME*)var->sqldata, &t);
  357. fmt = INI_STR("ibase.timeformat");
  358. } else if (0) {
  359. case SQL_TIMESTAMP:
  360. isc_decode_timestamp((ISC_TIMESTAMP*)var->sqldata, &t);
  361. fmt = INI_STR("ibase.timestampformat");
  362. }
  363. /* convert the timestamp into a string */
  364. *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len = 80, NULL);
  365. *len = strftime(*ptr, *len, fmt, &t);
  366. break;
  367. case SQL_BLOB:
  368. return firebird_fetch_blob(stmt,colno,ptr,len,
  369. (ISC_QUAD*)var->sqldata TSRMLS_CC);
  370. }
  371. }
  372. }
  373. return 1;
  374. }
  375. /* }}} */
  376. static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param TSRMLS_DC)
  377. {
  378. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  379. pdo_firebird_db_handle *H = S->H;
  380. isc_blob_handle h = NULL;
  381. unsigned long put_cnt = 0, rem_cnt;
  382. unsigned short chunk_size;
  383. int result = 1;
  384. if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) {
  385. RECORD_ERROR(stmt);
  386. return 0;
  387. }
  388. SEPARATE_ZVAL(&param);
  389. convert_to_string_ex(&param);
  390. for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) {
  391. chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
  392. if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
  393. RECORD_ERROR(stmt);
  394. result = 0;
  395. break;
  396. }
  397. put_cnt += chunk_size;
  398. }
  399. zval_dtor(param);
  400. if (isc_close_blob(H->isc_status, &h)) {
  401. RECORD_ERROR(stmt);
  402. return 0;
  403. }
  404. return result;
  405. }
  406. static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */
  407. enum pdo_param_event event_type TSRMLS_DC)
  408. {
  409. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  410. XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda;
  411. XSQLVAR *var;
  412. if (event_type == PDO_PARAM_EVT_FREE) { /* not used */
  413. return 1;
  414. }
  415. if (!sqlda || param->paramno >= sqlda->sqld) {
  416. strcpy(stmt->error_code, "HY093");
  417. S->H->last_app_error = "Invalid parameter index";
  418. return 0;
  419. }
  420. if (param->is_param && param->paramno == -1) {
  421. long *index;
  422. /* try to determine the index by looking in the named_params hash */
  423. if (SUCCESS == zend_hash_find(S->named_params, param->name, param->namelen+1, (void*)&index)) {
  424. param->paramno = *index;
  425. } else {
  426. /* ... or by looking in the input descriptor */
  427. int i;
  428. for (i = 0; i < sqlda->sqld; ++i) {
  429. XSQLVAR *var = &sqlda->sqlvar[i];
  430. if ((var->aliasname_length && !strncasecmp(param->name, var->aliasname,
  431. min(param->namelen, var->aliasname_length)))
  432. || (var->sqlname_length && !strncasecmp(param->name, var->sqlname,
  433. min(param->namelen, var->sqlname_length)))) {
  434. param->paramno = i;
  435. break;
  436. }
  437. }
  438. if (i >= sqlda->sqld) {
  439. strcpy(stmt->error_code, "HY093");
  440. S->H->last_app_error = "Invalid parameter name";
  441. return 0;
  442. }
  443. }
  444. }
  445. var = &sqlda->sqlvar[param->paramno];
  446. switch (event_type) {
  447. char *value;
  448. unsigned long value_len;
  449. int caller_frees;
  450. case PDO_PARAM_EVT_ALLOC:
  451. if (param->is_param) {
  452. /* allocate the parameter */
  453. var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
  454. var->sqldata = &((char*)var->sqlind)[sizeof(short)];
  455. }
  456. break;
  457. case PDO_PARAM_EVT_EXEC_PRE:
  458. if (!param->is_param) {
  459. break;
  460. }
  461. *var->sqlind = 0;
  462. switch (var->sqltype & ~1) {
  463. case SQL_ARRAY:
  464. strcpy(stmt->error_code, "HY000");
  465. S->H->last_app_error = "Cannot bind to array field";
  466. return 0;
  467. case SQL_BLOB:
  468. return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata,
  469. param->parameter TSRMLS_CC);
  470. }
  471. /* check if a NULL should be inserted */
  472. switch (Z_TYPE_P(param->parameter)) {
  473. int force_null;
  474. case IS_LONG:
  475. var->sqltype = sizeof(long) == 8 ? SQL_INT64 : SQL_LONG;
  476. var->sqldata = (void*)&Z_LVAL_P(param->parameter);
  477. var->sqllen = sizeof(long);
  478. break;
  479. case IS_DOUBLE:
  480. var->sqltype = SQL_DOUBLE;
  481. var->sqldata = (void*)&Z_DVAL_P(param->parameter);
  482. var->sqllen = sizeof(double);
  483. break;
  484. case IS_STRING:
  485. force_null = 0;
  486. /* for these types, an empty string can be handled like a NULL value */
  487. switch (var->sqltype & ~1) {
  488. case SQL_SHORT:
  489. case SQL_LONG:
  490. case SQL_INT64:
  491. case SQL_FLOAT:
  492. case SQL_DOUBLE:
  493. case SQL_TIMESTAMP:
  494. case SQL_TYPE_DATE:
  495. case SQL_TYPE_TIME:
  496. force_null = (Z_STRLEN_P(param->parameter) == 0);
  497. }
  498. if (!force_null) {
  499. var->sqltype = SQL_TEXT;
  500. var->sqldata = Z_STRVAL_P(param->parameter);
  501. var->sqllen = Z_STRLEN_P(param->parameter);
  502. break;
  503. }
  504. case IS_NULL:
  505. /* complain if this field doesn't allow NULL values */
  506. if (~var->sqltype & 1) {
  507. strcpy(stmt->error_code, "HY105");
  508. S->H->last_app_error = "Parameter requires non-null value";
  509. return 0;
  510. }
  511. *var->sqlind = -1;
  512. break;
  513. default:
  514. strcpy(stmt->error_code, "HY105");
  515. S->H->last_app_error = "Binding arrays/objects is not supported";
  516. return 0;
  517. }
  518. break;
  519. case PDO_PARAM_EVT_FETCH_POST:
  520. value = NULL;
  521. value_len = 0;
  522. caller_frees = 0;
  523. if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees TSRMLS_CC)) {
  524. switch (PDO_PARAM_TYPE(param->param_type)) {
  525. case PDO_PARAM_STR:
  526. if (value) {
  527. ZVAL_STRINGL(param->parameter, value, value_len, 1);
  528. break;
  529. }
  530. case PDO_PARAM_INT:
  531. if (value) {
  532. ZVAL_LONG(param->parameter, *(long*)value);
  533. break;
  534. }
  535. #if abies_0
  536. case PDO_PARAM_DBL:
  537. if (value) {
  538. ZVAL_DOUBLE(param->parameter, *(double*)value);
  539. break;
  540. }
  541. #endif
  542. default:
  543. ZVAL_NULL(param->parameter);
  544. }
  545. if (value && caller_frees) {
  546. efree(value);
  547. }
  548. return 1;
  549. }
  550. return 0;
  551. default:
  552. ;
  553. }
  554. return 1;
  555. }
  556. /* }}} */
  557. static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
  558. {
  559. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  560. switch (attr) {
  561. default:
  562. return 0;
  563. case PDO_ATTR_CURSOR_NAME:
  564. convert_to_string(val);
  565. if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
  566. RECORD_ERROR(stmt);
  567. return 0;
  568. }
  569. strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
  570. break;
  571. }
  572. return 1;
  573. }
  574. /* }}} */
  575. static int firebird_stmt_get_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
  576. {
  577. pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  578. switch (attr) {
  579. default:
  580. return 0;
  581. case PDO_ATTR_CURSOR_NAME:
  582. if (*S->name) {
  583. ZVAL_STRING(val,S->name,1);
  584. } else {
  585. ZVAL_NULL(val);
  586. }
  587. break;
  588. }
  589. return 1;
  590. }
  591. /* }}} */
  592. struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */
  593. firebird_stmt_dtor,
  594. firebird_stmt_execute,
  595. firebird_stmt_fetch,
  596. firebird_stmt_describe,
  597. firebird_stmt_get_col,
  598. firebird_stmt_param_hook,
  599. firebird_stmt_set_attribute,
  600. firebird_stmt_get_attribute
  601. };
  602. /* }}} */
  603. /*
  604. * Local variables:
  605. * tab-width: 4
  606. * c-basic-offset: 4
  607. * End:
  608. * vim600: noet sw=4 ts=4 fdm=marker
  609. * vim<600: noet sw=4 ts=4
  610. */