From: Ard Biesheuvel Date: Tue, 5 Aug 2003 23:40:30 +0000 (+0000) Subject: Changed ibase_trans() to allow multi-DB transactions with distinct X-Git-Tag: RELEASE_0_5_2~15 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3ef8d3663dd500b9e70508bfc7eb523505e67aa5;p=php Changed ibase_trans() to allow multi-DB transactions with distinct trans_args for each connection. --- diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c index 0bf878a04e..7122d799fa 100644 --- a/ext/interbase/interbase.c +++ b/ext/interbase/interbase.c @@ -974,7 +974,7 @@ PHP_FUNCTION(ibase_pconnect) Close an InterBase connection */ PHP_FUNCTION(ibase_close) { - zval **link_arg; + zval **link_arg = NULL; ibase_db_link *ib_link; int link_id; @@ -1006,7 +1006,7 @@ PHP_FUNCTION(ibase_close) Drop an InterBase database */ PHP_FUNCTION(ibase_drop_db) { - zval **link_arg; + zval **link_arg = NULL; ibase_db_link *ib_link; int link_id; @@ -1576,98 +1576,120 @@ _php_ibase_exec_error: /* I'm a bad boy... */ } /* }}} */ -/* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier]]) - Start transaction */ +/* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]]) + Start a transaction over one or several databases */ + +#define TPB_MAX_SIZE (8*sizeof(char)) + PHP_FUNCTION(ibase_trans) { - zval ***args; - char tpb[20]; - long trans_argl = 0; - int tpb_len = 0, argn, link_cnt, link_id[19], i; - ibase_db_link *ib_link[19]; + unsigned i, argn, link_cnt = 0, tpb_len = 0; + char last_tpb[TPB_MAX_SIZE]; + ibase_db_link **ib_link = NULL; ibase_trans *ib_trans; - - ISC_TEB *teb; isc_tr_handle tr_handle = NULL; + ISC_STATUS result; RESET_ERRMSG; argn = ZEND_NUM_ARGS(); - if (argn < 0) { - WRONG_PARAM_COUNT; - } - if (argn) { - /* the number of databases this transaction connects to */ - link_cnt = argn-1; + /* (1+argn) is an upper bound for the number of links this trans connects to */ + ib_link = (ibase_db_link**)do_alloca(sizeof(ibase_db_link*) * (1+argn)); + + if (argn > 0) { + long trans_argl = 0; + char *tpb; + ISC_TEB *teb; + zval ***args = (zval ***)do_alloca(sizeof(zval **) * argn); - args = (zval ***) emalloc(sizeof(zval **) * argn); if (zend_get_parameters_array_ex(argn, args) == FAILURE) { - efree(args); + free_alloca(args); + free_alloca(ib_link); RETURN_FALSE; } - /* Handle all database links. */ - for (i = argn-1; i > 0 && Z_TYPE_PP(args[i]) == IS_RESOURCE; --i) { - ZEND_FETCH_RESOURCE2(ib_link[i-1], ibase_db_link *, args[i], -1, "InterBase link", le_link, le_plink); - link_id[i-1] = Z_LVAL_PP(args[i]); - } + teb = (ISC_TEB*)do_alloca(sizeof(ISC_TEB) * argn); + tpb = (char*)do_alloca(TPB_MAX_SIZE * argn); - /* First argument is transaction parameters */ - convert_to_long_ex(args[0]); - trans_argl = Z_LVAL_PP(args[0]); + /* enumerate all the arguments: assume every non-resource argument + specifies modifiers for the link ids that follow it */ + for (i = 0; i < argn; ++i) { + + if (Z_TYPE_PP(args[i]) == IS_RESOURCE) { + + ZEND_FETCH_RESOURCE2(ib_link[link_cnt], ibase_db_link *, args[i], -1, "InterBase link", le_link, le_plink); + + /* copy the most recent modifier string into tbp[] */ + memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE); - efree(args); - } + /* add a database handle to the TEB with the most recently specified set of modifiers */ + teb[link_cnt].db_ptr = &ib_link[link_cnt]->link; + teb[link_cnt].tpb_len = tpb_len; + teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt]; + + ++link_cnt; + + } else { + + tpb_len = 0; - if (argn < 2) { - link_cnt = 1; - ZEND_FETCH_RESOURCE2(ib_link[0], ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink); - } + convert_to_long_ex(args[i]); + trans_argl = Z_LVAL_PP(args[i]); - if (trans_argl) { - tpb[tpb_len++] = isc_tpb_version3; - /* tpbp = tpb; */ - /* access mode */ - if (trans_argl & PHP_IBASE_READ) { /* READ ONLY TRANSACTION */ - tpb[tpb_len++] = isc_tpb_read; - } else { - tpb[tpb_len++] = isc_tpb_write; /* default access mode */ - } - /* isolation level */ - if (trans_argl & PHP_IBASE_COMMITTED) { - tpb[tpb_len++] = isc_tpb_read_committed; - if (trans_argl & PHP_IBASE_REC_VERSION) { - tpb[tpb_len++] = isc_tpb_rec_version; - } else { - tpb[tpb_len++] = isc_tpb_no_rec_version; /* default in read_committed */ - } - } else if (trans_argl & PHP_IBASE_CONSISTENCY) { - tpb[tpb_len++] = isc_tpb_consistency; - } else { - tpb[tpb_len++] = isc_tpb_concurrency; /* default isolation level */ - } - - /* lock resolution */ - if (trans_argl & PHP_IBASE_NOWAIT) { - tpb[tpb_len++] = isc_tpb_nowait; - } else { - tpb[tpb_len++] = isc_tpb_wait; /* default lock resolution */ + if (trans_argl) { + last_tpb[tpb_len++] = isc_tpb_version3; + + /* access mode */ + if (trans_argl & PHP_IBASE_READ) { /* READ ONLY TRANSACTION */ + last_tpb[tpb_len++] = isc_tpb_read; + } else { + last_tpb[tpb_len++] = isc_tpb_write; /* default access mode */ + } + + /* isolation level */ + if (trans_argl & PHP_IBASE_COMMITTED) { + last_tpb[tpb_len++] = isc_tpb_read_committed; + if (trans_argl & PHP_IBASE_REC_VERSION) { + last_tpb[tpb_len++] = isc_tpb_rec_version; + } else { + last_tpb[tpb_len++] = isc_tpb_no_rec_version; /* default in read_committed */ + } + } else if (trans_argl & PHP_IBASE_CONSISTENCY) { + last_tpb[tpb_len++] = isc_tpb_consistency; + } else { + last_tpb[tpb_len++] = isc_tpb_concurrency; /* default isolation level */ + } + + /* lock resolution */ + if (trans_argl & PHP_IBASE_NOWAIT) { + last_tpb[tpb_len++] = isc_tpb_nowait; + } else { + last_tpb[tpb_len++] = isc_tpb_wait; /* default lock resolution */ + } + } + } + } + + if (link_cnt > 0) { + result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb); } + + free_alloca(args); + free_alloca(tpb); + free_alloca(teb); } - /* allocate a TEB array */ - teb = (ISC_TEB*) emalloc(sizeof(ISC_TEB) * link_cnt); - for (i = 0; i < link_cnt; ++i) { - teb[i].db_ptr = &ib_link[i]->link; - teb[i].tpb_len = tpb_len; - teb[i].tpb_ptr = tpb; + if (link_cnt == 0) { + link_cnt = 1; + ZEND_FETCH_RESOURCE2(ib_link[0], ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink); + result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->link, tpb_len, last_tpb); } /* start the transaction */ - if (isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb)) { + if (result) { _php_ibase_error(TSRMLS_C); - efree(teb); + free_alloca(ib_link); RETURN_FALSE; } @@ -1692,7 +1714,7 @@ PHP_FUNCTION(ibase_trans) (*l)->trans = ib_trans; (*l)->next = NULL; } - efree(teb); + free_alloca(ib_link); ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans); } /* }}} */ @@ -1824,6 +1846,7 @@ PHP_FUNCTION(ibase_query) /* use stack to avoid leaks */ args = (zval ***) do_alloca(sizeof(zval **) * ZEND_NUM_ARGS()); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { + free_alloca(args); RETURN_FALSE; } @@ -2459,6 +2482,7 @@ PHP_FUNCTION(ibase_execute) /* use stack to avoid leaks */ args = (zval ***) do_alloca(ZEND_NUM_ARGS() * sizeof(zval **)); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { + free_alloca(args); RETURN_FALSE; }