Close an InterBase connection */
PHP_FUNCTION(ibase_close)
{
- zval **link_arg;
+ zval **link_arg = NULL;
ibase_db_link *ib_link;
int link_id;
Drop an InterBase database */
PHP_FUNCTION(ibase_drop_db)
{
- zval **link_arg;
+ zval **link_arg = NULL;
ibase_db_link *ib_link;
int link_id;
}
/* }}} */
-/* {{{ 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;
}
(*l)->trans = ib_trans;
(*l)->next = NULL;
}
- efree(teb);
+ free_alloca(ib_link);
ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans);
}
/* }}} */
/* 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;
}
/* 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;
}