Annotation of embedaddon/php/ext/mssql/php_mssql.c, revision 1.1.1.2
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Author: Frank M. Kromann <frank@kromann.info> |
16: +----------------------------------------------------------------------+
17: */
18:
1.1.1.2 ! misho 19: /* $Id$ */
1.1 misho 20:
21: #ifdef COMPILE_DL_MSSQL
22: #define HAVE_MSSQL 1
23: #endif
24:
25: #ifdef HAVE_CONFIG_H
26: #include "config.h"
27: #endif
28:
29: #include "php.h"
30: #include "php_globals.h"
31: #include "ext/standard/php_standard.h"
32: #include "ext/standard/info.h"
33: #include "php_mssql.h"
34: #include "php_ini.h"
35:
36: #if HAVE_MSSQL
37: #define SAFE_STRING(s) ((s)?(s):"")
38:
39: #define MSSQL_ASSOC 1<<0
40: #define MSSQL_NUM 1<<1
41: #define MSSQL_BOTH (MSSQL_ASSOC|MSSQL_NUM)
42:
43: static int le_result, le_link, le_plink, le_statement;
44:
45: static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
46: static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC);
47:
48: static void _mssql_bind_hash_dtor(void *data);
49:
50: /* {{{ arginfo */
51: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_connect, 0, 0, 0)
52: ZEND_ARG_INFO(0, servername)
53: ZEND_ARG_INFO(0, username)
54: ZEND_ARG_INFO(0, password)
55: ZEND_ARG_INFO(0, newlink)
56: ZEND_END_ARG_INFO()
57:
58: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_close, 0, 0, 0)
59: ZEND_ARG_INFO(0, link_identifier)
60: ZEND_END_ARG_INFO()
61:
62: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_select_db, 0, 0, 1)
63: ZEND_ARG_INFO(0, database_name)
64: ZEND_ARG_INFO(0, link_identifier)
65: ZEND_END_ARG_INFO()
66:
67: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_query, 0, 0, 1)
68: ZEND_ARG_INFO(0, query)
69: ZEND_ARG_INFO(0, link_identifier)
70: ZEND_ARG_INFO(0, batch_size)
71: ZEND_END_ARG_INFO()
72:
73: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_batch, 0, 0, 1)
74: ZEND_ARG_INFO(0, result)
75: ZEND_END_ARG_INFO()
76:
77: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_rows_affected, 0, 0, 1)
78: ZEND_ARG_INFO(0, link_identifier)
79: ZEND_END_ARG_INFO()
80:
81: ZEND_BEGIN_ARG_INFO(arginfo_mssql_get_last_message, 0)
82: ZEND_END_ARG_INFO()
83:
84: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_field, 0, 0, 1)
85: ZEND_ARG_INFO(0, result)
86: ZEND_ARG_INFO(0, field_offset)
87: ZEND_END_ARG_INFO()
88:
89: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_array, 0, 0, 1)
90: ZEND_ARG_INFO(0, result)
91: ZEND_ARG_INFO(0, result_type)
92: ZEND_END_ARG_INFO()
93:
94: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_fetch_assoc, 0, 0, 1)
95: ZEND_ARG_INFO(0, result_id)
96: ZEND_END_ARG_INFO()
97:
98: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_field_length, 0, 0, 1)
99: ZEND_ARG_INFO(0, result)
100: ZEND_ARG_INFO(0, offset)
101: ZEND_END_ARG_INFO()
102:
103: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_data_seek, 0, 0, 2)
104: ZEND_ARG_INFO(0, result_identifier)
105: ZEND_ARG_INFO(0, row_number)
106: ZEND_END_ARG_INFO()
107:
108: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_result, 0, 0, 3)
109: ZEND_ARG_INFO(0, result)
110: ZEND_ARG_INFO(0, row)
111: ZEND_ARG_INFO(0, field)
112: ZEND_END_ARG_INFO()
113:
114: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_min_error_severity, 0, 0, 1)
115: ZEND_ARG_INFO(0, severity)
116: ZEND_END_ARG_INFO()
117:
118: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_init, 0, 0, 1)
119: ZEND_ARG_INFO(0, sp_name)
120: ZEND_ARG_INFO(0, link_identifier)
121: ZEND_END_ARG_INFO()
122:
123: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_bind, 0, 0, 4)
124: ZEND_ARG_INFO(0, stmt)
125: ZEND_ARG_INFO(0, param_name)
126: ZEND_ARG_INFO(1, var)
127: ZEND_ARG_INFO(0, type)
128: ZEND_ARG_INFO(0, is_output)
129: ZEND_ARG_INFO(0, is_null)
130: ZEND_ARG_INFO(0, maxlen)
131: ZEND_END_ARG_INFO()
132:
133: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_execute, 0, 0, 1)
134: ZEND_ARG_INFO(0, stmt)
135: ZEND_ARG_INFO(0, skip_results)
136: ZEND_END_ARG_INFO()
137:
138: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_free_statement, 0, 0, 1)
139: ZEND_ARG_INFO(0, stmt)
140: ZEND_END_ARG_INFO()
141:
142: ZEND_BEGIN_ARG_INFO_EX(arginfo_mssql_guid_string, 0, 0, 1)
143: ZEND_ARG_INFO(0, binary)
144: ZEND_ARG_INFO(0, short_format)
145: ZEND_END_ARG_INFO()
146: /* }}} */
147:
148: /* {{{ mssql_functions
149: */
150: const zend_function_entry mssql_functions[] = {
151: PHP_FE(mssql_connect, arginfo_mssql_connect)
152: PHP_FE(mssql_pconnect, arginfo_mssql_connect)
153: PHP_FE(mssql_close, arginfo_mssql_close)
154: PHP_FE(mssql_select_db, arginfo_mssql_select_db)
155: PHP_FE(mssql_query, arginfo_mssql_query)
156: PHP_FE(mssql_fetch_batch, arginfo_mssql_fetch_batch)
157: PHP_FE(mssql_rows_affected, arginfo_mssql_rows_affected)
158: PHP_FE(mssql_free_result, arginfo_mssql_fetch_batch)
159: PHP_FE(mssql_get_last_message, arginfo_mssql_get_last_message)
160: PHP_FE(mssql_num_rows, arginfo_mssql_fetch_batch)
161: PHP_FE(mssql_num_fields, arginfo_mssql_fetch_batch)
162: PHP_FE(mssql_fetch_field, arginfo_mssql_fetch_field)
163: PHP_FE(mssql_fetch_row, arginfo_mssql_fetch_batch)
164: PHP_FE(mssql_fetch_array, arginfo_mssql_fetch_array)
165: PHP_FE(mssql_fetch_assoc, arginfo_mssql_fetch_assoc)
166: PHP_FE(mssql_fetch_object, arginfo_mssql_fetch_batch)
167: PHP_FE(mssql_field_length, arginfo_mssql_field_length)
168: PHP_FE(mssql_field_name, arginfo_mssql_field_length)
169: PHP_FE(mssql_field_type, arginfo_mssql_field_length)
170: PHP_FE(mssql_data_seek, arginfo_mssql_data_seek)
171: PHP_FE(mssql_field_seek, arginfo_mssql_fetch_field)
172: PHP_FE(mssql_result, arginfo_mssql_result)
173: PHP_FE(mssql_next_result, arginfo_mssql_fetch_assoc)
174: PHP_FE(mssql_min_error_severity, arginfo_mssql_min_error_severity)
175: PHP_FE(mssql_min_message_severity, arginfo_mssql_min_error_severity)
176: PHP_FE(mssql_init, arginfo_mssql_init)
177: PHP_FE(mssql_bind, arginfo_mssql_bind)
178: PHP_FE(mssql_execute, arginfo_mssql_execute)
179: PHP_FE(mssql_free_statement, arginfo_mssql_free_statement)
180: PHP_FE(mssql_guid_string, arginfo_mssql_guid_string)
181: PHP_FE_END
182: };
183: /* }}} */
184:
185: ZEND_DECLARE_MODULE_GLOBALS(mssql)
186: static PHP_GINIT_FUNCTION(mssql);
187:
188: /* {{{ mssql_module_entry
189: */
190: zend_module_entry mssql_module_entry =
191: {
192: STANDARD_MODULE_HEADER,
193: "mssql",
194: mssql_functions,
195: PHP_MINIT(mssql),
196: PHP_MSHUTDOWN(mssql),
197: PHP_RINIT(mssql),
198: PHP_RSHUTDOWN(mssql),
199: PHP_MINFO(mssql),
200: NO_VERSION_YET,
201: PHP_MODULE_GLOBALS(mssql),
202: PHP_GINIT(mssql),
203: NULL,
204: NULL,
205: STANDARD_MODULE_PROPERTIES_EX
206: };
207: /* }}} */
208:
209: #ifdef COMPILE_DL_MSSQL
210: ZEND_GET_MODULE(mssql)
211: #endif
212:
213: #define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } }
214:
215: /* {{{ PHP_INI_DISP
216: */
217: static PHP_INI_DISP(display_text_size)
218: {
219: char *value;
220: TSRMLS_FETCH();
221:
222: if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
223: value = ini_entry->orig_value;
224: } else if (ini_entry->value) {
225: value = ini_entry->value;
226: } else {
227: value = NULL;
228: }
229:
230: if (atoi(value) == -1) {
231: PUTS("Server default");
232: } else {
233: php_printf("%s", value);
234: }
235: }
236: /* }}} */
237:
238: /* {{{ PHP_INI
239: */
240: PHP_INI_BEGIN()
241: STD_PHP_INI_BOOLEAN("mssql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_mssql_globals, mssql_globals)
242: STD_PHP_INI_ENTRY_EX("mssql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mssql_globals, mssql_globals, display_link_numbers)
243: STD_PHP_INI_ENTRY_EX("mssql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mssql_globals, mssql_globals, display_link_numbers)
244: STD_PHP_INI_ENTRY_EX("mssql.min_error_severity", "10", PHP_INI_ALL, OnUpdateLong, cfg_min_error_severity, zend_mssql_globals, mssql_globals, display_link_numbers)
245: STD_PHP_INI_ENTRY_EX("mssql.min_message_severity", "10", PHP_INI_ALL, OnUpdateLong, cfg_min_message_severity, zend_mssql_globals, mssql_globals, display_link_numbers)
246: STD_PHP_INI_BOOLEAN("mssql.compatability_mode", "0", PHP_INI_ALL, OnUpdateBool, compatability_mode, zend_mssql_globals, mssql_globals)
247: STD_PHP_INI_ENTRY_EX("mssql.connect_timeout", "5", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mssql_globals, mssql_globals, display_link_numbers)
248: STD_PHP_INI_ENTRY_EX("mssql.timeout", "60", PHP_INI_ALL, OnUpdateLong, timeout, zend_mssql_globals, mssql_globals, display_link_numbers)
249: STD_PHP_INI_ENTRY_EX("mssql.textsize", "-1", PHP_INI_ALL, OnUpdateLong, textsize, zend_mssql_globals, mssql_globals, display_text_size)
250: STD_PHP_INI_ENTRY_EX("mssql.textlimit", "-1", PHP_INI_ALL, OnUpdateLong, textlimit, zend_mssql_globals, mssql_globals, display_text_size)
251: STD_PHP_INI_ENTRY_EX("mssql.batchsize", "0", PHP_INI_ALL, OnUpdateLong, batchsize, zend_mssql_globals, mssql_globals, display_link_numbers)
252: STD_PHP_INI_BOOLEAN("mssql.datetimeconvert", "1", PHP_INI_ALL, OnUpdateBool, datetimeconvert, zend_mssql_globals, mssql_globals)
253: STD_PHP_INI_BOOLEAN("mssql.secure_connection", "0", PHP_INI_SYSTEM, OnUpdateBool, secure_connection, zend_mssql_globals, mssql_globals)
254: STD_PHP_INI_ENTRY_EX("mssql.max_procs", "-1", PHP_INI_ALL, OnUpdateLong, max_procs, zend_mssql_globals, mssql_globals, display_link_numbers)
255: #ifdef HAVE_FREETDS
256: STD_PHP_INI_ENTRY("mssql.charset", "", PHP_INI_ALL, OnUpdateString, charset, zend_mssql_globals, mssql_globals)
257: #endif
258: PHP_INI_END()
259: /* }}} */
260:
261: /* error handler */
262: static int php_mssql_error_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
263: {
264: TSRMLS_FETCH();
265:
266: if (severity >= MS_SQL_G(min_error_severity)) {
267: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (severity %d)", dberrstr, severity);
268: }
269: return INT_CANCEL;
270: }
271:
272: /* {{{ php_mssql_message_handler
273: */
274: /* message handler */
275: static int php_mssql_message_handler(DBPROCESS *dbproc, DBINT msgno,int msgstate, int severity,char *msgtext,char *srvname, char *procname,DBUSMALLINT line)
276: {
277: TSRMLS_FETCH();
278:
279: if (severity >= MS_SQL_G(min_message_severity)) {
280: php_error_docref(NULL TSRMLS_CC, E_WARNING, "message: %s (severity %d)", msgtext, severity);
281: }
282: if (MS_SQL_G(server_message)) {
283: STR_FREE(MS_SQL_G(server_message));
284: MS_SQL_G(server_message) = NULL;
285: }
286: MS_SQL_G(server_message) = estrdup(msgtext);
287: return 0;
288: }
289: /* }}} */
290:
291: /* {{{ _clean_invalid_results
292: */
293: static int _clean_invalid_results(zend_rsrc_list_entry *le TSRMLS_DC)
294: {
295: if (Z_TYPE_P(le) == le_result) {
296: mssql_link *mssql_ptr = ((mssql_result *) le->ptr)->mssql_ptr;
297:
298: if (!mssql_ptr->valid) {
299: return 1;
300: }
301: }
302: return 0;
303: }
304: /* }}} */
305:
306: /* {{{ _free_result
307: */
308: static void _free_result(mssql_result *result, int free_fields)
309: {
310: int i,j;
311:
312: if (result->data) {
313: for (i=0; i<result->num_rows; i++) {
314: if (result->data[i]) {
315: for (j=0; j<result->num_fields; j++) {
316: zval_dtor(&result->data[i][j]);
317: }
318: efree(result->data[i]);
319: }
320: }
321: efree(result->data);
322: result->data = NULL;
323: result->blocks_initialized = 0;
324: }
325:
326: if (free_fields && result->fields) {
327: for (i=0; i<result->num_fields; i++) {
328: STR_FREE(result->fields[i].name);
329: STR_FREE(result->fields[i].column_source);
330: }
331: efree(result->fields);
332: }
333: }
334: /* }}} */
335:
336: /* {{{ _free_mssql_statement
337: */
338: static void _free_mssql_statement(zend_rsrc_list_entry *rsrc TSRMLS_DC)
339: {
340: mssql_statement *statement = (mssql_statement *)rsrc->ptr;
341:
342: if (statement->binds) {
343: zend_hash_destroy(statement->binds);
344: efree(statement->binds);
345: }
346:
347: efree(statement);
348: }
349: /* }}} */
350:
351: /* {{{ _free_mssql_result
352: */
353: static void _free_mssql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
354: {
355: mssql_result *result = (mssql_result *)rsrc->ptr;
356:
357: _free_result(result, 1);
358: dbcancel(result->mssql_ptr->link);
359: efree(result);
360: }
361: /* }}} */
362:
363: /* {{{ php_mssql_set_defaullt_link
364: */
365: static void php_mssql_set_default_link(int id TSRMLS_DC)
366: {
367: if (MS_SQL_G(default_link)!=-1) {
368: zend_list_delete(MS_SQL_G(default_link));
369: }
370: MS_SQL_G(default_link) = id;
371: zend_list_addref(id);
372: }
373: /* }}} */
374:
375: /* {{{ _close_mssql_link
376: */
377: static void _close_mssql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
378: {
379: mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
380:
381: mssql_ptr->valid = 0;
382: zend_hash_apply(&EG(regular_list),(apply_func_t) _clean_invalid_results TSRMLS_CC);
383: dbclose(mssql_ptr->link);
384: dbfreelogin(mssql_ptr->login);
385: efree(mssql_ptr);
386: MS_SQL_G(num_links)--;
387: }
388: /* }}} */
389:
390: /* {{{ _close_mssql_plink
391: */
392: static void _close_mssql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
393: {
394: mssql_link *mssql_ptr = (mssql_link *)rsrc->ptr;
395:
396: dbclose(mssql_ptr->link);
397: dbfreelogin(mssql_ptr->login);
398: free(mssql_ptr);
399: MS_SQL_G(num_persistent)--;
400: MS_SQL_G(num_links)--;
401: }
402: /* }}} */
403:
404: /* {{{ _mssql_bind_hash_dtor
405: */
406: static void _mssql_bind_hash_dtor(void *data)
407: {
408: mssql_bind *bind= (mssql_bind *) data;
409:
410: zval_ptr_dtor(&(bind->zval));
411: }
412: /* }}} */
413:
414: /* {{{ PHP_GINIT_FUNCTION
415: */
416: static PHP_GINIT_FUNCTION(mssql)
417: {
418: long compatability_mode;
419:
420: mssql_globals->num_persistent = 0;
421: mssql_globals->get_column_content = php_mssql_get_column_content_with_type;
422: if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) {
423: if (compatability_mode) {
424: mssql_globals->get_column_content = php_mssql_get_column_content_without_type;
425: }
426: }
427: }
428: /* }}} */
429:
430: /* {{{ PHP_MINIT_FUNCTION
431: */
432: PHP_MINIT_FUNCTION(mssql)
433: {
434: REGISTER_INI_ENTRIES();
435:
436: le_statement = zend_register_list_destructors_ex(_free_mssql_statement, NULL, "mssql statement", module_number);
437: le_result = zend_register_list_destructors_ex(_free_mssql_result, NULL, "mssql result", module_number);
438: le_link = zend_register_list_destructors_ex(_close_mssql_link, NULL, "mssql link", module_number);
439: le_plink = zend_register_list_destructors_ex(NULL, _close_mssql_plink, "mssql link persistent", module_number);
440: Z_TYPE(mssql_module_entry) = type;
441:
442: if (dbinit()==FAIL) {
443: return FAILURE;
444: }
445:
446: /* BEGIN MSSQL data types for mssql_bind */
447: REGISTER_LONG_CONSTANT("MSSQL_ASSOC", MSSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
448: REGISTER_LONG_CONSTANT("MSSQL_NUM", MSSQL_NUM, CONST_CS | CONST_PERSISTENT);
449: REGISTER_LONG_CONSTANT("MSSQL_BOTH", MSSQL_BOTH, CONST_CS | CONST_PERSISTENT);
450:
451: REGISTER_LONG_CONSTANT("SQLTEXT",SQLTEXT, CONST_CS | CONST_PERSISTENT);
452: REGISTER_LONG_CONSTANT("SQLVARCHAR",SQLVARCHAR, CONST_CS | CONST_PERSISTENT);
453: REGISTER_LONG_CONSTANT("SQLCHAR",SQLCHAR, CONST_CS | CONST_PERSISTENT);
454: REGISTER_LONG_CONSTANT("SQLINT1",SQLINT1, CONST_CS | CONST_PERSISTENT);
455: REGISTER_LONG_CONSTANT("SQLINT2",SQLINT2, CONST_CS | CONST_PERSISTENT);
456: REGISTER_LONG_CONSTANT("SQLINT4",SQLINT4, CONST_CS | CONST_PERSISTENT);
457: REGISTER_LONG_CONSTANT("SQLBIT",SQLBIT, CONST_CS | CONST_PERSISTENT);
458: REGISTER_LONG_CONSTANT("SQLFLT4",SQLFLT4, CONST_CS | CONST_PERSISTENT);
459: REGISTER_LONG_CONSTANT("SQLFLT8",SQLFLT8, CONST_CS | CONST_PERSISTENT);
460: REGISTER_LONG_CONSTANT("SQLFLTN",SQLFLTN, CONST_CS | CONST_PERSISTENT);
461: /* END MSSQL data types for mssql_bind */
462:
463: return SUCCESS;
464: }
465: /* }}} */
466:
467: /* {{{ PHP_MSHUTDOWN_FUNCTION
468: */
469: PHP_MSHUTDOWN_FUNCTION(mssql)
470: {
471: UNREGISTER_INI_ENTRIES();
472: #ifndef HAVE_FREETDS
473: dbwinexit();
474: #else
475: dbexit();
476: #endif
477: return SUCCESS;
478: }
479: /* }}} */
480:
481: /* {{{ PHP_RINIT_FUNCTION
482: */
483: PHP_RINIT_FUNCTION(mssql)
484: {
485: MS_SQL_G(default_link) = -1;
486: MS_SQL_G(num_links) = MS_SQL_G(num_persistent);
487: MS_SQL_G(appname) = estrndup("PHP 5", 5);
488: MS_SQL_G(server_message) = NULL;
489: MS_SQL_G(min_error_severity) = MS_SQL_G(cfg_min_error_severity);
490: MS_SQL_G(min_message_severity) = MS_SQL_G(cfg_min_message_severity);
491: if (MS_SQL_G(connect_timeout) < 1) MS_SQL_G(connect_timeout) = 1;
492: if (MS_SQL_G(timeout) < 0) MS_SQL_G(timeout) = 60;
493: if (MS_SQL_G(max_procs) != -1) {
494: dbsetmaxprocs((TDS_SHORT)MS_SQL_G(max_procs));
495: }
496:
497: return SUCCESS;
498: }
499: /* }}} */
500:
501: /* {{{ PHP_RSHUTDOWN_FUNCTION
502: */
503: PHP_RSHUTDOWN_FUNCTION(mssql)
504: {
505: STR_FREE(MS_SQL_G(appname));
506: MS_SQL_G(appname) = NULL;
507: if (MS_SQL_G(server_message)) {
508: STR_FREE(MS_SQL_G(server_message));
509: MS_SQL_G(server_message) = NULL;
510: }
511: return SUCCESS;
512: }
513: /* }}} */
514:
515: /* {{{ PHP_MINFO_FUNCTION
516: */
517: PHP_MINFO_FUNCTION(mssql)
518: {
519: char buf[32];
520:
521: php_info_print_table_start();
522: php_info_print_table_header(2, "MSSQL Support", "enabled");
523:
524: snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_persistent));
525: php_info_print_table_row(2, "Active Persistent Links", buf);
526: snprintf(buf, sizeof(buf), "%ld", MS_SQL_G(num_links));
527: php_info_print_table_row(2, "Active Links", buf);
528:
529: php_info_print_table_row(2, "Library version", MSSQL_VERSION);
530: php_info_print_table_end();
531:
532: DISPLAY_INI_ENTRIES();
533:
534: }
535: /* }}} */
536:
537: /* {{{ php_mssql_do_connect
538: */
539: static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
540: {
541: char *host = NULL, *user = NULL, *passwd = NULL;
542: int host_len = 0, user_len = 0, passwd_len = 0;
543: zend_bool new_link = 0;
544: char *hashed_details;
545: int hashed_details_length;
546: mssql_link mssql, *mssql_ptr;
547: char buffer[40];
548:
549: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssb", &host, &host_len, &user, &user_len, &passwd, &passwd_len, &new_link) == FAILURE) {
550: return;
551: }
552:
553: /* Limit strings to 255 chars to prevent overflow issues in underlying libraries */
554: if(host_len>255) {
555: host[255] = '\0';
556: }
557: if(user_len>255) {
558: user[255] = '\0';
559: }
560: if(passwd_len>255) {
561: passwd[255] = '\0';
562: }
563:
564: switch(ZEND_NUM_ARGS())
565: {
566: case 0:
567: /* defaults */
568: hashed_details_length=5+3;
569: hashed_details = (char *) emalloc(hashed_details_length+1);
570: strcpy(hashed_details, "mssql___");
571: break;
572: case 1:
573: hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s__", host);
574: break;
575: case 2:
576: hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_", host, user);
577: break;
578: case 3:
579: case 4:
580: hashed_details_length = spprintf(&hashed_details, 0, "mssql_%s_%s_%s", host, user, passwd);
581: break;
582: }
583:
584: if (hashed_details == NULL) {
585: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Out of memory");
586: RETURN_FALSE;
587: }
588:
589: dbsetlogintime(MS_SQL_G(connect_timeout));
590: dbsettime(MS_SQL_G(timeout));
591:
592: /* set a DBLOGIN record */
593: if ((mssql.login = dblogin()) == NULL) {
594: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate login record");
595: RETURN_FALSE;
596: }
597:
598: DBERRHANDLE(mssql.login, (EHANDLEFUNC) php_mssql_error_handler);
599: DBMSGHANDLE(mssql.login, (MHANDLEFUNC) php_mssql_message_handler);
600:
601: #ifndef HAVE_FREETDS
602: if (MS_SQL_G(secure_connection)){
603: DBSETLSECURE(mssql.login);
604: }
605: else {
606: #endif
607: if (user) {
608: DBSETLUSER(mssql.login,user);
609: }
610: if (passwd) {
611: DBSETLPWD(mssql.login,passwd);
612: }
613: #ifndef HAVE_FREETDS
614: }
615: #endif
616:
617: #ifdef HAVE_FREETDS
618: if (MS_SQL_G(charset) && strlen(MS_SQL_G(charset))) {
619: DBSETLCHARSET(mssql.login, MS_SQL_G(charset));
620: }
621: #endif
622:
623: DBSETLAPP(mssql.login,MS_SQL_G(appname));
624: mssql.valid = 1;
625:
626: #ifndef HAVE_FREETDS
627: DBSETLVERSION(mssql.login, DBVER60);
628: #endif
629: /* DBSETLTIME(mssql.login, TIMEOUT_INFINITE); */
630:
631: if (!MS_SQL_G(allow_persistent)) {
632: persistent=0;
633: }
634: if (persistent) {
635: zend_rsrc_list_entry *le;
636:
637: /* try to find if we already have this link in our persistent list */
638: if (new_link || zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length + 1, (void **) &le)==FAILURE) { /* we don't */
639: zend_rsrc_list_entry new_le;
640:
641: if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
642: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
643: efree(hashed_details);
644: dbfreelogin(mssql.login);
645: RETURN_FALSE;
646: }
647: if (MS_SQL_G(max_persistent) != -1 && MS_SQL_G(num_persistent) >= MS_SQL_G(max_persistent)) {
648: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MS_SQL_G(num_persistent));
649: efree(hashed_details);
650: dbfreelogin(mssql.login);
651: RETURN_FALSE;
652: }
653: /* create the link */
654: if ((mssql.link = dbopen(mssql.login, host)) == FAIL) {
655: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
656: efree(hashed_details);
657: dbfreelogin(mssql.login);
658: RETURN_FALSE;
659: }
660:
661: if (DBSETOPT(mssql.link, DBBUFFER, "2")==FAIL) {
662: efree(hashed_details);
663: dbfreelogin(mssql.login);
664: dbclose(mssql.link);
665: RETURN_FALSE;
666: }
667:
668: #ifndef HAVE_FREETDS
669: if (MS_SQL_G(textlimit) != -1) {
670: snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
671: if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
672: efree(hashed_details);
673: dbfreelogin(mssql.login);
674: dbclose(mssql.link);
675: RETURN_FALSE;
676: }
677: }
678: #endif
679: if (MS_SQL_G(textsize) != -1) {
680: snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
681: dbcmd(mssql.link, buffer);
682: dbsqlexec(mssql.link);
683: dbresults(mssql.link);
684: }
685:
686: /* hash it up */
687: mssql_ptr = (mssql_link *) malloc(sizeof(mssql_link));
688: if (!mssql_ptr) {
689: efree(hashed_details);
690: dbfreelogin(mssql.login);
691: dbclose(mssql.link);
692: RETURN_FALSE;
693: }
694:
695: memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
696: Z_TYPE(new_le) = le_plink;
697: new_le.ptr = mssql_ptr;
698: if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length + 1, &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
699: free(mssql_ptr);
700: efree(hashed_details);
701: dbfreelogin(mssql.login);
702: dbclose(mssql.link);
703: RETURN_FALSE;
704: }
705: MS_SQL_G(num_persistent)++;
706: MS_SQL_G(num_links)++;
707: } else { /* we do */
708: if (Z_TYPE_P(le) != le_plink) {
709: #if BROKEN_MSSQL_PCONNECTS
710: log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server);
711: #endif
712: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!");
713: efree(hashed_details);
714: RETURN_FALSE;
715: }
716:
717: mssql_ptr = (mssql_link *) le->ptr;
718: /* test that the link hasn't died */
719: if (DBDEAD(mssql_ptr->link) == TRUE) {
720: dbclose(mssql_ptr->link);
721: #if BROKEN_MSSQL_PCONNECTS
722: log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server);
723: #endif
724: if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) {
725: #if BROKEN_MSSQL_PCONNECTS
726: log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server);
727: #endif
728: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
729: zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
730: efree(hashed_details);
731: dbfreelogin(mssql_ptr->login);
732: RETURN_FALSE;
733: }
734: #if BROKEN_MSSQL_PCONNECTS
735: log_error("PHP/MS SQL: Reconnect successful!",php_rqst->server);
736: #endif
737: if (DBSETOPT(mssql_ptr->link, DBBUFFER, "2")==FAIL) {
738: #if BROKEN_MSSQL_PCONNECTS
739: log_error("PHP/MS SQL: Unable to set required options",php_rqst->server);
740: #endif
741: zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length + 1);
742: efree(hashed_details);
743: dbfreelogin(mssql_ptr->login);
744: dbclose(mssql_ptr->link);
745: RETURN_FALSE;
746: }
747: }
748: }
749: ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_plink);
750: } else { /* non persistent */
751: zend_rsrc_list_entry *index_ptr, new_index_ptr;
752:
753: /* first we check the hash for the hashed_details key. if it exists,
754: * it should point us to the right offset where the actual mssql link sits.
755: * if it doesn't, open a new mssql link, add it to the resource list,
756: * and add a pointer to it with hashed_details as the key.
757: */
758: if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length + 1,(void **) &index_ptr)==SUCCESS) {
759: int type,link;
760: void *ptr;
761:
762: if (Z_TYPE_P(index_ptr) != le_index_ptr) {
763: efree(hashed_details);
764: dbfreelogin(mssql.login);
765: RETURN_FALSE;
766: }
767: link = (int) index_ptr->ptr;
768: ptr = zend_list_find(link,&type); /* check if the link is still there */
769: if (ptr && (type==le_link || type==le_plink)) {
770: zend_list_addref(link);
771: Z_LVAL_P(return_value) = link;
772: php_mssql_set_default_link(link TSRMLS_CC);
773: Z_TYPE_P(return_value) = IS_RESOURCE;
774: dbfreelogin(mssql.login);
775: efree(hashed_details);
776: return;
777: } else {
778: zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length + 1);
779: }
780: }
781: if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) {
782: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links));
783: efree(hashed_details);
784: dbfreelogin(mssql.login);
785: RETURN_FALSE;
786: }
787:
788: if ((mssql.link=dbopen(mssql.login, host))==NULL) {
789: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", (host == NULL ? "" : host));
790: efree(hashed_details);
791: dbfreelogin(mssql.login);
792: RETURN_FALSE;
793: }
794:
795: if (DBSETOPT(mssql.link, DBBUFFER,"2")==FAIL) {
796: efree(hashed_details);
797: dbfreelogin(mssql.login);
798: dbclose(mssql.link);
799: RETURN_FALSE;
800: }
801:
802: #ifndef HAVE_FREETDS
803: if (MS_SQL_G(textlimit) != -1) {
804: snprintf(buffer, sizeof(buffer), "%li", MS_SQL_G(textlimit));
805: if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) {
806: efree(hashed_details);
807: dbfreelogin(mssql.login);
808: dbclose(mssql.link);
809: RETURN_FALSE;
810: }
811: }
812: #endif
813: if (MS_SQL_G(textsize) != -1) {
814: snprintf(buffer, sizeof(buffer), "SET TEXTSIZE %li", MS_SQL_G(textsize));
815: dbcmd(mssql.link, buffer);
816: dbsqlexec(mssql.link);
817: dbresults(mssql.link);
818: }
819:
820: /* add it to the list */
821: mssql_ptr = (mssql_link *) emalloc(sizeof(mssql_link));
822: memcpy(mssql_ptr, &mssql, sizeof(mssql_link));
823: ZEND_REGISTER_RESOURCE(return_value, mssql_ptr, le_link);
824:
825: /* add it to the hash */
826: new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
827: Z_TYPE(new_index_ptr) = le_index_ptr;
828: if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length + 1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry),NULL)==FAILURE) {
829: efree(hashed_details);
830: RETURN_FALSE;
831: }
832: MS_SQL_G(num_links)++;
833: }
834: efree(hashed_details);
835: php_mssql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
836: }
837: /* }}} */
838:
839: /* {{{ php_mssql_get_default_link
840: */
841: static int php_mssql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
842: {
843: if (MS_SQL_G(default_link)==-1) { /* no link opened yet, implicitly open one */
844: ht = 0;
845: php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
846: }
847: return MS_SQL_G(default_link);
848: }
849: /* }}} */
850:
851: /* {{{ proto int mssql_connect([string servername [, string username [, string password [, bool new_link]]]])
852: Establishes a connection to a MS-SQL server */
853: PHP_FUNCTION(mssql_connect)
854: {
855: php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
856: }
857: /* }}} */
858:
859: /* {{{ proto int mssql_pconnect([string servername [, string username [, string password [, bool new_link]]]])
860: Establishes a persistent connection to a MS-SQL server */
861: PHP_FUNCTION(mssql_pconnect)
862: {
863: php_mssql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
864: }
865: /* }}} */
866:
867: /* {{{ proto bool mssql_close([resource conn_id])
868: Closes a connection to a MS-SQL server */
869: PHP_FUNCTION(mssql_close)
870: {
871: zval *mssql_link_index = NULL;
872: int id = -1;
873: mssql_link *mssql_ptr;
874:
875: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mssql_link_index) == FAILURE) {
876: return;
877: }
878:
879: if (mssql_link_index == NULL) {
880: id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
881: CHECK_LINK(id);
882: }
883:
884: ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
885:
886: if (mssql_link_index) {
887: zend_list_delete(Z_RESVAL_P(mssql_link_index));
888: } else {
889: zend_list_delete(id);
890: }
891:
892: RETURN_TRUE;
893: }
894: /* }}} */
895:
896: /* {{{ proto bool mssql_select_db(string database_name [, resource conn_id])
897: Select a MS-SQL database */
898: PHP_FUNCTION(mssql_select_db)
899: {
900: char *db;
901: zval *mssql_link_index = NULL;
902: int db_len;
903: int id = -1;
904: mssql_link *mssql_ptr;
905:
906: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &db, &db_len, &mssql_link_index) == FAILURE) {
907: return;
908: }
909:
910: if (mssql_link_index == NULL) {
911: id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
912: CHECK_LINK(id);
913: }
914:
915: ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
916:
917: if (dbuse(mssql_ptr->link, db)==FAIL) {
918: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to select database: %s", db);
919: RETURN_FALSE;
920: } else {
921: RETURN_TRUE;
922: }
923: }
924: /* }}} */
925:
926: /* {{{ php_mssql_get_column_content_with_type
927: */
928: static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
929: {
930: if (dbdata(mssql_ptr->link,offset) == NULL && dbdatlen(mssql_ptr->link,offset) == 0) {
931: ZVAL_NULL(result);
932: return;
933: }
934:
935: switch (column_type)
936: {
937: case SQLBIT:
938: case SQLINT1:
939: case SQLINT2:
940: case SQLINT4:
941: case SQLINTN: {
942: ZVAL_LONG(result, (long) anyintcol(offset));
943: break;
944: }
945: case SQLCHAR:
946: case SQLVARCHAR:
947: case SQLTEXT: {
948: int length;
949: char *data = charcol(offset);
950:
951: length=dbdatlen(mssql_ptr->link,offset);
952: #if ilia_0
953: while (length>0 && data[length-1] == ' ') { /* nuke trailing whitespace */
954: length--;
955: }
956: #endif
957: ZVAL_STRINGL(result, data, length, 1);
958: break;
959: }
960: case SQLFLT4:
961: ZVAL_DOUBLE(result, (double) floatcol4(offset));
962: break;
963: case SQLMONEY:
964: case SQLMONEY4:
965: case SQLMONEYN: {
966: DBFLT8 res_buf;
967: dbconvert(NULL, column_type, dbdata(mssql_ptr->link,offset), 8, SQLFLT8, (LPBYTE)&res_buf, -1);
968: ZVAL_DOUBLE(result, res_buf);
969: }
970: break;
971: case SQLFLT8:
972: ZVAL_DOUBLE(result, (double) floatcol8(offset));
973: break;
974: #ifdef SQLUNIQUE
975: case SQLUNIQUE: {
976: #else
977: case 36: { /* FreeTDS hack */
978: #endif
979: char *data = charcol(offset);
980:
981: /* uniqueidentifier is a 16-byte binary number */
982: ZVAL_STRINGL(result, data, 16, 1);
983: }
984: break;
985: case SQLVARBINARY:
986: case SQLBINARY:
987: case SQLIMAGE: {
988: int res_length = dbdatlen(mssql_ptr->link, offset);
989:
990: if (!res_length) {
991: ZVAL_NULL(result);
992: } else {
993: ZVAL_STRINGL(result, (char *)dbdata(mssql_ptr->link, offset), res_length, 1);
994: }
995: }
996: break;
997: case SQLNUMERIC:
998: default: {
999: if (dbwillconvert(column_type,SQLCHAR)) {
1000: char *res_buf;
1001: DBDATEREC dateinfo;
1002: int res_length = dbdatlen(mssql_ptr->link,offset);
1003:
1004: if (res_length == -1) {
1005: res_length = 255;
1006: }
1007:
1008: if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
1009:
1010: switch (column_type) {
1011: case SQLDATETIME :
1012: case SQLDATETIM4 :
1013: res_length += 20;
1014: break;
1015: case SQLMONEY :
1016: case SQLMONEY4 :
1017: case SQLMONEYN :
1018: case SQLDECIMAL :
1019: case SQLNUMERIC :
1020: res_length += 5;
1021: case 127 :
1022: res_length += 20;
1023: break;
1024: }
1025:
1026: res_buf = (unsigned char *) emalloc(res_length+1);
1027: res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1);
1028: res_buf[res_length] = '\0';
1029: } else {
1030: if (column_type == SQLDATETIM4) {
1031: DBDATETIME temp;
1032:
1033: dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
1034: dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
1035: } else {
1036: dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
1037: }
1038:
1039: res_length = 19;
1040: spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
1041: }
1042:
1043: ZVAL_STRINGL(result, res_buf, res_length, 0);
1044: } else {
1045: php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
1046: ZVAL_FALSE(result);
1047: }
1048: }
1049: }
1050: }
1051: /* }}} */
1052:
1053: /* {{{ php_mssql_get_column_content_without_type
1054: */
1055: static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int offset,zval *result, int column_type TSRMLS_DC)
1056: {
1057: if (dbdatlen(mssql_ptr->link,offset) == 0) {
1058: ZVAL_NULL(result);
1059: return;
1060: }
1061:
1062: if (column_type == SQLVARBINARY ||
1063: column_type == SQLBINARY ||
1064: column_type == SQLIMAGE) {
1065: DBBINARY *bin;
1066: unsigned char *res_buf;
1067: int res_length = dbdatlen(mssql_ptr->link, offset);
1068:
1069: if (res_length == 0) {
1070: ZVAL_NULL(result);
1071: return;
1072: } else if (res_length < 0) {
1073: ZVAL_FALSE(result);
1074: return;
1075: }
1076:
1077: res_buf = (unsigned char *) emalloc(res_length+1);
1078: bin = ((DBBINARY *)dbdata(mssql_ptr->link, offset));
1079: res_buf[res_length] = '\0';
1080: memcpy(res_buf, bin, res_length);
1081: ZVAL_STRINGL(result, res_buf, res_length, 0);
1082: }
1083: else if (dbwillconvert(coltype(offset),SQLCHAR)) {
1084: unsigned char *res_buf;
1085: DBDATEREC dateinfo;
1086: int res_length = dbdatlen(mssql_ptr->link,offset);
1087:
1088: if ((column_type != SQLDATETIME && column_type != SQLDATETIM4) || MS_SQL_G(datetimeconvert)) {
1089:
1090: switch (column_type) {
1091: case SQLDATETIME :
1092: case SQLDATETIM4 :
1093: res_length += 20;
1094: break;
1095: case SQLMONEY :
1096: case SQLMONEY4 :
1097: case SQLMONEYN :
1098: case SQLDECIMAL :
1099: case SQLNUMERIC :
1100: res_length += 5;
1101: case 127 :
1102: res_length += 20;
1103: break;
1104: }
1105:
1106: res_buf = (unsigned char *) emalloc(res_length+1);
1107: res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR, res_buf, -1);
1108: res_buf[res_length] = '\0';
1109: } else {
1110: if (column_type == SQLDATETIM4) {
1111: DBDATETIME temp;
1112:
1113: dbconvert(NULL, SQLDATETIM4, dbdata(mssql_ptr->link,offset), -1, SQLDATETIME, (LPBYTE) &temp, -1);
1114: dbdatecrack(mssql_ptr->link, &dateinfo, &temp);
1115: } else {
1116: dbdatecrack(mssql_ptr->link, &dateinfo, (DBDATETIME *) dbdata(mssql_ptr->link,offset));
1117: }
1118:
1119: res_length = 19;
1120: spprintf(&res_buf, 0, "%d-%02d-%02d %02d:%02d:%02d" , dateinfo.year, dateinfo.month, dateinfo.day, dateinfo.hour, dateinfo.minute, dateinfo.second);
1121: }
1122:
1123: ZVAL_STRINGL(result, res_buf, res_length, 0);
1124: } else {
1125: php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d has unknown data type (%d)", offset, coltype(offset));
1126: ZVAL_FALSE(result);
1127: }
1128: }
1129: /* }}} */
1130:
1131: /* {{{ _mssql_get_sp_result
1132: */
1133: static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *statement TSRMLS_DC)
1134: {
1135: int i, num_rets, type;
1136: char *parameter;
1137: mssql_bind *bind;
1138:
1139: /* Now to fetch RETVAL and OUTPUT values*/
1140: num_rets = dbnumrets(mssql_ptr->link);
1141:
1142: if (num_rets!=0) {
1143: for (i = 1; i <= num_rets; i++) {
1144: parameter = (char*)dbretname(mssql_ptr->link, i);
1145: type = dbrettype(mssql_ptr->link, i);
1146:
1147: if (statement->binds != NULL) { /* Maybe a non-parameter sp */
1148: if (zend_hash_find(statement->binds, parameter, strlen(parameter), (void**)&bind)==SUCCESS) {
1149: if (!dbretlen(mssql_ptr->link,i)) {
1150: ZVAL_NULL(bind->zval);
1151: }
1152: else {
1153: switch (type) {
1154: case SQLBIT:
1155: case SQLINT1:
1156: case SQLINT2:
1157: case SQLINT4:
1158: convert_to_long_ex(&bind->zval);
1159: /* FIXME this works only on little endian machine !!! */
1160: Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
1161: break;
1162:
1163: case SQLFLT4:
1164: case SQLFLT8:
1165: case SQLFLTN:
1166: case SQLMONEY4:
1167: case SQLMONEY:
1168: case SQLMONEYN:
1169: convert_to_double_ex(&bind->zval);
1170: Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
1171: break;
1172:
1173: case SQLCHAR:
1174: case SQLVARCHAR:
1175: case SQLTEXT:
1176: convert_to_string_ex(&bind->zval);
1177: Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
1178: Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
1179: break;
1180: /* TODO binary */
1181: }
1182: }
1183: }
1184: else {
1185: php_error_docref(NULL TSRMLS_CC, E_WARNING, "An output parameter variable was not provided");
1186: }
1187: }
1188: }
1189: }
1190: if (statement->binds != NULL) { /* Maybe a non-parameter sp */
1191: if (zend_hash_find(statement->binds, "RETVAL", 6, (void**)&bind)==SUCCESS) {
1192: if (dbhasretstat(mssql_ptr->link)) {
1193: convert_to_long_ex(&bind->zval);
1194: Z_LVAL_P(bind->zval)=dbretstatus(mssql_ptr->link);
1195: }
1196: else {
1197: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure has no return value. Nothing was returned into RETVAL");
1198: }
1199: }
1200: }
1201: }
1202: /* }}} */
1203:
1204: /* {{{ _mssql_fetch_batch
1205: */
1206: static int _mssql_fetch_batch(mssql_link *mssql_ptr, mssql_result *result, int retvalue TSRMLS_DC)
1207: {
1208: int i, j = 0;
1209: char computed_buf[16];
1210:
1211: if (!result->have_fields) {
1212: for (i=0; i<result->num_fields; i++) {
1213: char *source = NULL;
1214: char *fname = (char *)dbcolname(mssql_ptr->link,i+1);
1215:
1216: if (*fname) {
1217: result->fields[i].name = estrdup(fname);
1218: } else {
1219: if (j>0) {
1220: snprintf(computed_buf,16,"computed%d",j);
1221: } else {
1222: strcpy(computed_buf,"computed");
1223: }
1224: result->fields[i].name = estrdup(computed_buf);
1225: j++;
1226: }
1227: result->fields[i].max_length = dbcollen(mssql_ptr->link,i+1);
1228: source = (char *)dbcolsource(mssql_ptr->link,i+1);
1229: if (source) {
1230: result->fields[i].column_source = estrdup(source);
1231: }
1232: else {
1233: result->fields[i].column_source = STR_EMPTY_ALLOC();
1234: }
1235:
1236: result->fields[i].type = coltype(i+1);
1237: /* set numeric flag */
1238: switch (result->fields[i].type) {
1239: case SQLINT1:
1240: case SQLINT2:
1241: case SQLINT4:
1242: case SQLINTN:
1243: case SQLFLT4:
1244: case SQLFLT8:
1245: case SQLNUMERIC:
1246: case SQLDECIMAL:
1247: result->fields[i].numeric = 1;
1248: break;
1249: case SQLCHAR:
1250: case SQLVARCHAR:
1251: case SQLTEXT:
1252: default:
1253: result->fields[i].numeric = 0;
1254: break;
1255: }
1256: }
1257: result->have_fields = 1;
1258: }
1259:
1260: i=0;
1261: if (!result->data) {
1262: result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK*(++result->blocks_initialized), 0);
1263: }
1264: while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
1265: result->num_rows++;
1266: if (result->num_rows > result->blocks_initialized*MSSQL_ROWS_BLOCK) {
1267: result->data = (zval **) erealloc(result->data,sizeof(zval *)*MSSQL_ROWS_BLOCK*(++result->blocks_initialized));
1268: }
1269: result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0);
1270: for (j=0; j<result->num_fields; j++) {
1271: INIT_ZVAL(result->data[i][j]);
1272: MS_SQL_G(get_column_content(mssql_ptr, j+1, &result->data[i][j], result->fields[j].type TSRMLS_CC));
1273: }
1274: if (i<result->batchsize || result->batchsize==0) {
1275: i++;
1276: dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
1277: retvalue=dbnextrow(mssql_ptr->link);
1278: }
1279: else
1280: break;
1281: result->lastresult = retvalue;
1282: }
1283: if (result->statement && (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS)) {
1284: _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
1285: }
1286: return i;
1287: }
1288: /* }}} */
1289:
1290: /* {{{ proto int mssql_fetch_batch(resource result_index)
1291: Returns the next batch of records */
1292: PHP_FUNCTION(mssql_fetch_batch)
1293: {
1294: zval *mssql_result_index;
1295: mssql_result *result;
1296: mssql_link *mssql_ptr;
1297:
1298: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1299: return;
1300: }
1301:
1302: if (Z_RESVAL_P(mssql_result_index) == 0) {
1303: RETURN_FALSE;
1304: }
1305:
1306: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1307:
1308: mssql_ptr = result->mssql_ptr;
1309: _free_result(result, 0);
1310: result->cur_row=result->num_rows=0;
1311: result->num_rows = _mssql_fetch_batch(mssql_ptr, result, result->lastresult TSRMLS_CC);
1312:
1313: RETURN_LONG(result->num_rows);
1314: }
1315: /* }}} */
1316:
1317: /* {{{ proto resource mssql_query(string query [, resource conn_id [, int batch_size]])
1318: Perform an SQL query on a MS-SQL server database */
1319: PHP_FUNCTION(mssql_query)
1320: {
1321: char *query;
1322: zval *mssql_link_index = NULL;
1323: int query_len, retvalue, batchsize, num_fields;
1324: long zbatchsize = 0;
1325: mssql_link *mssql_ptr;
1326: mssql_result *result;
1327: int id = -1;
1328:
1329: dbsettime(MS_SQL_G(timeout));
1330: batchsize = MS_SQL_G(batchsize);
1331:
1332: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|rl", &query, &query_len, &mssql_link_index, &zbatchsize) == FAILURE) {
1333: return;
1334: }
1335:
1336: switch(ZEND_NUM_ARGS()) {
1337: case 1:
1338: id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1339: CHECK_LINK(id);
1340: break;
1341: case 3:
1342: batchsize = (int) zbatchsize;
1343: break;
1344: }
1345:
1346: ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
1347:
1348: if (dbcmd(mssql_ptr->link, query)==FAIL) {
1349: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set query");
1350: RETURN_FALSE;
1351: }
1352: if (dbsqlexec(mssql_ptr->link)==FAIL || (retvalue = dbresults(mssql_ptr->link))==FAIL) {
1353: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed");
1354: dbcancel(mssql_ptr->link);
1355: RETURN_FALSE;
1356: }
1357:
1358: /* Skip results not returning any columns */
1359: while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) {
1360: retvalue = dbresults(mssql_ptr->link);
1361: }
1362:
1363: if (num_fields <= 0) {
1364: RETURN_TRUE;
1365: }
1366:
1367: retvalue=dbnextrow(mssql_ptr->link);
1368: if (retvalue==FAIL) {
1369: dbcancel(mssql_ptr->link);
1370: RETURN_FALSE;
1371: }
1372:
1373: result = (mssql_result *) emalloc(sizeof(mssql_result));
1374: result->statement = NULL;
1375: result->num_fields = num_fields;
1376: result->blocks_initialized = 1;
1377:
1378: result->batchsize = batchsize;
1379: result->data = NULL;
1380: result->blocks_initialized = 0;
1381: result->mssql_ptr = mssql_ptr;
1382: result->cur_field=result->cur_row=result->num_rows=0;
1383: result->have_fields = 0;
1384:
1385: result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
1386: result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
1387:
1388: ZEND_REGISTER_RESOURCE(return_value, result, le_result);
1389: }
1390: /* }}} */
1391:
1392: /* {{{ proto int mssql_rows_affected(resource conn_id)
1393: Returns the number of records affected by the query */
1394: PHP_FUNCTION(mssql_rows_affected)
1395: {
1396: zval *mssql_link_index;
1397: mssql_link *mssql_ptr;
1398:
1399: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_link_index) == FAILURE) {
1400: return;
1401: }
1402:
1403: ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, -1, "MS SQL-Link", le_link, le_plink);
1404:
1405: RETURN_LONG(DBCOUNT(mssql_ptr->link));
1406: }
1407: /* }}} */
1408:
1409: /* {{{ proto bool mssql_free_result(resource result_index)
1410: Free a MS-SQL result index */
1411: PHP_FUNCTION(mssql_free_result)
1412: {
1413: zval *mssql_result_index;
1414: mssql_result *result;
1415: int retvalue;
1416:
1417: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1418: return;
1419: }
1420:
1421: if (Z_RESVAL_P(mssql_result_index) == 0) {
1422: RETURN_FALSE;
1423: }
1424:
1425: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1426: /* Release remaining results */
1427: do {
1428: dbcanquery(result->mssql_ptr->link);
1429: retvalue = dbresults(result->mssql_ptr->link);
1430: } while (retvalue == SUCCEED);
1431:
1432: zend_list_delete(Z_RESVAL_P(mssql_result_index));
1433: RETURN_TRUE;
1434: }
1435: /* }}} */
1436:
1437: /* {{{ proto string mssql_get_last_message(void)
1438: Gets the last message from the MS-SQL server */
1439: PHP_FUNCTION(mssql_get_last_message)
1440: {
1441: if (zend_parse_parameters_none() == FAILURE) {
1442: return;
1443: }
1444:
1445: if (MS_SQL_G(server_message)) {
1446: RETURN_STRING(MS_SQL_G(server_message),1);
1447: } else {
1448: RETURN_STRING("",1);
1449: }
1450: }
1451: /* }}} */
1452:
1453: /* {{{ proto int mssql_num_rows(resource mssql_result_index)
1454: Returns the number of rows fetched in from the result id specified */
1455: PHP_FUNCTION(mssql_num_rows)
1456: {
1457: zval *mssql_result_index;
1458: mssql_result *result;
1459:
1460: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1461: return;
1462: }
1463:
1464: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1465:
1466: RETURN_LONG(result->num_rows);
1467: }
1468: /* }}} */
1469:
1470: /* {{{ proto int mssql_num_fields(resource mssql_result_index)
1471: Returns the number of fields fetched in from the result id specified */
1472: PHP_FUNCTION(mssql_num_fields)
1473: {
1474: zval *mssql_result_index;
1475: mssql_result *result;
1476:
1477: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1478: return;
1479: }
1480:
1481: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1482:
1483: RETURN_LONG(result->num_fields);
1484: }
1485: /* }}} */
1486:
1487: /* {{{ php_mssql_fetch_hash
1488: */
1489: static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
1490: {
1491: zval *mssql_result_index;
1492: mssql_result *result;
1493: int i;
1494: long resulttype = 0;
1495:
1496: switch (result_type) {
1497: case MSSQL_NUM:
1498: case MSSQL_ASSOC:
1499: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1500: return;
1501: }
1502: break;
1503: case MSSQL_BOTH:
1504: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &resulttype) == FAILURE) {
1505: return;
1506: }
1507: result_type = (resulttype > 0 && (resulttype & MSSQL_BOTH)) ? resulttype : result_type;
1508: break;
1509: default:
1510: return;
1511: }
1512:
1513: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1514:
1515: if (MS_SQL_G(server_message)) {
1516: STR_FREE(MS_SQL_G(server_message));
1517: MS_SQL_G(server_message) = NULL;
1518: }
1519:
1520: if (result->cur_row >= result->num_rows) {
1521: RETURN_FALSE;
1522: }
1523:
1524: array_init(return_value);
1525:
1526: for (i=0; i<result->num_fields; i++) {
1527: if (Z_TYPE(result->data[result->cur_row][i]) != IS_NULL) {
1528: char *data;
1529: int data_len;
1530:
1531: if (Z_TYPE(result->data[result->cur_row][i]) == IS_STRING) {
1.1.1.2 ! misho 1532: data = Z_STRVAL(result->data[result->cur_row][i]);
! 1533: data_len = Z_STRLEN(result->data[result->cur_row][i]);
1.1 misho 1534:
1535: if (result_type & MSSQL_NUM) {
1.1.1.2 ! misho 1536: add_index_stringl(return_value, i, data, data_len, 1);
1.1 misho 1537: }
1538:
1539: if (result_type & MSSQL_ASSOC) {
1.1.1.2 ! misho 1540: add_assoc_stringl(return_value, result->fields[i].name, data, data_len, 1);
1.1 misho 1541: }
1542: }
1543: else if (Z_TYPE(result->data[result->cur_row][i]) == IS_LONG) {
1544: if (result_type & MSSQL_NUM)
1545: add_index_long(return_value, i, Z_LVAL(result->data[result->cur_row][i]));
1546:
1547: if (result_type & MSSQL_ASSOC)
1548: add_assoc_long(return_value, result->fields[i].name, Z_LVAL(result->data[result->cur_row][i]));
1549: }
1550: else if (Z_TYPE(result->data[result->cur_row][i]) == IS_DOUBLE) {
1551: if (result_type & MSSQL_NUM)
1552: add_index_double(return_value, i, Z_DVAL(result->data[result->cur_row][i]));
1553:
1554: if (result_type & MSSQL_ASSOC)
1555: add_assoc_double(return_value, result->fields[i].name, Z_DVAL(result->data[result->cur_row][i]));
1556: }
1557: }
1558: else
1559: {
1560: if (result_type & MSSQL_NUM)
1561: add_index_null(return_value, i);
1562: if (result_type & MSSQL_ASSOC)
1563: add_assoc_null(return_value, result->fields[i].name);
1564: }
1565: }
1566: result->cur_row++;
1567: }
1568: /* }}} */
1569:
1570: /* {{{ proto array mssql_fetch_row(resource result_id)
1571: Returns an array of the current row in the result set specified by result_id */
1572: PHP_FUNCTION(mssql_fetch_row)
1573: {
1574: php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_NUM);
1575: }
1576: /* }}} */
1577:
1578: /* {{{ proto object mssql_fetch_object(resource result_id)
1579: Returns a pseudo-object of the current row in the result set specified by result_id */
1580: PHP_FUNCTION(mssql_fetch_object)
1581: {
1582: php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
1583: if (Z_TYPE_P(return_value)==IS_ARRAY) {
1584: object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
1585: }
1586: }
1587: /* }}} */
1588:
1589: /* {{{ proto array mssql_fetch_array(resource result_id [, int result_type])
1590: Returns an associative array of the current row in the result set specified by result_id */
1591: PHP_FUNCTION(mssql_fetch_array)
1592: {
1593: php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_BOTH);
1594: }
1595: /* }}} */
1596:
1597: /* {{{ proto array mssql_fetch_assoc(resource result_id)
1598: Returns an associative array of the current row in the result set specified by result_id */
1599: PHP_FUNCTION(mssql_fetch_assoc)
1600: {
1601: php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MSSQL_ASSOC);
1602: }
1603: /* }}} */
1604:
1605: /* {{{ proto bool mssql_data_seek(resource result_id, int offset)
1606: Moves the internal row pointer of the MS-SQL result associated with the specified result identifier to pointer to the specified row number */
1607: PHP_FUNCTION(mssql_data_seek)
1608: {
1609: zval *mssql_result_index;
1610: long offset;
1611: mssql_result *result;
1612:
1613: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &offset) == FAILURE) {
1614: return;
1615: }
1616:
1617: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1618:
1619: if (offset < 0 || offset >= result->num_rows) {
1620: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset");
1621: RETURN_FALSE;
1622: }
1623:
1624: result->cur_row = offset;
1625: RETURN_TRUE;
1626: }
1627: /* }}} */
1628:
1629: /* {{{ php_mssql_get_field_name
1630: */
1631: static char *php_mssql_get_field_name(int type)
1632: {
1633: switch (type) {
1634: case SQLBINARY:
1635: case SQLVARBINARY:
1636: return "blob";
1637: break;
1638: case SQLCHAR:
1639: case SQLVARCHAR:
1640: return "char";
1641: break;
1642: case SQLTEXT:
1643: return "text";
1644: break;
1645: case SQLDATETIME:
1646: case SQLDATETIM4:
1647: case SQLDATETIMN:
1648: return "datetime";
1649: break;
1650: case SQLDECIMAL:
1651: case SQLFLT4:
1652: case SQLFLT8:
1653: case SQLFLTN:
1654: return "real";
1655: break;
1656: case SQLINT1:
1657: case SQLINT2:
1658: case SQLINT4:
1659: case SQLINTN:
1660: return "int";
1661: break;
1662: case SQLNUMERIC:
1663: return "numeric";
1664: break;
1665: case SQLMONEY:
1666: case SQLMONEY4:
1667: case SQLMONEYN:
1668: return "money";
1669: break;
1670: case SQLBIT:
1671: return "bit";
1672: break;
1673: case SQLIMAGE:
1674: return "image";
1675: break;
1676: #ifdef SQLUNIQUE
1677: case SQLUNIQUE:
1678: return "uniqueidentifier";
1679: break;
1680: #endif
1681: default:
1682: return "unknown";
1683: break;
1684: }
1685: }
1686: /* }}} */
1687:
1688: /* {{{ proto object mssql_fetch_field(resource result_id [, int offset])
1689: Gets information about certain fields in a query result */
1690: PHP_FUNCTION(mssql_fetch_field)
1691: {
1692: zval *mssql_result_index;
1693: long field_offset = -1;
1694: mssql_result *result;
1695:
1696: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
1697: return;
1698: }
1699:
1700: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1701:
1702: if (field_offset==-1) {
1703: field_offset = result->cur_field;
1704: result->cur_field++;
1705: }
1706:
1707: if (field_offset<0 || field_offset >= result->num_fields) {
1708: if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
1709: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
1710: }
1711: RETURN_FALSE;
1712: }
1713:
1714: object_init(return_value);
1715:
1716: add_property_string(return_value, "name",result->fields[field_offset].name, 1);
1717: add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
1718: add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
1719: add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
1720: add_property_string(return_value, "type", php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), 1);
1721: }
1722: /* }}} */
1723:
1724: /* {{{ proto int mssql_field_length(resource result_id [, int offset])
1725: Get the length of a MS-SQL field */
1726: PHP_FUNCTION(mssql_field_length)
1727: {
1728: zval *mssql_result_index;
1729: long field_offset = -1;
1730: mssql_result *result;
1731:
1732: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
1733: return;
1734: }
1735:
1736: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1737:
1738: if (field_offset==-1) {
1739: field_offset = result->cur_field;
1740: result->cur_field++;
1741: }
1742:
1743: if (field_offset<0 || field_offset >= result->num_fields) {
1744: if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
1745: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
1746: }
1747: RETURN_FALSE;
1748: }
1749:
1750: RETURN_LONG(result->fields[field_offset].max_length);
1751: }
1752: /* }}} */
1753:
1754: /* {{{ proto string mssql_field_name(resource result_id [, int offset])
1755: Returns the name of the field given by offset in the result set given by result_id */
1756: PHP_FUNCTION(mssql_field_name)
1757: {
1758: zval *mssql_result_index;
1759: long field_offset = -1;
1760: mssql_result *result;
1761:
1762: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
1763: return;
1764: }
1765:
1766: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1767:
1768: if (field_offset==-1) {
1769: field_offset = result->cur_field;
1770: result->cur_field++;
1771: }
1772:
1773: if (field_offset<0 || field_offset >= result->num_fields) {
1774: if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
1775: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
1776: }
1777: RETURN_FALSE;
1778: }
1779:
1780: RETURN_STRINGL(result->fields[field_offset].name, strlen(result->fields[field_offset].name), 1);
1781: }
1782: /* }}} */
1783:
1784: /* {{{ proto string mssql_field_type(resource result_id [, int offset])
1785: Returns the type of a field */
1786: PHP_FUNCTION(mssql_field_type)
1787: {
1788: zval *mssql_result_index;
1789: long field_offset = -1;
1790: mssql_result *result;
1791:
1792: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &mssql_result_index, &field_offset) == FAILURE) {
1793: return;
1794: }
1795:
1796: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1797:
1798: if (field_offset==-1) {
1799: field_offset = result->cur_field;
1800: result->cur_field++;
1801: }
1802:
1803: if (field_offset<0 || field_offset >= result->num_fields) {
1804: if (ZEND_NUM_ARGS()==2) { /* field specified explicitly */
1805: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
1806: }
1807: RETURN_FALSE;
1808: }
1809:
1810: RETURN_STRINGL(php_mssql_get_field_name(Z_TYPE(result->fields[field_offset])), strlen(php_mssql_get_field_name(Z_TYPE(result->fields[field_offset]))), 1);
1811: }
1812: /* }}} */
1813:
1814: /* {{{ proto bool mssql_field_seek(resource result_id, int offset)
1815: Seeks to the specified field offset */
1816: PHP_FUNCTION(mssql_field_seek)
1817: {
1818: zval *mssql_result_index;
1819: long field_offset;
1820: mssql_result *result;
1821:
1822: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &mssql_result_index, &field_offset) == FAILURE) {
1823: return;
1824: }
1825:
1826: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1827:
1828: if (field_offset<0 || field_offset >= result->num_fields) {
1829: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset");
1830: RETURN_FALSE;
1831: }
1832:
1833: result->cur_field = field_offset;
1834: RETURN_TRUE;
1835: }
1836: /* }}} */
1837:
1838: /* {{{ proto string mssql_result(resource result_id, int row, mixed field)
1839: Returns the contents of one cell from a MS-SQL result set */
1840: PHP_FUNCTION(mssql_result)
1841: {
1842: zval **field, *mssql_result_index;
1843: long row;
1844: int field_offset=0;
1845: mssql_result *result;
1846:
1847: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &mssql_result_index, &row, &field) == FAILURE) {
1848: return;
1849: }
1850:
1851: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1852:
1853: if (row < 0 || row >= result->num_rows) {
1854: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad row offset (%ld)", row);
1855: RETURN_FALSE;
1856: }
1857:
1858: switch(Z_TYPE_PP(field)) {
1859: case IS_STRING: {
1860: int i;
1861:
1862: for (i=0; i<result->num_fields; i++) {
1863: if (!strcasecmp(result->fields[i].name, Z_STRVAL_PP(field))) {
1864: field_offset = i;
1865: break;
1866: }
1867: }
1868: if (i>=result->num_fields) { /* no match found */
1869: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s field not found in result", Z_STRVAL_PP(field));
1870: RETURN_FALSE;
1871: }
1872: break;
1873: }
1874: default:
1875: convert_to_long_ex(field);
1876: field_offset = Z_LVAL_PP(field);
1877: if (field_offset<0 || field_offset>=result->num_fields) {
1878: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
1879: RETURN_FALSE;
1880: }
1881: break;
1882: }
1883:
1884: *return_value = result->data[row][field_offset];
1885: zval_copy_ctor(return_value);
1886: }
1887: /* }}} */
1888:
1889: /* {{{ proto bool mssql_next_result(resource result_id)
1890: Move the internal result pointer to the next result */
1891: PHP_FUNCTION(mssql_next_result)
1892: {
1893: zval *mssql_result_index;
1894: int retvalue;
1895: mssql_result *result;
1896: mssql_link *mssql_ptr;
1897:
1898: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_result_index) == FAILURE) {
1899: return;
1900: }
1901:
1902: ZEND_FETCH_RESOURCE(result, mssql_result *, &mssql_result_index, -1, "MS SQL-result", le_result);
1903:
1904: mssql_ptr = result->mssql_ptr;
1905: retvalue = dbresults(mssql_ptr->link);
1906:
1907: while (dbnumcols(mssql_ptr->link) <= 0 && retvalue == SUCCEED) {
1908: retvalue = dbresults(mssql_ptr->link);
1909: }
1910:
1911: if (retvalue == FAIL) {
1912: RETURN_FALSE;
1913: }
1914: else if (retvalue == NO_MORE_RESULTS || retvalue == NO_MORE_RPC_RESULTS) {
1915: if (result->statement) {
1916: _mssql_get_sp_result(mssql_ptr, result->statement TSRMLS_CC);
1917: }
1918: RETURN_FALSE;
1919: }
1920: else {
1921: _free_result(result, 1);
1922: result->cur_row=result->num_fields=result->num_rows=0;
1923: dbclrbuf(mssql_ptr->link,DBLASTROW(mssql_ptr->link));
1924: retvalue = dbnextrow(mssql_ptr->link);
1925:
1926: result->num_fields = dbnumcols(mssql_ptr->link);
1927: result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0);
1928: result->have_fields = 0;
1929: result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
1930: RETURN_TRUE;
1931: }
1932:
1933: }
1934: /* }}} */
1935:
1936:
1937: /* {{{ proto void mssql_min_error_severity(int severity)
1938: Sets the lower error severity */
1939: PHP_FUNCTION(mssql_min_error_severity)
1940: {
1941: long severity;
1942:
1943: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
1944: return;
1945: }
1946:
1947: MS_SQL_G(min_error_severity) = severity;
1948: }
1949:
1950: /* }}} */
1951:
1952: /* {{{ proto void mssql_min_message_severity(int severity)
1953: Sets the lower message severity */
1954: PHP_FUNCTION(mssql_min_message_severity)
1955: {
1956: long severity;
1957:
1958: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &severity) == FAILURE) {
1959: return;
1960: }
1961:
1962: MS_SQL_G(min_message_severity) = severity;
1963: }
1964: /* }}} */
1965:
1966: /* {{{ proto int mssql_init(string sp_name [, resource conn_id])
1967: Initializes a stored procedure or a remote stored procedure */
1968: PHP_FUNCTION(mssql_init)
1969: {
1970: char *sp_name;
1971: int sp_name_len;
1972: zval *mssql_link_index = NULL;
1973: mssql_link *mssql_ptr;
1974: mssql_statement *statement;
1975: int id = -1;
1976:
1977: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &sp_name, &sp_name_len, &mssql_link_index) == FAILURE) {
1978: return;
1979: }
1980:
1981: if (mssql_link_index == NULL) {
1982: id = php_mssql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1983: CHECK_LINK(id);
1984: }
1985:
1986: ZEND_FETCH_RESOURCE2(mssql_ptr, mssql_link *, &mssql_link_index, id, "MS SQL-Link", le_link, le_plink);
1987:
1988: if (dbrpcinit(mssql_ptr->link, sp_name,0)==FAIL) {
1989: php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to init stored procedure");
1990: RETURN_FALSE;
1991: }
1992:
1993: statement=NULL;
1994: statement = ecalloc(1,sizeof(mssql_statement));
1995: statement->link = mssql_ptr;
1996: statement->executed=FALSE;
1997:
1.1.1.2 ! misho 1998: statement->id = zend_list_insert(statement,le_statement TSRMLS_CC);
1.1 misho 1999:
2000: RETURN_RESOURCE(statement->id);
2001: }
2002: /* }}} */
2003:
2004: /* {{{ proto bool mssql_bind(resource stmt, string param_name, mixed var, int type [, bool is_output [, bool is_null [, int maxlen]]])
2005: Adds a parameter to a stored procedure or a remote stored procedure */
2006: PHP_FUNCTION(mssql_bind)
2007: {
2008: char *param_name;
2009: int param_name_len, datalen;
2010: int status = 0;
2011: long type = 0, maxlen = -1;
2012: zval *stmt, **var;
2013: zend_bool is_output = 0, is_null = 0;
2014: mssql_link *mssql_ptr;
2015: mssql_statement *statement;
2016: mssql_bind bind,*bindp;
2017: LPBYTE value = NULL;
2018:
2019: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZl|bbl", &stmt, ¶m_name, ¶m_name_len, &var, &type, &is_output, &is_null, &maxlen) == FAILURE) {
2020: return;
2021: }
2022:
2023: if (ZEND_NUM_ARGS() == 7 && !is_output) {
2024: maxlen = -1;
2025: }
2026:
2027: ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
2028:
2029: if (statement==NULL) {
2030: RETURN_FALSE;
2031: }
2032: mssql_ptr=statement->link;
2033:
2034: /* modify datalen and maxlen according to dbrpcparam documentation */
2035: if ( (type==SQLVARCHAR) || (type==SQLCHAR) || (type==SQLTEXT) ) { /* variable-length type */
2036: if (is_null) {
2037: maxlen=0;
2038: datalen=0;
2039: } else {
2040: convert_to_string_ex(var);
2041: datalen=Z_STRLEN_PP(var);
2042: value=(LPBYTE)Z_STRVAL_PP(var);
2043: }
2044: } else {
2045: /* fixed-length type */
2046: if (is_null) {
2047: datalen=0;
2048: } else {
2049: datalen=-1;
2050: }
2051: maxlen=-1;
2052:
2053: switch (type) {
2054: case SQLFLT4:
2055: case SQLFLT8:
2056: case SQLFLTN:
2057: convert_to_double_ex(var);
2058: value=(LPBYTE)(&Z_DVAL_PP(var));
2059: break;
2060:
2061: case SQLBIT:
2062: case SQLINT1:
2063: case SQLINT2:
2064: case SQLINT4:
2065: convert_to_long_ex(var);
2066: value=(LPBYTE)(&Z_LVAL_PP(var));
2067: break;
2068:
2069: default:
2070: php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type");
2071: RETURN_FALSE;
2072: break;
2073: }
2074: }
2075:
2076: if (is_output) {
2077: status=DBRPCRETURN;
2078: }
2079:
2080: /* hashtable of binds */
2081: if (! statement->binds) {
2082: ALLOC_HASHTABLE(statement->binds);
2083: zend_hash_init(statement->binds, 13, NULL, _mssql_bind_hash_dtor, 0);
2084: }
2085:
2086: if (zend_hash_exists(statement->binds, param_name, param_name_len)) {
2087: RETURN_FALSE;
2088: }
2089: else {
2090: memset((void*)&bind,0,sizeof(mssql_bind));
2091: zend_hash_add(statement->binds, param_name, param_name_len, &bind, sizeof(mssql_bind), (void **)&bindp);
2092: if( NULL == bindp ) RETURN_FALSE;
2093: bindp->zval=*var;
2094: zval_add_ref(var);
2095:
2096: /* no call to dbrpcparam if RETVAL */
2097: if ( strcmp("RETVAL", param_name)!=0 ) {
2098: if (dbrpcparam(mssql_ptr->link, param_name, (BYTE)status, type, maxlen, datalen, (LPBYTE)value)==FAIL) {
2099: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set parameter");
2100: RETURN_FALSE;
2101: }
2102: }
2103: }
2104:
2105: RETURN_TRUE;
2106: }
2107: /* }}} */
2108:
2109: /* {{{ proto mixed mssql_execute(resource stmt [, bool skip_results = false])
2110: Executes a stored procedure on a MS-SQL server database */
2111: PHP_FUNCTION(mssql_execute)
2112: {
2113: zval *stmt;
2114: zend_bool skip_results = 0;
2115: int retvalue, retval_results;
2116: mssql_link *mssql_ptr;
2117: mssql_statement *statement;
2118: mssql_result *result;
2119: int num_fields;
2120: int batchsize;
2121: int exec_retval;
2122:
2123: batchsize = MS_SQL_G(batchsize);
2124:
2125: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &stmt, &skip_results) == FAILURE) {
2126: return;
2127: }
2128:
2129: ZEND_FETCH_RESOURCE(statement, mssql_statement *, &stmt, -1, "MS SQL-Statement", le_statement);
2130:
2131: mssql_ptr=statement->link;
2132: exec_retval = dbrpcexec(mssql_ptr->link);
2133:
2134: if (exec_retval == FAIL || dbsqlok(mssql_ptr->link) == FAIL) {
2135: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stored procedure execution failed");
2136:
2137: if (exec_retval == FAIL) {
2138: dbcancel(mssql_ptr->link);
2139: }
2140:
2141: RETURN_FALSE;
2142: }
2143:
2144: retval_results=dbresults(mssql_ptr->link);
2145:
2146: if (retval_results==FAIL) {
2147: php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not retrieve results");
2148: dbcancel(mssql_ptr->link);
2149: RETURN_FALSE;
2150: }
2151:
2152: /* The following is just like mssql_query, fetch all rows from the first result
2153: * set into the row buffer.
2154: */
2155: result=NULL;
2156: if (retval_results == SUCCEED) {
2157: if (skip_results) {
2158: do {
2159: dbcanquery(mssql_ptr->link);
2160: retval_results = dbresults(mssql_ptr->link);
2161: } while (retval_results == SUCCEED);
2162: }
2163: else {
2164: /* Skip results not returning any columns */
2165: while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retval_results == SUCCEED) {
2166: retval_results = dbresults(mssql_ptr->link);
2167: }
2168: if ((num_fields = dbnumcols(mssql_ptr->link)) > 0) {
2169: retvalue = dbnextrow(mssql_ptr->link);
2170: result = (mssql_result *) emalloc(sizeof(mssql_result));
2171: result->batchsize = batchsize;
2172: result->blocks_initialized = 1;
2173: result->data = (zval **) safe_emalloc(sizeof(zval *), MSSQL_ROWS_BLOCK, 0);
2174: result->mssql_ptr = mssql_ptr;
2175: result->cur_field=result->cur_row=result->num_rows=0;
2176: result->num_fields = num_fields;
2177: result->have_fields = 0;
2178:
2179: result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), num_fields, 0);
2180: result->statement = statement;
2181: result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC);
2182: }
2183: }
2184: }
2185: if (retval_results == NO_MORE_RESULTS || retval_results == NO_MORE_RPC_RESULTS) {
2186: _mssql_get_sp_result(mssql_ptr, statement TSRMLS_CC);
2187: }
2188:
2189: if (result==NULL) {
2190: RETURN_TRUE; /* no recordset returned ...*/
2191: }
2192: else {
2193: ZEND_REGISTER_RESOURCE(return_value, result, le_result);
2194: }
2195: }
2196: /* }}} */
2197:
2198: /* {{{ proto bool mssql_free_statement(resource result_index)
2199: Free a MS-SQL statement index */
2200: PHP_FUNCTION(mssql_free_statement)
2201: {
2202: zval *mssql_statement_index;
2203: mssql_statement *statement;
2204: int retvalue;
2205:
2206: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mssql_statement_index) == FAILURE) {
2207: return;
2208: }
2209:
2210: if (Z_RESVAL_P(mssql_statement_index) == 0) {
2211: RETURN_FALSE;
2212: }
2213:
2214: ZEND_FETCH_RESOURCE(statement, mssql_statement *, &mssql_statement_index, -1, "MS SQL-statement", le_statement);
2215: /* Release remaining results */
2216: do {
2217: dbcanquery(statement->link->link);
2218: retvalue = dbresults(statement->link->link);
2219: } while (retvalue == SUCCEED);
2220:
2221: zend_list_delete(Z_RESVAL_P(mssql_statement_index));
2222: RETURN_TRUE;
2223: }
2224: /* }}} */
2225:
2226: /* {{{ proto string mssql_guid_string(string binary [,bool short_format])
2227: Converts a 16 byte binary GUID to a string */
2228: PHP_FUNCTION(mssql_guid_string)
2229: {
2230: char *binary;
2231: int binary_len;
2232: zend_bool sf = 0;
2233: char buffer[32+1];
2234: char buffer2[36+1];
2235:
2236: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &binary, &binary_len, &sf) == FAILURE) {
2237: return;
2238: }
2239:
2240: dbconvert(NULL, SQLBINARY, (BYTE*) binary, MIN(16, binary_len), SQLCHAR, buffer, -1);
2241:
2242: if (sf) {
2243: php_strtoupper(buffer, 32);
2244: RETURN_STRING(buffer, 1);
2245: }
2246: else {
2247: int i;
2248: /* FIXME this works only on little endian machine */
2249: for (i=0; i<4; i++) {
2250: buffer2[2*i] = buffer[6-2*i];
2251: buffer2[2*i+1] = buffer[7-2*i];
2252: }
2253: buffer2[8] = '-';
2254: for (i=0; i<2; i++) {
2255: buffer2[9+2*i] = buffer[10-2*i];
2256: buffer2[10+2*i] = buffer[11-2*i];
2257: }
2258: buffer2[13] = '-';
2259: for (i=0; i<2; i++) {
2260: buffer2[14+2*i] = buffer[14-2*i];
2261: buffer2[15+2*i] = buffer[15-2*i];
2262: }
2263: buffer2[18] = '-';
2264: for (i=0; i<4; i++) {
2265: buffer2[19+i] = buffer[16+i];
2266: }
2267: buffer2[23] = '-';
2268: for (i=0; i<12; i++) {
2269: buffer2[24+i] = buffer[20+i];
2270: }
2271: buffer2[36] = 0;
2272:
2273: php_strtoupper(buffer2, 36);
2274: RETURN_STRING(buffer2, 1);
2275: }
2276: }
2277: /* }}} */
2278:
2279: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>