📄 php_sybase_ct.c
字号:
if (zend_get_parameters_ex(1, &sybase_link_index) == FAILURE) { RETURN_FALSE; } 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); if (id == -1) { /* explicit resource number */ zend_list_delete(Z_RESVAL_PP(sybase_link_index)); } if (id != -1 || (sybase_link_index && Z_RESVAL_PP(sybase_link_index)==SybCtG(default_link))) { zend_list_delete(SybCtG(default_link)); SybCtG(default_link) = -1; } RETURN_TRUE;}/* }}} */static int exec_cmd(sybase_link *sybase_ptr, char *cmdbuf){ CS_RETCODE retcode; CS_INT restype; int failure=0; /* Fail if we already marked this connection dead. */ if (sybase_ptr->dead) { return FAILURE; } /* ** Get a command handle, store the command string in it, and ** send it to the server. */ if (ct_command(sybase_ptr->cmd, CS_LANG_CMD, cmdbuf, CS_NULLTERM, CS_UNUSED)!=CS_SUCCEED) { sybase_ptr->dead = 1; return FAILURE; } if (ct_send(sybase_ptr->cmd)!=CS_SUCCEED) { sybase_ptr->dead = 1; return FAILURE; } 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: failure=1; break; case CS_STATUS_RESULT: ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_CURRENT); break; default: failure=1; break; } if (failure) { ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL); return FAILURE; } } switch (retcode) { case CS_END_RESULTS: return SUCCESS; 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; return FAILURE; default: return FAILURE; }}/* {{{ proto bool sybase_select_db(string database [, int link_id]) Select Sybase database */PHP_FUNCTION(sybase_select_db){ zval **db, **sybase_link_index; int id; char *cmdbuf; sybase_link *sybase_ptr; switch(ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &db) == FAILURE) { RETURN_FALSE; } id = php_sybase_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); CHECK_LINK(id); break; case 2: if (zend_get_parameters_ex(2, &db, &sybase_link_index) == FAILURE) { RETURN_FALSE; } 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(db); cmdbuf = (char *) emalloc(sizeof("use ")+Z_STRLEN_PP(db)+1); sprintf(cmdbuf, "use %s", Z_STRVAL_PP(db)); /* SAFE */ if (exec_cmd(sybase_ptr, cmdbuf)==FAILURE) { efree(cmdbuf); RETURN_FALSE; } else { efree(cmdbuf); RETURN_TRUE; }}/* }}} */static int php_sybase_finish_results (sybase_result *result) { int i, fail; CS_RETCODE retcode; CS_INT restype; TSRMLS_FETCH(); efree(result->datafmt); efree(result->lengths); efree(result->indicators); efree(result->numerics); efree(result->types); for (i=0; i<result->num_fields; i++) { efree(result->tmp_buffer[i]); } efree(result->tmp_buffer); /* Indicate we have read all rows */ result->sybase_ptr->active_result_index= 0; /* The only restype we should get now is CS_CMD_DONE, possibly * followed by a CS_STATUS_RESULT/CS_CMD_SUCCEED/CS_CMD_DONE * sequence if the command was a stored procedure call. But we * still need to read and discard unexpected results. We might * want to return a failure in this case because the application * won't be getting all the results it asked for. */ fail = 0; while ((retcode = ct_results(result->sybase_ptr->cmd, &restype))==CS_SUCCEED) { switch ((int) restype) { case CS_CMD_SUCCEED: case CS_CMD_DONE: break; case CS_CMD_FAIL: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Command failed, cancelling rest"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); fail = 1; break; case CS_COMPUTE_RESULT: case CS_CURSOR_RESULT: case CS_PARAM_RESULT: case CS_ROW_RESULT: /* Unexpected results, cancel them. */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling current"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); break; case CS_STATUS_RESULT: /* Status result from a stored procedure, cancel it but do not tell user */ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); break; default: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling all"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); break; } if (fail) { 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, result->sybase_ptr->cmd, CS_CANCEL_ALL); /* Don't take chances with the vagaries of ct-lib. Mark it * dead ourselves. */ result->sybase_ptr->dead = 1; case CS_CANCELED: default: _free_sybase_result(result); result = NULL; retcode = CS_FAIL; break; } return retcode;}#define RETURN_DOUBLE_VAL(result, buf, length) \ if ((length - 1) <= EG(precision)) { \ errno = 0; \ Z_DVAL(result) = strtod(buf, NULL); \ if (errno != ERANGE) { \ Z_TYPE(result) = IS_DOUBLE; \ } else { \ ZVAL_STRINGL(&result, buf, length- 1, 1); \ } \ } else { \ ZVAL_STRINGL(&result, buf, length- 1, 1); \ }static int php_sybase_fetch_result_row (sybase_result *result, int numrows) { int i, j; CS_INT retcode; TSRMLS_FETCH(); /* We've already fetched everything */ if (result->last_retcode == CS_END_DATA || result->last_retcode == CS_END_RESULTS) { return result->last_retcode; } if (numrows!=-1) numrows+= result->num_rows; while ((retcode=ct_fetch(result->sybase_ptr->cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, NULL))==CS_SUCCEED || retcode==CS_ROW_FAIL) { /* if (retcode==CS_ROW_FAIL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Error reading row %d", result->num_rows); } */ result->num_rows++; i= result->store ? result->num_rows- 1 : 0; if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) { result->data = (zval **) erealloc(result->data, sizeof(zval *)*SYBASE_ROWS_BLOCK*(++result->blocks_initialized)); } if (result->store || 1 == result->num_rows) { result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0); } for (j = 0; j < result->num_fields; j++) { /* If we are in non-storing mode, free the previous result */ if (!result->store && result->num_rows > 1 && Z_TYPE(result->data[i][j]) == IS_STRING) { efree(Z_STRVAL(result->data[i][j])); } if (result->indicators[j] == -1) { /* null value */ ZVAL_NULL(&result->data[i][j]); } else { switch (result->numerics[j]) { case 1: { /* This indicates a long */ ZVAL_LONG(&result->data[i][j], strtol(result->tmp_buffer[j], NULL, 10)); break; } case 2: { /* This indicates a float */ RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); break; } case 3: { /* This indicates either a long or a float, which ever fits */ errno = 0; Z_LVAL(result->data[i][j]) = strtol(result->tmp_buffer[j], NULL, 10); if (errno == ERANGE) { /* An overflow occurred, so try to fit it into a double */ RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); break; } Z_TYPE(result->data[i][j]) = IS_LONG; break; } default: { /* This indicates anything else, return it as string */ ZVAL_STRINGL(&result->data[i][j], result->tmp_buffer[j], result->lengths[j]- 1, 1); break; } } } } if (numrows!=-1 && result->num_rows>=numrows) break; } result->last_retcode= retcode; switch (retcode) { case CS_END_DATA: retcode = php_sybase_finish_results(result); break; case CS_ROW_FAIL: case CS_SUCCEED: break; default: _free_sybase_result(result); result = NULL; retcode = CS_FAIL; /* Just to be sure */ break; } return retcode;}static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr, int buffered, int store){ int num_fields; sybase_result *result; int i, j; CS_INT retcode; /* The following (if unbuffered) is more or less the equivalent of mysql_store_result(). * fetch all rows from the server into the row buffer, thus: * 1) Being able to fire up another query without explicitly reading all rows * 2) Having numrows accessible */ if (ct_res_info(sybase_ptr->cmd, CS_NUMDATA, &num_fields, CS_UNUSED, NULL)!=CS_SUCCEED) { return NULL; } result = (sybase_result *) emalloc(sizeof(sybase_result)); result->data = (zval **) safe_emalloc(sizeof(zval *), SYBASE_ROWS_BLOCK, 0); result->fields = NULL; result->sybase_ptr = sybase_ptr; result->cur_field=result->cur_row=result->num_rows=0; result->num_fields = num_fields; result->last_retcode = 0; result->store= store; result->blocks_initialized= 1; result->tmp_buffer = (char **) safe_emalloc(sizeof(char *), num_fields, 0); result->lengths = (CS_INT *) safe_emalloc(sizeof(CS_INT), num_fields, 0); result->indicators = (CS_SMALLINT *) safe_emalloc(sizeof(CS_INT), num_fields, 0); result->datafmt = (CS_DATAFMT *) safe_emalloc(sizeof(CS_DATAFMT), num_fields, 0); result->numerics = (unsigned char *) safe_emalloc(sizeof(unsigned char), num_fields, 0); result->types = (CS_INT *) safe_emalloc(sizeof(CS_INT), num_fields, 0); for (i=0; i<num_fields; i++) { ct_describe(sybase_ptr->cmd, i+1, &result->datafmt[i]); result->types[i] = result->datafmt[i].datatype; switch (result->datafmt[i].datatype) { case CS_CHAR_TYPE: case CS_VARCHAR_TYPE: case CS_TEXT_TYPE: case CS_IMAGE_TYPE: result->datafmt[i].maxlength++; result->numerics[i] = 0; break; case CS_BINARY_TYPE: case CS_VARBINARY_TYPE: result->datafmt[i].maxlength *= 2; result->datafmt[i].maxlength++; result->numerics[i] = 0; break; case CS_BIT_TYPE: case CS_TINYINT_TYPE: result->datafmt[i].maxlength = 4; result->numerics[i] = 1; break; case CS_SMALLINT_TYPE: result->datafmt[i].maxlength = 7; result->numerics[i] = 1; break; case CS_INT_TYPE: result->datafmt[i].maxlength = 12; result->numerics[i] = 1; break; case CS_REAL_TYPE: case CS_FLOAT_TYPE: result->datafmt[i].maxlength = 24; result->numerics[i] = 2; break; case CS_MONEY_TYPE: case CS_MONEY4_TYPE: result->datafmt[i].maxlength = 24; result->numerics[i] = 2; break; case CS_DATETIME_TYPE: case CS_DATETIME4_TYPE: result->datafmt[i].maxlength = 30; result->numerics[i] = 0; break; case CS_NUMERIC_TYPE: case CS_DECIMAL_TYPE: result->datafmt[i].maxlength = result->datafmt[i].precision + 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -