summaryrefslogtreecommitdiff
path: root/ext/pdo_dblib/dblib_stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_dblib/dblib_stmt.c')
-rw-r--r--ext/pdo_dblib/dblib_stmt.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
new file mode 100644
index 0000000..1a2fefd
--- /dev/null
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -0,0 +1,302 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 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 |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ | Frank M. Kromann <frank@kromann.info> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/php_string.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_dblib.h"
+#include "php_pdo_dblib_int.h"
+#include "zend_exceptions.h"
+
+
+/* {{{ pdo_dblib_get_field_name
+ *
+ * Updated for MSSQL 2008 SR2 extended types
+ *
+ */
+static char *pdo_dblib_get_field_name(int type)
+{
+ switch (type) {
+ case 34: return "image";
+ case 35: return "text";
+ case 36: return "uniqueidentifier";
+ case 40: return "date";
+ case 41: return "time";
+ case 42: return "datetime2";
+ case 43: return "datetimeoffset";
+ case 48: return "tinyint";
+ case 52: return "smallint";
+ case 56: return "int";
+ case 58: return "smalldatetime";
+ case 59: return "real";
+ case 60: return "money";
+ case 61: return "datetime";
+ case 62: return "float";
+ case 98: return "sql_variant";
+ case 99: return "ntext";
+ case 104: return "bit";
+ case 106: return "decimal";
+ case 108: return "numeric";
+ case 122: return "smallmoney";
+ case 127: return "bigint";
+ case 240: return "geometry";
+ case 165: return "varbinary";
+ case 167: return "varchar";
+ case 173: return "binary";
+ case 175: return "char";
+ case 189: return "timestamp";
+ case 231: return "nvarchar";
+ case 239: return "nchar";
+ case 241: return "xml";
+ default:
+ return "unknown";
+ break;
+ }
+}
+/* }}} */
+
+static int dblib_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ /* Cancel any pending results */
+ dbcancel(H->link);
+
+ efree(stmt->columns);
+ stmt->columns = NULL;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+
+ dblib_dblib_stmt_cursor_closer(stmt TSRMLS_CC);
+
+ efree(S);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+ RETCODE ret;
+
+ ret = dbresults(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_RESULTS) {
+ return 0;
+ }
+
+ stmt->row_count = DBCOUNT(H->link);
+ stmt->column_count = dbnumcols(H->link);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+ RETCODE ret;
+
+ dbsetuserdata(H->link, (BYTE*) &S->err);
+
+ if (FAIL == dbcmd(H->link, stmt->active_query_string)) {
+ return 0;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return 0;
+ }
+
+ ret = pdo_dblib_stmt_next_rowset(stmt TSRMLS_CC);
+
+ if (ret == 0) {
+ return 0;
+ }
+
+ stmt->row_count = DBCOUNT(H->link);
+ stmt->column_count = dbnumcols(H->link);
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_fetch(pdo_stmt_t *stmt,
+ enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
+{
+
+ RETCODE ret;
+
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ ret = dbnextrow(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_ROWS) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ struct pdo_column_data *col = &stmt->columns[colno];
+
+ col->name = (char*)dbcolname(H->link, colno+1);
+ col->maxlen = dbcollen(H->link, colno+1);
+ col->namelen = strlen(col->name);
+ col->param_type = PDO_PARAM_STR;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
+ unsigned long *len, int *caller_frees TSRMLS_DC)
+{
+
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ int coltype;
+ unsigned int tmp_len;
+ char *tmp_ptr = NULL;
+
+ coltype = dbcoltype(H->link, colno+1);
+
+ *len = dbdatlen(H->link, colno+1);
+ *ptr = dbdata(H->link, colno+1);
+
+ if (*len == 0 && *ptr == NULL) {
+ return 1;
+ }
+
+ switch (coltype) {
+ case SQLCHAR:
+ case SQLTEXT:
+ case SQLVARBINARY:
+ case SQLBINARY:
+ case SQLIMAGE:
+ case SQLVARCHAR:
+ tmp_ptr = emalloc(*len + 1);
+ memcpy(tmp_ptr, *ptr, *len);
+ tmp_ptr[*len] = '\0';
+ *ptr = tmp_ptr;
+ break;
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN: {
+ DBFLT8 money_value;
+ dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
+ *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
+ *ptr = tmp_ptr;
+ break;
+ }
+#ifdef SQLUNIQUE
+ case SQLUNIQUE: {
+#else
+ case 36: { /* FreeTDS hack, also used by ext/mssql */
+#endif
+ *len = 36+1;
+ tmp_ptr = emalloc(*len + 1);
+
+ /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
+#ifdef SQLUNIQUE
+ *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#else
+ *len = dbconvert(NULL, 36, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#endif
+ php_strtoupper(tmp_ptr, *len);
+ *ptr = tmp_ptr;
+ break;
+ }
+ default:
+ if (dbwillconvert(coltype, SQLCHAR)) {
+ tmp_len = 32 + (2 * (*len));
+ tmp_ptr = emalloc(tmp_len);
+ *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
+ *ptr = tmp_ptr;
+ } else {
+ *len = 0;
+ *ptr = NULL;
+ }
+ }
+
+ *caller_frees = 1;
+
+ return 1;
+}
+
+static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
+ enum pdo_param_event event_type TSRMLS_DC)
+{
+ return 1;
+}
+
+static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ array_init(return_value);
+
+ DBTYPEINFO* dbtypeinfo;
+ dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
+
+ add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
+ add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
+ add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
+ add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1), 1);
+ add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)), 1);
+
+ return 1;
+}
+
+
+struct pdo_stmt_methods dblib_stmt_methods = {
+ pdo_dblib_stmt_dtor,
+ pdo_dblib_stmt_execute,
+ pdo_dblib_stmt_fetch,
+ pdo_dblib_stmt_describe,
+ pdo_dblib_stmt_get_col,
+ pdo_dblib_stmt_param_hook,
+ NULL, /* set attr */
+ NULL, /* get attr */
+ pdo_dblib_stmt_get_column_meta, /* meta */
+ pdo_dblib_stmt_next_rowset, /* nextrow */
+ dblib_dblib_stmt_cursor_closer
+};
+