270 lines
9.2 KiB
Diff
270 lines
9.2 KiB
Diff
|
diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c
|
||
|
index f2c43b9a69..79733c2c57 100644
|
||
|
--- a/ext/pdo_oci/oci_statement.c
|
||
|
+++ b/ext/pdo_oci/oci_statement.c
|
||
|
@@ -2,7 +2,7 @@
|
||
|
+----------------------------------------------------------------------+
|
||
|
| PHP Version 7 |
|
||
|
+----------------------------------------------------------------------+
|
||
|
- | Copyright (c) 1997-2018 The PHP Group |
|
||
|
+ | Copyright (c) The PHP Group |
|
||
|
+----------------------------------------------------------------------+
|
||
|
| This source file is subject to version 3.01 of the PHP license, |
|
||
|
| that is bundled with this package in the file LICENSE, and is |
|
||
|
@@ -525,7 +525,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
|
||
|
pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
|
||
|
OCIParam *param = NULL;
|
||
|
text *colname;
|
||
|
- ub2 dtype, data_size, scale, precis;
|
||
|
+ ub2 dtype, data_size, precis;
|
||
|
ub4 namelen;
|
||
|
struct pdo_column_data *col = &stmt->columns[colno];
|
||
|
zend_bool dyn = FALSE;
|
||
|
@@ -541,10 +541,6 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
|
||
|
STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_SIZE",
|
||
|
(param, OCI_DTYPE_PARAM, &data_size, 0, OCI_ATTR_DATA_SIZE, S->err));
|
||
|
|
||
|
- /* scale ? */
|
||
|
- STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_SCALE",
|
||
|
- (param, OCI_DTYPE_PARAM, &scale, 0, OCI_ATTR_SCALE, S->err));
|
||
|
-
|
||
|
/* precision ? */
|
||
|
STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_PRECISION",
|
||
|
(param, OCI_DTYPE_PARAM, &precis, 0, OCI_ATTR_PRECISION, S->err));
|
||
|
@@ -553,7 +549,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
|
||
|
STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_NAME",
|
||
|
(param, OCI_DTYPE_PARAM, &colname, &namelen, OCI_ATTR_NAME, S->err));
|
||
|
|
||
|
- col->precision = scale;
|
||
|
+ col->precision = precis;
|
||
|
col->maxlen = data_size;
|
||
|
col->name = zend_string_init((char *)colname, namelen, 0);
|
||
|
|
||
|
@@ -598,7 +594,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
|
||
|
S->cols[colno].datalen = 1024;
|
||
|
#endif
|
||
|
} else if (dtype == SQLT_BIN) {
|
||
|
- S->cols[colno].datalen = (ub4) col->maxlen * 2; // raw characters to hex digits
|
||
|
+ S->cols[colno].datalen = (ub4) col->maxlen * 2; /* raw characters to hex digits */
|
||
|
} else {
|
||
|
S->cols[colno].datalen = (ub4) (col->maxlen * S->H->max_char_width);
|
||
|
}
|
||
|
@@ -793,20 +789,207 @@ static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len
|
||
|
}
|
||
|
} /* }}} */
|
||
|
|
||
|
+
|
||
|
+static int oci_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value) /* {{{ */
|
||
|
+{
|
||
|
+ pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
|
||
|
+ OCIParam *param = NULL;
|
||
|
+ ub2 dtype, precis;
|
||
|
+ sb1 scale;
|
||
|
+ zval flags;
|
||
|
+ ub1 isnull, charset_form;
|
||
|
+ if (!S->stmt) {
|
||
|
+ return FAILURE;
|
||
|
+ }
|
||
|
+ if (colno >= stmt->column_count) {
|
||
|
+ /* error invalid column */
|
||
|
+ return FAILURE;
|
||
|
+ }
|
||
|
+
|
||
|
+ array_init(return_value);
|
||
|
+ array_init(&flags);
|
||
|
+
|
||
|
+ /* describe the column */
|
||
|
+ STMT_CALL(OCIParamGet, (S->stmt, OCI_HTYPE_STMT, S->err, (dvoid*)¶m, colno+1));
|
||
|
+
|
||
|
+ /* column data type */
|
||
|
+ STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_TYPE",
|
||
|
+ (param, OCI_DTYPE_PARAM, &dtype, 0, OCI_ATTR_DATA_TYPE, S->err));
|
||
|
+
|
||
|
+ /* column precision */
|
||
|
+ STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_PRECISION",
|
||
|
+ (param, OCI_DTYPE_PARAM, &precis, 0, OCI_ATTR_PRECISION, S->err));
|
||
|
+
|
||
|
+ /* column scale */
|
||
|
+ STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_SCALE",
|
||
|
+ (param, OCI_DTYPE_PARAM, &scale, 0, OCI_ATTR_SCALE, S->err));
|
||
|
+
|
||
|
+ /* string column charset form */
|
||
|
+ if (dtype == SQLT_CHR || dtype == SQLT_VCS || dtype == SQLT_AFC || dtype == SQLT_CLOB) {
|
||
|
+ STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_CHARSET_FORM",
|
||
|
+ (param, OCI_DTYPE_PARAM, &charset_form, 0, OCI_ATTR_CHARSET_FORM, S->err));
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ if (dtype) {
|
||
|
+ /* if there is a declared type */
|
||
|
+ switch (dtype) {
|
||
|
+#ifdef SQLT_TIMESTAMP
|
||
|
+ case SQLT_TIMESTAMP:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "TIMESTAMP");
|
||
|
+ add_assoc_string(return_value, "native_type", "TIMESTAMP");
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+#ifdef SQLT_TIMESTAMP_TZ
|
||
|
+ case SQLT_TIMESTAMP_TZ:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "TIMESTAMP WITH TIMEZONE");
|
||
|
+ add_assoc_string(return_value, "native_type", "TIMESTAMP WITH TIMEZONE");
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+#ifdef SQLT_TIMESTAMP_LTZ
|
||
|
+ case SQLT_TIMESTAMP_LTZ:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "TIMESTAMP WITH LOCAL TIMEZONE");
|
||
|
+ add_assoc_string(return_value, "native_type", "TIMESTAMP WITH LOCAL TIMEZONE");
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+#ifdef SQLT_INTERVAL_YM
|
||
|
+ case SQLT_INTERVAL_YM:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "INTERVAL YEAR TO MONTH");
|
||
|
+ add_assoc_string(return_value, "native_type", "INTERVAL YEAR TO MONTH");
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+#ifdef SQLT_INTERVAL_DS
|
||
|
+ case SQLT_INTERVAL_DS:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "INTERVAL DAY TO SECOND");
|
||
|
+ add_assoc_string(return_value, "native_type", "INTERVAL DAY TO SECOND");
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+ case SQLT_DAT:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "DATE");
|
||
|
+ add_assoc_string(return_value, "native_type", "DATE");
|
||
|
+ break;
|
||
|
+ case SQLT_FLT :
|
||
|
+ case SQLT_NUM:
|
||
|
+ /* if the precision is nonzero and scale is -127 then it is a FLOAT */
|
||
|
+ if (scale == -127 && precis != 0) {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "FLOAT");
|
||
|
+ add_assoc_string(return_value, "native_type", "FLOAT");
|
||
|
+ } else {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "NUMBER");
|
||
|
+ add_assoc_string(return_value, "native_type", "NUMBER");
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ case SQLT_LNG:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "LONG");
|
||
|
+ add_assoc_string(return_value, "native_type", "LONG");
|
||
|
+ break;
|
||
|
+ case SQLT_BIN:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "RAW");
|
||
|
+ add_assoc_string(return_value, "native_type", "RAW");
|
||
|
+ break;
|
||
|
+ case SQLT_LBI:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "LONG RAW");
|
||
|
+ add_assoc_string(return_value, "native_type", "LONG RAW");
|
||
|
+ break;
|
||
|
+ case SQLT_CHR:
|
||
|
+ case SQLT_VCS:
|
||
|
+ if (charset_form == SQLCS_NCHAR) {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "NVARCHAR2");
|
||
|
+ add_assoc_string(return_value, "native_type", "NVARCHAR2");
|
||
|
+ } else {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "VARCHAR2");
|
||
|
+ add_assoc_string(return_value, "native_type", "VARCHAR2");
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ case SQLT_AFC:
|
||
|
+ if (charset_form == SQLCS_NCHAR) {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "NCHAR");
|
||
|
+ add_assoc_string(return_value, "native_type", "NCHAR");
|
||
|
+ } else {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "CHAR");
|
||
|
+ add_assoc_string(return_value, "native_type", "CHAR");
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ case SQLT_BLOB:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "BLOB");
|
||
|
+ add_next_index_string(&flags, "blob");
|
||
|
+ add_assoc_string(return_value, "native_type", "BLOB");
|
||
|
+ break;
|
||
|
+ case SQLT_CLOB:
|
||
|
+ if (charset_form == SQLCS_NCHAR) {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "NCLOB");
|
||
|
+ add_assoc_string(return_value, "native_type", "NCLOB");
|
||
|
+ } else {
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "CLOB");
|
||
|
+ add_assoc_string(return_value, "native_type", "CLOB");
|
||
|
+ }
|
||
|
+ add_next_index_string(&flags, "blob");
|
||
|
+ break;
|
||
|
+ case SQLT_BFILE:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "BFILE");
|
||
|
+ add_next_index_string(&flags, "blob");
|
||
|
+ add_assoc_string(return_value, "native_type", "BFILE");
|
||
|
+ break;
|
||
|
+ case SQLT_RDD:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "ROWID");
|
||
|
+ add_assoc_string(return_value, "native_type", "ROWID");
|
||
|
+ break;
|
||
|
+ case SQLT_BFLOAT:
|
||
|
+ case SQLT_IBFLOAT:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "BINARY_FLOAT");
|
||
|
+ add_assoc_string(return_value, "native_type", "BINARY_FLOAT");
|
||
|
+ break;
|
||
|
+ case SQLT_BDOUBLE:
|
||
|
+ case SQLT_IBDOUBLE:
|
||
|
+ add_assoc_string(return_value, "oci:decl_type", "BINARY_DOUBLE");
|
||
|
+ add_assoc_string(return_value, "native_type", "BINARY_DOUBLE");
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ add_assoc_long(return_value, "oci:decl_type", dtype);
|
||
|
+ add_assoc_string(return_value, "native_type", "UNKNOWN");
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ /* if the column is NULL */
|
||
|
+ add_assoc_long(return_value, "oci:decl_type", 0);
|
||
|
+ add_assoc_string(return_value, "native_type", "NULL");
|
||
|
+ }
|
||
|
+
|
||
|
+ /* column can be null */
|
||
|
+ STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_IS_NULL",
|
||
|
+ (param, OCI_DTYPE_PARAM, &isnull, 0, OCI_ATTR_IS_NULL, S->err));
|
||
|
+
|
||
|
+ if (isnull) {
|
||
|
+ add_next_index_string(&flags, "nullable");
|
||
|
+ } else {
|
||
|
+ add_next_index_string(&flags, "not_null");
|
||
|
+ }
|
||
|
+
|
||
|
+ /* PDO type */
|
||
|
+ switch (dtype) {
|
||
|
+ case SQLT_BFILE:
|
||
|
+ case SQLT_BLOB:
|
||
|
+ case SQLT_CLOB:
|
||
|
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_LOB);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
|
||
|
+ }
|
||
|
+
|
||
|
+ add_assoc_long(return_value, "scale", scale);
|
||
|
+ add_assoc_zval(return_value, "flags", &flags);
|
||
|
+
|
||
|
+ OCIDescriptorFree(param, OCI_DTYPE_PARAM);
|
||
|
+ return SUCCESS;
|
||
|
+} /* }}} */
|
||
|
+
|
||
|
const struct pdo_stmt_methods oci_stmt_methods = {
|
||
|
oci_stmt_dtor,
|
||
|
oci_stmt_execute,
|
||
|
oci_stmt_fetch,
|
||
|
oci_stmt_describe,
|
||
|
oci_stmt_get_col,
|
||
|
- oci_stmt_param_hook
|
||
|
+ oci_stmt_param_hook,
|
||
|
+ NULL, /* set_attr */
|
||
|
+ NULL, /* get_attr */
|
||
|
+ oci_stmt_col_meta
|
||
|
};
|
||
|
-
|
||
|
-/*
|
||
|
- * Local variables:
|
||
|
- * tab-width: 4
|
||
|
- * c-basic-offset: 4
|
||
|
- * End:
|
||
|
- * vim600: noet sw=4 ts=4 fdm=marker
|
||
|
- * vim<600: noet sw=4 ts=4
|
||
|
- */
|