📄 php_sybase_ct.c
字号:
/* numeric(10) vs numeric(10, 1) */ result->numerics[i] = (result->datafmt[i].scale == 0) ? 3 : 2; break; default: result->datafmt[i].maxlength++; result->numerics[i] = 0; break; } result->tmp_buffer[i] = (char *)emalloc(result->datafmt[i].maxlength); result->datafmt[i].datatype = CS_CHAR_TYPE; result->datafmt[i].format = CS_FMT_NULLTERM; ct_bind(sybase_ptr->cmd, i+1, &result->datafmt[i], result->tmp_buffer[i], &result->lengths[i], &result->indicators[i]); } result->fields = (sybase_field *) safe_emalloc(sizeof(sybase_field), num_fields, 0); j=0; for (i=0; i<num_fields; i++) { char computed_buf[16]; if (result->datafmt[i].namelen>0) { result->fields[i].name = estrndup(result->datafmt[i].name, result->datafmt[i].namelen); } else { if (j>0) { snprintf(computed_buf, 16, "computed%d", j); } else { strcpy(computed_buf, "computed"); } result->fields[i].name = estrdup(computed_buf); j++; } result->fields[i].column_source = empty_string; result->fields[i].max_length = result->datafmt[i].maxlength-1; result->fields[i].numeric = result->numerics[i]; Z_TYPE(result->fields[i]) = result->types[i]; } if (buffered) { retcode = CS_SUCCEED; } else { if ((retcode = php_sybase_fetch_result_row(result, -1)) == CS_FAIL) { return NULL; } } result->last_retcode = retcode; return result;}static void php_sybase_query (INTERNAL_FUNCTION_PARAMETERS, int buffered){ zval **query, **sybase_link_index=NULL; zval **store_mode= NULL; int id, deadlock_count, store; sybase_link *sybase_ptr; sybase_result *result; CS_INT restype; CS_RETCODE retcode; enum { Q_RESULT, /* Success with results. */ Q_SUCCESS, /* Success but no results. */ Q_FAILURE, /* Failure, no results. */ } status; store= 1; switch(ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &query)==FAILURE) { RETURN_FALSE; } id = SybCtG(default_link); break; case 2: if (zend_get_parameters_ex(2, &query, &sybase_link_index)==FAILURE) { RETURN_FALSE; } id = -1; break; case 3: if (zend_get_parameters_ex(3, &query, &sybase_link_index, &store_mode)==FAILURE) { RETURN_FALSE; } if (!buffered) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "cannot use non-storing mode with buffered queries"); store = 1; } else { convert_to_long_ex(store_mode); store= (Z_LVAL_PP(store_mode) != 0); } id = -1; break; default: WRONG_PARAM_COUNT; break; } ZEND_FETCH_RESOURCE2(sybase_ptr, sybase_link *, sybase_link_index, id, "Sybase-Link", le_link, le_plink); convert_to_string_ex(query); /* Fail if we already marked this connection dead. */ if (sybase_ptr->dead) { RETURN_FALSE; } /* Check to see if a previous sybase_unbuffered_query has read all rows */ if (sybase_ptr->active_result_index) { zval *tmp = NULL; php_error_docref(NULL TSRMLS_CC, E_NOTICE, "called without first fetching all rows from a previous unbuffered query"); if (sybase_ptr->cmd) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); } /* Get the resultset and free it */ ALLOC_ZVAL(tmp); Z_LVAL_P(tmp)= sybase_ptr->active_result_index; Z_TYPE_P(tmp)= IS_RESOURCE; INIT_PZVAL(tmp); ZEND_FETCH_RESOURCE(result, sybase_result *, &tmp, -1, "Sybase result", le_result); /* Causes the following segfault: Program received signal SIGSEGV, Segmentation fault. 0x8144380 in _efree (ptr=0x81fe024, __zend_filename=0x81841a0 "php4/ext/sybase_ct/php_sybase_ct.c", __zend_lineno=946, __zend_orig_filename=0x0, __zend_orig_lineno=0) at php4/Zend/zend_alloc.c:229 php4/Zend/zend_alloc.c:229:7284:beg:0x8144380 */ #if O_TIMM if (result) { php_sybase_finish_results(result); } #endif zval_ptr_dtor(&tmp); zend_list_delete(sybase_ptr->active_result_index); sybase_ptr->active_result_index= 0; } /* Repeat until we don't deadlock. */ deadlock_count= 0; for (;;) { result = NULL; sybase_ptr->deadlock = 0; sybase_ptr->affected_rows = 0; /* On Solaris 11.5, ct_command() can be moved outside the * loop, but not on Linux 11.0. */ if (ct_command(sybase_ptr->cmd, CS_LANG_CMD, Z_STRVAL_PP(query), CS_NULLTERM, CS_UNUSED)!=CS_SUCCEED) { /* If this didn't work, the connection is screwed but * ct-lib might not set CS_CONSTAT_DEAD. So set our own * flag. This happens sometimes when the database is restarted * and/or its machine is rebooted, and ct_command() returns * CS_BUSY for some reason. */ sybase_ptr->dead = 1; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Connection is dead"); RETURN_FALSE; } if (ct_send(sybase_ptr->cmd)!=CS_SUCCEED) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); sybase_ptr->dead = 1; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Cannot send command"); RETURN_FALSE; } /* Use the first result set or succeed/fail status and discard the * others. Applications really shouldn't be making calls that * return multiple result sets, but if they do then we need to * properly read or cancel them or the connection will become * unusable. */ if (ct_results(sybase_ptr->cmd, &restype)!=CS_SUCCEED) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); sybase_ptr->dead = 1; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Cannot read results"); RETURN_FALSE; } switch ((int) restype) { case CS_CMD_FAIL: default: status = Q_FAILURE; break; case CS_CMD_SUCCEED: case CS_CMD_DONE: { CS_INT row_count; if (ct_res_info(sybase_ptr->cmd, CS_ROW_COUNT, &row_count, CS_UNUSED, NULL)==CS_SUCCEED) { sybase_ptr->affected_rows = (long)row_count; } } /* Fall through */ case CS_COMPUTEFMT_RESULT: case CS_ROWFMT_RESULT: case CS_DESCRIBE_RESULT: case CS_MSG_RESULT: buffered= 0; /* These queries have no need for buffering */ status = Q_SUCCESS; break; case CS_COMPUTE_RESULT: case CS_CURSOR_RESULT: case CS_PARAM_RESULT: case CS_ROW_RESULT: case CS_STATUS_RESULT: result = php_sybase_fetch_result_set(sybase_ptr, buffered, store); if (result == NULL) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); RETURN_FALSE; } status = Q_RESULT; break; } /* Check for left-over results */ if (!buffered && status != Q_RESULT) { while ((retcode = ct_results(sybase_ptr->cmd, &restype))==CS_SUCCEED) { switch ((int) restype) { case CS_CMD_SUCCEED: case CS_CMD_DONE: break; case CS_CMD_FAIL: status = Q_FAILURE; break; case CS_COMPUTE_RESULT: case CS_CURSOR_RESULT: case CS_PARAM_RESULT: case CS_ROW_RESULT: if (status != Q_RESULT) { result = php_sybase_fetch_result_set(sybase_ptr, buffered, store); if (result == NULL) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); sybase_ptr->dead = 1; RETURN_FALSE; } status = Q_RESULT; retcode = result->last_retcode; } else { /* Unexpected results, cancel them. */ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_CURRENT); } break; case CS_STATUS_RESULT: /* Unexpected results, cancel them. */ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_CURRENT); break; default: status = Q_FAILURE; break; } if (status == Q_FAILURE) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); } if (retcode == CS_END_RESULTS) { break; } } switch (retcode) { case CS_END_RESULTS: /* Normal. */ break; case CS_FAIL: /* Hopefully this either cleans up the connection, or the * connection ends up marked dead so it will be reopened * if it is persistent. We may want to do * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the * doc for ct_results()==CS_FAIL. */ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); /* Don't take chances with the vagaries of ct-lib. Mark it * dead ourselves. */ sybase_ptr->dead = 1; case CS_CANCELED: default: status = Q_FAILURE; break; } } /* Retry deadlocks up until deadlock_retry_count times */ if (sybase_ptr->deadlock && SybCtG(deadlock_retry_count) != -1 && ++deadlock_count > SybCtG(deadlock_retry_count)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Retried deadlock %d times [max: %ld], giving up\n", deadlock_count- 1, SybCtG(deadlock_retry_count)); if (result != NULL) { _free_sybase_result(result); } break; } /* If query completed without deadlock, break out of the loop. * Sometimes deadlock results in failures and sometimes not, * it seems to depend on the server flavor. But we want to * retry all deadlocks. */ if (sybase_ptr->dead || sybase_ptr->deadlock == 0) { break; } /* Get rid of any results we may have fetched. This happens: * e.g., our result set may be a stored procedure status which * is returned even if the stored procedure deadlocks. As an * optimization, we could try not to fetch results in known * deadlock conditions, but deadlock is (should be) rare. */ if (result != NULL) { _free_sybase_result(result); } } if (status == Q_SUCCESS) { RETURN_TRUE; } if (status == Q_FAILURE) { if (result != NULL) { _free_sybase_result(result); } RETURN_FALSE; } /* Indicate we have data in case of buffered queries */ id= ZEND_REGISTER_RESOURCE(return_value, result, le_result); sybase_ptr->active_result_index= buffered ? id : 0;}/* {{{ proto int sybase_query(string query [, int link_id]) Send Sybase query */PHP_FUNCTION(sybase_query){ php_sybase_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);}/* }}} *//* {{{ proto int sybase_unbuffered_query(string query [, int link_id]) Send Sybase query */PHP_FUNCTION(sybase_unbuffered_query){ php_sybase_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);}/* {{{ proto bool sybase_free_result(int result) Free result memory */PHP_FUNCTION(sybase_free_result){ zval **sybase_result_index; sybase_result *result; if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &sybase_result_index) == FAILURE) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(sybase_result_index) == IS_RESOURCE && Z_LVAL_PP(sybase_result_index) == 0) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(result, sybase_result *, sybase_result_index, -1, "Sybase result", le_result); /* Did we fetch up until the end? */ if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS) { /* php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Cancelling the rest of the results\n"); */ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); php_sybase_finish_results(result); } zend_list_delete(Z_LVAL_PP(sybase_result_index)); RETURN_TRUE;}/* }}} *//* {{{ proto string sybase_get_last_message(void) Returns the last message from server (over min_message_severity) */PHP_FUNCTION(sybase_get_last_message){ RETURN_STRING(SybCtG(server_message), 1);}/* }}} *//* {{{ proto int sybase_num_rows(int result) Get number of rows in result */PHP_FUNCTION(sybase_num_rows){ zval **sybase_result_index; sybase_result *result; if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &sybase_result_index) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(result, sybase_result *, sybase_result_index, -1, "Sybase result", le_result); Z_LVAL_P(return_value) = result->num_rows; Z_TYPE_P(return_value) = IS_LONG;}/* }}} *//* {{{ proto int sybase_num_fields(int result) Get number of fields in result */PHP_FUNCTION(sybase_num_fields){ zval **sybase_result_index; sybase_result *result; if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &sybase_result_index) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(result, sybase_result *, sybase_result_index, -1, "Sybase result", le_result); Z_LVAL_P(return_value) = result->num_fields; Z_TYPE_P(return_value) = IS_LONG;}/* }}} *//* {{{ proto array sybase_fetch_row(int result) Get row as enumerated array */PHP_FUNCTION(sybase_fetch_row){ zval **sybase_result_index; int i; sybase_result *result; zval *field_content; if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &sybase_result_index) == FAILURE) { WRONG_PARAM_COUNT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -