1999-04-22 10:48:28 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2004-01-08 16:18:22 +08:00
|
|
|
| PHP Version 5 |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2004-01-08 16:18:22 +08:00
|
|
|
| Copyright (c) 1997-2004 The PHP Group |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2003-06-11 04:04:29 +08:00
|
|
|
| This source file is subject to version 3.0 of the PHP license, |
|
1999-07-16 21:13:16 +08:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-11 04:04:29 +08:00
|
|
|
| available through the world-wide-web at the following url: |
|
|
|
|
| http://www.php.net/license/3_0.txt. |
|
1999-07-16 21:13:16 +08:00
|
|
|
| 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. |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2001-01-04 19:15:35 +08:00
|
|
|
| Authors: Jouni Ahto <jouni.ahto@exdec.fi> |
|
2000-05-15 05:55:45 +08:00
|
|
|
| Andrew Avdeev <andy@rsc.mv.ru> |
|
2004-02-20 18:59:24 +08:00
|
|
|
| Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl> |
|
1999-04-22 10:48:28 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
2001-05-24 18:07:29 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2004-02-11 20:08:44 +08:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
#include "php.h"
|
2003-08-16 23:30:22 +08:00
|
|
|
|
2003-09-08 03:59:55 +08:00
|
|
|
#define FILE_REVISION "$Revision$"
|
|
|
|
|
2003-09-17 09:25:08 +08:00
|
|
|
#if HAVE_IBASE
|
2003-08-16 23:30:22 +08:00
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
#include "php_ini.h"
|
|
|
|
#include "ext/standard/php_standard.h"
|
2004-02-20 18:59:24 +08:00
|
|
|
#include "ext/standard/md5.h"
|
1999-12-05 03:19:57 +08:00
|
|
|
#include "php_interbase.h"
|
2004-02-02 21:49:48 +08:00
|
|
|
#include "php_ibase_includes.h"
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2003-08-16 23:30:22 +08:00
|
|
|
#include <time.h>
|
2003-08-12 21:19:36 +08:00
|
|
|
|
2003-08-28 06:55:06 +08:00
|
|
|
#define ROLLBACK 0
|
|
|
|
#define COMMIT 1
|
|
|
|
#define RETAIN 2
|
2003-08-20 20:22:58 +08:00
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
/* {{{ extension definition structures */
|
|
|
|
function_entry ibase_functions[] = {
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_connect, NULL)
|
|
|
|
PHP_FE(ibase_pconnect, NULL)
|
|
|
|
PHP_FE(ibase_close, NULL)
|
2003-08-05 21:17:16 +08:00
|
|
|
PHP_FE(ibase_drop_db, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_query, NULL)
|
|
|
|
PHP_FE(ibase_fetch_row, NULL)
|
2002-03-15 23:26:01 +08:00
|
|
|
PHP_FE(ibase_fetch_assoc, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_fetch_object, NULL)
|
|
|
|
PHP_FE(ibase_free_result, NULL)
|
2003-08-07 01:51:46 +08:00
|
|
|
PHP_FE(ibase_name_result, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_prepare, NULL)
|
|
|
|
PHP_FE(ibase_execute, NULL)
|
|
|
|
PHP_FE(ibase_free_query, NULL)
|
2002-09-12 19:18:47 +08:00
|
|
|
#if HAVE_STRFTIME
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_timefmt, NULL)
|
2002-09-12 19:18:47 +08:00
|
|
|
#endif
|
2003-09-24 06:17:40 +08:00
|
|
|
PHP_FE(ibase_gen_id, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_num_fields, NULL)
|
2003-08-11 04:53:19 +08:00
|
|
|
PHP_FE(ibase_num_params, NULL)
|
2003-08-16 09:58:29 +08:00
|
|
|
#if abies_0
|
2003-08-11 00:21:26 +08:00
|
|
|
PHP_FE(ibase_num_rows, NULL)
|
2003-08-16 09:58:29 +08:00
|
|
|
#endif
|
2003-08-11 00:21:26 +08:00
|
|
|
PHP_FE(ibase_affected_rows, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FE(ibase_field_info, NULL)
|
2003-08-11 04:53:19 +08:00
|
|
|
PHP_FE(ibase_param_info, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
PHP_FE(ibase_trans, NULL)
|
|
|
|
PHP_FE(ibase_commit, NULL)
|
|
|
|
PHP_FE(ibase_rollback, NULL)
|
2003-08-07 01:51:46 +08:00
|
|
|
PHP_FE(ibase_commit_ret, NULL)
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
PHP_FE(ibase_blob_info, NULL)
|
|
|
|
PHP_FE(ibase_blob_create, NULL)
|
|
|
|
PHP_FE(ibase_blob_add, NULL)
|
|
|
|
PHP_FE(ibase_blob_cancel, NULL)
|
|
|
|
PHP_FE(ibase_blob_close, NULL)
|
|
|
|
PHP_FE(ibase_blob_open, NULL)
|
|
|
|
PHP_FE(ibase_blob_get, NULL)
|
|
|
|
PHP_FE(ibase_blob_echo, NULL)
|
|
|
|
PHP_FE(ibase_blob_import, NULL)
|
|
|
|
PHP_FE(ibase_errmsg, NULL)
|
2003-08-08 19:04:12 +08:00
|
|
|
PHP_FE(ibase_errcode, NULL)
|
2002-01-27 23:31:15 +08:00
|
|
|
|
2004-02-02 01:52:36 +08:00
|
|
|
#if HAVE_IBASE6_API
|
2002-01-27 23:31:15 +08:00
|
|
|
PHP_FE(ibase_add_user, NULL)
|
|
|
|
PHP_FE(ibase_modify_user, NULL)
|
|
|
|
PHP_FE(ibase_delete_user, NULL)
|
2003-09-04 22:18:39 +08:00
|
|
|
|
|
|
|
PHP_FE(ibase_rollback_ret, NULL)
|
2004-02-02 00:13:07 +08:00
|
|
|
|
|
|
|
PHP_FE(ibase_service_attach, NULL)
|
|
|
|
PHP_FE(ibase_service_detach, NULL)
|
|
|
|
PHP_FE(ibase_backup, NULL)
|
|
|
|
PHP_FE(ibase_restore, NULL)
|
2004-02-02 21:49:48 +08:00
|
|
|
PHP_FE(ibase_maintain_db, NULL)
|
|
|
|
PHP_FE(ibase_db_info, NULL)
|
|
|
|
PHP_FE(ibase_server_info, NULL)
|
2002-06-07 03:47:28 +08:00
|
|
|
#endif
|
2003-08-14 18:55:02 +08:00
|
|
|
PHP_FE(ibase_wait_event, NULL)
|
2003-08-15 08:06:07 +08:00
|
|
|
PHP_FE(ibase_set_event_handler, NULL)
|
2003-08-16 00:13:51 +08:00
|
|
|
PHP_FE(ibase_free_event_handler, NULL)
|
1999-04-22 10:48:28 +08:00
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
zend_module_entry ibase_module_entry = {
|
2001-10-12 07:33:59 +08:00
|
|
|
STANDARD_MODULE_HEADER,
|
2000-03-07 02:44:01 +08:00
|
|
|
"interbase",
|
1999-04-22 10:48:28 +08:00
|
|
|
ibase_functions,
|
1999-08-02 23:02:52 +08:00
|
|
|
PHP_MINIT(ibase),
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_MSHUTDOWN(ibase),
|
1999-08-02 23:02:52 +08:00
|
|
|
PHP_RINIT(ibase),
|
2000-04-18 10:52:45 +08:00
|
|
|
PHP_RSHUTDOWN(ibase),
|
1999-08-02 23:02:52 +08:00
|
|
|
PHP_MINFO(ibase),
|
2003-03-16 13:00:50 +08:00
|
|
|
NO_VERSION_YET,
|
1999-04-22 10:48:28 +08:00
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
|
2000-05-23 17:33:51 +08:00
|
|
|
#ifdef COMPILE_DL_INTERBASE
|
2000-05-02 08:30:36 +08:00
|
|
|
ZEND_GET_MODULE(ibase)
|
2000-03-13 03:44:23 +08:00
|
|
|
#define DL_MALLOC(size) malloc(size)
|
|
|
|
#define DL_STRDUP(str) strdup(str)
|
|
|
|
#define DL_FREE(ptr) free(ptr)
|
|
|
|
#else
|
|
|
|
#define DL_MALLOC(size) emalloc(size)
|
|
|
|
#define DL_STRDUP(str) estrdup(str)
|
|
|
|
#define DL_FREE(ptr) efree(ptr)
|
|
|
|
#endif
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-10-05 20:47:39 +08:00
|
|
|
/* True globals, no need for thread safety */
|
2004-04-05 21:22:34 +08:00
|
|
|
int le_link, le_plink, le_trans;
|
2000-10-05 20:47:39 +08:00
|
|
|
|
2000-07-05 12:21:00 +08:00
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(ibase)
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
/* }}} */
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
/* error handling ---------------------------- */
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
/* {{{ proto string ibase_errmsg(void)
|
|
|
|
Return error message */
|
|
|
|
PHP_FUNCTION(ibase_errmsg)
|
|
|
|
{
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
2003-08-08 19:04:12 +08:00
|
|
|
if (IBG(sql_code) != 0) {
|
2003-08-05 21:17:16 +08:00
|
|
|
RETURN_STRING(IBG(errmsg), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-08-29 06:12:06 +08:00
|
|
|
/* {{{ proto int ibase_errcode(void)
|
2003-08-08 19:04:12 +08:00
|
|
|
Return error code */
|
|
|
|
PHP_FUNCTION(ibase_errcode)
|
|
|
|
{
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IBG(sql_code) != 0) {
|
|
|
|
RETURN_LONG(IBG(sql_code));
|
|
|
|
}
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
/* print interbase error and save it for ibase_errmsg() */
|
|
|
|
void _php_ibase_error(TSRMLS_D) /* {{{ */
|
2003-08-05 21:17:16 +08:00
|
|
|
{
|
2003-08-08 19:04:12 +08:00
|
|
|
char *s = IBG(errmsg);
|
|
|
|
ISC_STATUS *statusp = IB_STATUS;
|
2003-08-05 21:17:16 +08:00
|
|
|
|
2003-08-08 19:04:12 +08:00
|
|
|
IBG(sql_code) = isc_sqlcode(IB_STATUS);
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && isc_interprete(s, &statusp)) {
|
|
|
|
strcat(IBG(errmsg), " ");
|
|
|
|
s = IBG(errmsg) + strlen(IBG(errmsg));
|
|
|
|
}
|
|
|
|
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
/* print php interbase module error and save it for ibase_errmsg() */
|
|
|
|
void _php_ibase_module_error(char *msg TSRMLS_DC, ...) /* {{{ */
|
2003-08-05 21:17:16 +08:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2003-08-28 08:11:16 +08:00
|
|
|
#ifdef ZTS
|
|
|
|
va_start(ap, TSRMLS_C);
|
|
|
|
#else
|
2003-08-05 21:17:16 +08:00
|
|
|
va_start(ap, msg);
|
2003-08-28 08:11:16 +08:00
|
|
|
#endif
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
/* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */
|
|
|
|
vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap);
|
|
|
|
va_end(ap);
|
2003-08-16 23:30:22 +08:00
|
|
|
|
|
|
|
IBG(sql_code) = -999; /* no SQL error */
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ internal macros, functions and structures */
|
|
|
|
typedef struct {
|
2003-09-24 06:17:40 +08:00
|
|
|
isc_db_handle *db_ptr;
|
|
|
|
long tpb_len;
|
|
|
|
char *tpb_ptr;
|
2003-08-05 21:17:16 +08:00
|
|
|
} ISC_TEB;
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* Fill ib_link and trans with the correct database link and transaction. */
|
2004-02-17 20:53:54 +08:00
|
|
|
void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
|
|
|
|
zval **link_id, ibase_db_link **ib_link, ibase_trans **trans)
|
2003-03-16 13:00:50 +08:00
|
|
|
{
|
2000-07-07 20:06:05 +08:00
|
|
|
int type;
|
|
|
|
|
2003-09-02 21:17:56 +08:00
|
|
|
IBDEBUG("Transaction or database link?");
|
2003-08-11 04:53:19 +08:00
|
|
|
if (zend_list_find(Z_LVAL_PP(link_id), &type)) {
|
|
|
|
if (type == le_trans) {
|
|
|
|
/* Transaction resource: make sure it refers to one link only, then
|
|
|
|
fetch it; database link is stored in ib_trans->db_link[]. */
|
|
|
|
IBDEBUG("Type is le_trans");
|
|
|
|
ZEND_FETCH_RESOURCE(*trans, ibase_trans *, link_id, -1, "InterBase transaction", le_trans);
|
|
|
|
if ((*trans)->link_cnt > 1) {
|
2004-02-17 20:53:54 +08:00
|
|
|
_php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections."
|
|
|
|
TSRMLS_CC);
|
2003-08-11 04:53:19 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
*ib_link = (*trans)->db_link[0];
|
2003-08-10 21:20:38 +08:00
|
|
|
return;
|
2003-08-11 04:53:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
IBDEBUG("Type is le_[p]link or id not found");
|
|
|
|
/* Database link resource, use default transaction. */
|
|
|
|
*trans = NULL;
|
|
|
|
ZEND_FETCH_RESOURCE2(*ib_link, ibase_db_link *, link_id, -1, "InterBase link", le_link, le_plink);
|
2000-07-07 20:06:05 +08:00
|
|
|
}
|
2004-02-02 00:13:07 +08:00
|
|
|
/* }}} */
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
/* destructors ---------------------- */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void _php_ibase_commit_link(ibase_db_link *link TSRMLS_DC) /* {{{ */
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2003-08-28 06:55:06 +08:00
|
|
|
unsigned short i = 0, j;
|
2003-08-05 21:17:16 +08:00
|
|
|
ibase_tr_list *l;
|
2004-02-17 20:53:54 +08:00
|
|
|
ibase_event *e;
|
2000-07-05 12:21:00 +08:00
|
|
|
IBDEBUG("Checking transactions to close...");
|
2003-08-05 21:17:16 +08:00
|
|
|
|
2003-08-08 19:04:12 +08:00
|
|
|
for (l = link->tr_list; l != NULL; ++i) {
|
2003-08-05 21:17:16 +08:00
|
|
|
ibase_tr_list *p = l;
|
|
|
|
if (p->trans != NULL) {
|
|
|
|
if (i == 0) {
|
2003-08-06 23:27:16 +08:00
|
|
|
if (p->trans->handle != NULL) {
|
|
|
|
IBDEBUG("Committing default transaction...");
|
|
|
|
if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
}
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
|
|
|
efree(p->trans); /* default transaction is not a registered resource: clean up */
|
|
|
|
}
|
2003-08-06 23:27:16 +08:00
|
|
|
else {
|
|
|
|
if (p->trans->handle != NULL) {
|
2004-02-17 20:53:54 +08:00
|
|
|
/* non-default trans might have been rolled back by other call of this dtor */
|
2003-08-06 23:27:16 +08:00
|
|
|
IBDEBUG("Rolling back other transactions...");
|
|
|
|
if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
}
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
|
|
|
/* set this link pointer to NULL in the transaction */
|
|
|
|
for (j = 0; j < p->trans->link_cnt; ++j) {
|
2003-08-08 19:04:12 +08:00
|
|
|
if (p->trans->db_link[j] == link) {
|
|
|
|
p->trans->db_link[j] = NULL;
|
2003-08-05 21:17:16 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2003-08-05 21:17:16 +08:00
|
|
|
l = l->next;
|
|
|
|
efree(p);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2003-08-08 19:04:12 +08:00
|
|
|
link->tr_list = NULL;
|
2004-02-17 20:53:54 +08:00
|
|
|
|
|
|
|
for (e = link->event_head; e; e = e->event_next) {
|
|
|
|
_php_ibase_free_event(e TSRMLS_CC);
|
|
|
|
e->link = NULL;
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2004-02-17 20:53:54 +08:00
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void php_ibase_commit_link_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
|
2000-10-21 02:25:16 +08:00
|
|
|
{
|
2003-03-16 13:00:50 +08:00
|
|
|
ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
|
2001-07-31 13:44:11 +08:00
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
_php_ibase_commit_link(link TSRMLS_CC);
|
2000-10-21 02:25:16 +08:00
|
|
|
}
|
2004-02-02 00:13:07 +08:00
|
|
|
/* }}} */
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void _php_ibase_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2003-03-16 13:00:50 +08:00
|
|
|
ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
|
2000-07-05 12:21:00 +08:00
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
_php_ibase_commit_link(link TSRMLS_CC);
|
2003-08-13 02:01:59 +08:00
|
|
|
if (link->handle != NULL) {
|
2003-08-06 23:27:16 +08:00
|
|
|
IBDEBUG("Closing normal link...");
|
2003-08-13 02:01:59 +08:00
|
|
|
isc_detach_database(IB_STATUS, &link->handle);
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
IBG(num_links)--;
|
|
|
|
efree(link);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void _php_ibase_close_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2003-03-16 13:00:50 +08:00
|
|
|
ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
|
2000-07-05 12:21:00 +08:00
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
_php_ibase_commit_link(link TSRMLS_CC);
|
2000-04-30 13:46:04 +08:00
|
|
|
IBDEBUG("Closing permanent link...");
|
2003-08-13 02:01:59 +08:00
|
|
|
if (link->handle != NULL) {
|
|
|
|
isc_detach_database(IB_STATUS, &link->handle);
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
IBG(num_persistent)--;
|
|
|
|
IBG(num_links)--;
|
|
|
|
free(link);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void _php_ibase_free_trans(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
|
2000-07-09 15:30:15 +08:00
|
|
|
{
|
2003-08-07 08:00:19 +08:00
|
|
|
ibase_trans *trans = (ibase_trans *)rsrc->ptr;
|
2003-08-28 06:55:06 +08:00
|
|
|
unsigned short i;
|
2000-07-09 15:30:15 +08:00
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
IBDEBUG("Cleaning up transaction resource...");
|
|
|
|
if (trans->handle != NULL) {
|
|
|
|
IBDEBUG("Rolling back unhandled transaction...");
|
|
|
|
if (isc_rollback_transaction(IB_STATUS, &trans->handle)) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now remove this transaction from all the connection-transaction lists */
|
|
|
|
for (i = 0; i < trans->link_cnt; ++i) {
|
2003-08-08 19:04:12 +08:00
|
|
|
if (trans->db_link[i] != NULL) {
|
2003-08-05 21:17:16 +08:00
|
|
|
ibase_tr_list **l;
|
2003-08-08 19:04:12 +08:00
|
|
|
for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) {
|
2003-08-05 21:17:16 +08:00
|
|
|
if ( (*l)->trans == trans) {
|
|
|
|
ibase_tr_list *p = *l;
|
|
|
|
*l = p->next;
|
|
|
|
efree(p);
|
|
|
|
break;
|
2002-05-10 05:41:20 +08:00
|
|
|
}
|
2000-07-09 15:30:15 +08:00
|
|
|
}
|
|
|
|
}
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
|
|
|
efree(trans);
|
2000-07-09 15:30:15 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-22 10:48:28 +08:00
|
|
|
/* {{{ startup, shutdown and info functions */
|
2000-04-18 10:52:45 +08:00
|
|
|
PHP_INI_BEGIN()
|
2003-03-16 13:00:50 +08:00
|
|
|
STD_PHP_INI_BOOLEAN("ibase.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_ibase_globals, ibase_globals)
|
|
|
|
STD_PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_ibase_globals, ibase_globals, display_link_numbers)
|
|
|
|
STD_PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ibase_globals, ibase_globals, display_link_numbers)
|
2004-02-20 18:59:24 +08:00
|
|
|
STD_PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, OnUpdateString, default_db, zend_ibase_globals, ibase_globals)
|
2003-03-16 13:00:50 +08:00
|
|
|
STD_PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_ibase_globals, ibase_globals)
|
|
|
|
STD_PHP_INI_ENTRY("ibase.default_password", NULL, PHP_INI_ALL, OnUpdateString, default_password, zend_ibase_globals, ibase_globals)
|
2004-02-20 18:59:24 +08:00
|
|
|
STD_PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, OnUpdateString, default_charset, zend_ibase_globals, ibase_globals)
|
2003-03-16 13:00:50 +08:00
|
|
|
STD_PHP_INI_ENTRY("ibase.timestampformat", "%m/%d/%Y %H:%M:%S", PHP_INI_ALL, OnUpdateString, cfg_timestampformat, zend_ibase_globals, ibase_globals)
|
|
|
|
STD_PHP_INI_ENTRY("ibase.dateformat", "%m/%d/%Y", PHP_INI_ALL, OnUpdateString, cfg_dateformat, zend_ibase_globals, ibase_globals)
|
|
|
|
STD_PHP_INI_ENTRY("ibase.timeformat", "%H:%M:%S", PHP_INI_ALL, OnUpdateString, cfg_timeformat, zend_ibase_globals, ibase_globals)
|
2000-04-18 10:52:45 +08:00
|
|
|
PHP_INI_END()
|
|
|
|
|
2001-09-05 05:47:05 +08:00
|
|
|
static void php_ibase_init_globals(zend_ibase_globals *ibase_globals)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2001-09-05 05:47:05 +08:00
|
|
|
ibase_globals->timestampformat = NULL;
|
|
|
|
ibase_globals->dateformat = NULL;
|
|
|
|
ibase_globals->timeformat = NULL;
|
|
|
|
ibase_globals->num_persistent = 0;
|
2003-08-08 19:04:12 +08:00
|
|
|
ibase_globals->sql_code = 0;
|
2000-07-05 12:21:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PHP_MINIT_FUNCTION(ibase)
|
|
|
|
{
|
|
|
|
ZEND_INIT_MODULE_GLOBALS(ibase, php_ibase_init_globals, NULL);
|
2000-04-18 10:52:45 +08:00
|
|
|
|
|
|
|
REGISTER_INI_ENTRIES();
|
|
|
|
|
2000-10-26 01:44:02 +08:00
|
|
|
le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, "interbase link", module_number);
|
|
|
|
le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, "interbase link persistent", module_number);
|
|
|
|
le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, "interbase transaction", module_number);
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT);
|
2003-08-16 23:30:22 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT);
|
2000-05-12 11:02:14 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT);
|
2003-06-15 00:38:10 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_TIMESTAMP", PHP_IBASE_TIMESTAMP, CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_DATE", PHP_IBASE_DATE, CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_TIME", PHP_IBASE_TIME, CONST_PERSISTENT);
|
2004-04-05 21:22:34 +08:00
|
|
|
|
2003-06-15 00:38:10 +08:00
|
|
|
/* transactions */
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT);
|
2000-03-13 03:44:23 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT);
|
2000-04-18 10:52:45 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT);
|
2000-03-13 03:44:23 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT);
|
2003-06-15 00:38:10 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT);
|
2000-03-13 03:44:23 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT);
|
2003-06-15 00:38:10 +08:00
|
|
|
REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT);
|
2004-04-05 21:22:34 +08:00
|
|
|
|
|
|
|
php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU);
|
|
|
|
php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU);
|
|
|
|
php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU);
|
|
|
|
php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU);
|
|
|
|
|
2004-02-02 21:49:48 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
1999-08-02 23:02:52 +08:00
|
|
|
PHP_RINIT_FUNCTION(ibase)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-04-18 10:52:45 +08:00
|
|
|
IBG(default_link)= -1;
|
2000-03-13 03:44:23 +08:00
|
|
|
IBG(num_links) = IBG(num_persistent);
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timestampformat)) {
|
|
|
|
DL_FREE(IBG(timestampformat));
|
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(timestampformat) = DL_STRDUP(IBG(cfg_timestampformat));
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(dateformat)) {
|
|
|
|
DL_FREE(IBG(dateformat));
|
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(dateformat) = DL_STRDUP(IBG(cfg_dateformat));
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timeformat)) {
|
|
|
|
DL_FREE(IBG(timeformat));
|
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
IBG(timeformat) = DL_STRDUP(IBG(cfg_timeformat));
|
|
|
|
|
2003-08-07 09:00:22 +08:00
|
|
|
RESET_ERRMSG;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_MSHUTDOWN_FUNCTION(ibase)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2004-01-21 18:22:04 +08:00
|
|
|
#ifndef PHP_WIN32
|
|
|
|
/**
|
|
|
|
* When the Interbase client API library libgds.so is first loaded, it registers a call to
|
|
|
|
* gds__cleanup() with atexit(), in order to clean up after itself when the process exits.
|
|
|
|
* This means that the library is called at process shutdown, and cannot be unloaded beforehand.
|
|
|
|
* PHP tries to unload modules after every request [dl()'ed modules], and right before the
|
|
|
|
* process shuts down [modules loaded from php.ini]. This results in a segfault for this module.
|
|
|
|
* By NULLing the dlopen() handle in the module entry, Zend omits the call to dlclose(),
|
|
|
|
* ensuring that the module will remain present until the process exits. However, the functions
|
|
|
|
* and classes exported by the module will not be available until the module is 'reloaded'.
|
|
|
|
* When reloaded, dlopen() will return the handle of the already loaded module. The module will
|
|
|
|
* be unloaded automatically when the process exits.
|
|
|
|
*/
|
|
|
|
zend_module_entry *ibase_entry;
|
2004-02-02 00:13:07 +08:00
|
|
|
if (SUCCESS == zend_hash_find(&module_registry, ibase_module_entry.name,
|
|
|
|
strlen(ibase_module_entry.name) +1, (void*) &ibase_entry)) {
|
2004-01-21 18:22:04 +08:00
|
|
|
ibase_entry->handle = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
2000-04-18 10:52:45 +08:00
|
|
|
UNREGISTER_INI_ENTRIES();
|
2000-03-13 03:44:23 +08:00
|
|
|
return SUCCESS;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_RSHUTDOWN_FUNCTION(ibase)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timestampformat)) {
|
|
|
|
DL_FREE(IBG(timestampformat));
|
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(timestampformat) = NULL;
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(dateformat)) {
|
|
|
|
DL_FREE(IBG(dateformat));
|
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(dateformat) = NULL;
|
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timeformat)) {
|
|
|
|
DL_FREE(IBG(timeformat));
|
|
|
|
}
|
2000-04-18 10:52:45 +08:00
|
|
|
IBG(timeformat) = NULL;
|
2003-03-16 13:00:50 +08:00
|
|
|
|
|
|
|
return SUCCESS;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
|
1999-08-02 23:02:52 +08:00
|
|
|
PHP_MINFO_FUNCTION(ibase)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2004-02-11 20:08:44 +08:00
|
|
|
char tmp[64], *s;
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2000-04-07 00:57:33 +08:00
|
|
|
php_info_print_table_start();
|
2003-03-16 13:00:50 +08:00
|
|
|
php_info_print_table_row(2, "Interbase Support", "enabled");
|
2003-09-12 07:08:48 +08:00
|
|
|
|
2004-02-11 20:08:44 +08:00
|
|
|
#ifdef FB_API_VER
|
|
|
|
sprintf( (s = tmp), "Firebird API version %d", FB_API_VER);
|
|
|
|
#elif (SQLDA_CURRENT_VERSION > 1)
|
|
|
|
s = "Interbase 7.0 and up";
|
2003-09-17 04:28:27 +08:00
|
|
|
#elif (SQL_DIALECT_CURRENT == 1)
|
2004-02-11 20:08:44 +08:00
|
|
|
s = "Interbase 5.6 or earlier";
|
2003-09-12 07:08:48 +08:00
|
|
|
#elif !defined(DSC_null)
|
2004-02-11 20:08:44 +08:00
|
|
|
s = "Interbase 6";
|
2003-09-12 07:08:48 +08:00
|
|
|
#else
|
2004-02-11 20:08:44 +08:00
|
|
|
s = "Firebird 1.0";
|
2003-09-12 07:08:48 +08:00
|
|
|
#endif
|
2004-02-11 20:08:44 +08:00
|
|
|
php_info_print_table_row(2, "Compile-time Client Library Version", s);
|
|
|
|
|
|
|
|
#if defined(__GNUC__) || defined(PHP_WIN32)
|
|
|
|
do {
|
2004-03-08 18:32:26 +08:00
|
|
|
info_func_t info_func = NULL;
|
2004-02-11 20:08:44 +08:00
|
|
|
#ifdef __GNUC__
|
2004-03-08 18:32:26 +08:00
|
|
|
info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
|
2004-02-11 20:08:44 +08:00
|
|
|
#else
|
|
|
|
HMODULE l = GetModuleHandle("fbclient");
|
|
|
|
|
|
|
|
if (!l && !(l = GetModuleHandle("gds32"))) {
|
|
|
|
break;
|
|
|
|
}
|
2004-03-08 18:32:26 +08:00
|
|
|
info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
|
2004-03-07 22:25:08 +08:00
|
|
|
#endif
|
2004-02-11 20:08:44 +08:00
|
|
|
if (info_func) {
|
|
|
|
info_func(s = tmp);
|
|
|
|
} else {
|
|
|
|
#if HAVE_IBASE6_API
|
|
|
|
s = "Firebird 1.0/Interbase 6";
|
|
|
|
#else
|
|
|
|
s = "Firebird 1.0/Interbase 6 or earlier";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
php_info_print_table_row(2, "Run-time Client Library Version", s);
|
|
|
|
} while (0);
|
|
|
|
#endif
|
2003-09-12 07:08:48 +08:00
|
|
|
|
2003-09-08 03:59:55 +08:00
|
|
|
php_info_print_table_row(2, "Revision", FILE_REVISION);
|
2000-05-23 17:33:51 +08:00
|
|
|
#ifdef COMPILE_DL_INTERBASE
|
2003-08-06 23:27:16 +08:00
|
|
|
php_info_print_table_row(2, "Dynamic Module", "Yes");
|
2000-03-13 03:44:23 +08:00
|
|
|
#endif
|
2003-03-16 13:00:50 +08:00
|
|
|
php_info_print_table_row(2, "Allow Persistent Links", (IBG(allow_persistent) ? "Yes" : "No"));
|
2000-04-07 00:57:33 +08:00
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
if (IBG(max_persistent) == -1) {
|
2003-09-12 07:08:48 +08:00
|
|
|
sprintf(tmp, "%ld/unlimited", IBG(num_persistent));
|
2000-03-13 03:44:23 +08:00
|
|
|
} else {
|
2003-09-12 07:08:48 +08:00
|
|
|
sprintf(tmp, "%ld/%ld", IBG(num_persistent), IBG(max_persistent));
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
2003-03-16 13:00:50 +08:00
|
|
|
php_info_print_table_row(2, "Persistent Links", tmp);
|
2000-04-07 00:57:33 +08:00
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
if (IBG(max_links) == -1) {
|
2003-09-12 07:08:48 +08:00
|
|
|
sprintf(tmp, "%ld/unlimited", IBG(num_links));
|
2000-03-13 03:44:23 +08:00
|
|
|
} else {
|
2003-09-12 07:08:48 +08:00
|
|
|
sprintf(tmp, "%ld/%ld", IBG(num_links), IBG(max_links));
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
2003-03-16 13:00:50 +08:00
|
|
|
php_info_print_table_row(2, "Total Links", tmp);
|
2000-04-07 00:57:33 +08:00
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
php_info_print_table_row(2, "Timestamp Format", IBG(timestampformat));
|
|
|
|
php_info_print_table_row(2, "Date Format", IBG(dateformat));
|
|
|
|
php_info_print_table_row(2, "Time Format", IBG(timeformat));
|
2000-04-07 00:57:33 +08:00
|
|
|
|
|
|
|
php_info_print_table_end();
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1 };
|
|
|
|
|
|
|
|
static char const dpb_args[] = { 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype
|
|
|
|
#ifdef isc_dpb_sql_role_name
|
|
|
|
, isc_dpb_sql_role_name
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db TSRMLS_DC)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2004-02-20 18:59:24 +08:00
|
|
|
short i;
|
|
|
|
char dpb_buffer[256] = { isc_dpb_version1 }, *dpb;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
dpb = dpb_buffer + 1;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
for (i = 0; i < sizeof(dpb_args); ++i) {
|
|
|
|
if (dpb_args[i] && args[i]) {
|
|
|
|
dpb += sprintf(dpb, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]);
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2004-02-20 18:59:24 +08:00
|
|
|
if (largs[BUF]) {
|
|
|
|
dpb += sprintf(dpb, "%c\2%c%c", isc_dpb_num_buffers,
|
|
|
|
(char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff));
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2004-03-08 18:49:17 +08:00
|
|
|
if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) {
|
2002-07-19 17:21:29 +08:00
|
|
|
_php_ibase_error(TSRMLS_C);
|
2000-03-13 03:44:23 +08:00
|
|
|
return FAILURE;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
return SUCCESS;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2004-02-20 18:59:24 +08:00
|
|
|
char hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL };
|
|
|
|
int i, len[] = { 0, 0, 0, 0, 0 };
|
2004-04-03 19:00:14 +08:00
|
|
|
long largs[] = { 0, 0 };
|
2004-02-20 18:59:24 +08:00
|
|
|
PHP_MD5_CTX hash_context;
|
|
|
|
list_entry new_index_ptr, *le;
|
1999-04-22 10:48:28 +08:00
|
|
|
isc_db_handle db_handle = NULL;
|
2004-02-20 18:59:24 +08:00
|
|
|
ibase_db_link *ib_link;
|
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
RESET_ERRMSG;
|
2004-02-20 18:59:24 +08:00
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sssslls",
|
|
|
|
&args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS],
|
|
|
|
&args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE])) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* restrict to the server/db in the .ini if in safe mode */
|
|
|
|
if ((!len[DB] || PG(sql_safe_mode)) && IBG(default_db)) {
|
|
|
|
args[DB] = IBG(default_db);
|
|
|
|
len[DB] = strlen(IBG(default_db));
|
|
|
|
}
|
|
|
|
if (!len[USER] && IBG(default_user)) {
|
|
|
|
args[USER] = IBG(default_user);
|
|
|
|
len[USER] = strlen(args[USER]);
|
|
|
|
}
|
|
|
|
if (!len[PASS] && IBG(default_password)) {
|
|
|
|
args[PASS] = IBG(default_password);
|
|
|
|
len[PASS] = strlen(args[PASS]);
|
|
|
|
}
|
|
|
|
if (!len[CSET] && IBG(default_charset)) {
|
|
|
|
args[CSET] = IBG(default_charset);
|
|
|
|
len[CSET] = strlen(args[CSET]);
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* don't want usernames and passwords floating around */
|
|
|
|
PHP_MD5Init(&hash_context);
|
|
|
|
for (i = 0; i < sizeof(args)/sizeof(char*); ++i) {
|
|
|
|
PHP_MD5Update(&hash_context,args[i],len[i]);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2004-02-20 18:59:24 +08:00
|
|
|
for (i = 0; i < sizeof(largs)/sizeof(long); ++i) {
|
|
|
|
PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long));
|
|
|
|
}
|
|
|
|
PHP_MD5Final(hash, &hash_context);
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* try to reuse a connection */
|
|
|
|
if (SUCCESS == zend_hash_find(&EG(regular_list), hash, sizeof(hash), (void *) &le)) {
|
|
|
|
long xlink;
|
|
|
|
int type;
|
2000-05-04 20:28:00 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
if (Z_TYPE_P(le) != le_index_ptr) {
|
|
|
|
RETURN_FALSE;
|
2000-05-04 20:28:00 +08:00
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
xlink = (long) le->ptr;
|
|
|
|
if (zend_list_find(xlink, &type) && ((!persistent && type == le_link) || type == le_plink)) {
|
|
|
|
zend_list_addref(xlink);
|
|
|
|
RETURN_RESOURCE(IBG(default_link) = xlink);
|
|
|
|
} else {
|
|
|
|
zend_hash_del(&EG(regular_list), hash, sizeof(hash));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ... or a persistent one */
|
|
|
|
if (SUCCESS == zend_hash_find(&EG(persistent_list), hash, sizeof(hash), (void *) &le)) {
|
|
|
|
static char info[] = { isc_info_base_level, isc_info_end };
|
|
|
|
char result[8];
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
if (Z_TYPE_P(le) != le_plink) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
/* check if connection has timed out */
|
|
|
|
ib_link = (ibase_db_link *) le->ptr;
|
|
|
|
if (isc_database_info(IB_STATUS, &ib_link->handle, sizeof(info), info, sizeof(result), result)) {
|
|
|
|
zend_hash_del(&EG(persistent_list), hash, sizeof(hash));
|
|
|
|
} else {
|
|
|
|
ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
|
|
|
|
goto register_link_resource;
|
|
|
|
}
|
|
|
|
}
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* no link found, so we have to open one */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
if (IBG(max_links) != -1 && IBG(num_links) >= IBG(max_links)) {
|
|
|
|
_php_ibase_module_error("Too many open links (%ld)" TSRMLS_CC, IBG(num_links));
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-07-07 20:06:05 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* create the ib_link */
|
|
|
|
if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle TSRMLS_CC)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-07-07 20:06:05 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* use non-persistent if allowed number of persistent links is exceeded */
|
|
|
|
if (!persistent || (IBG(max_persistent) != -1 && IBG(num_persistent) >= IBG(max_persistent))) {
|
|
|
|
ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
|
|
|
|
ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link);
|
1999-04-22 10:48:28 +08:00
|
|
|
} else {
|
2004-02-20 18:59:24 +08:00
|
|
|
list_entry new_le;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link));
|
|
|
|
|
|
|
|
/* hash it up */
|
|
|
|
Z_TYPE(new_le) = le_plink;
|
|
|
|
new_le.ptr = ib_link;
|
|
|
|
if (FAILURE == zend_hash_update(&EG(persistent_list), hash, sizeof(hash),
|
|
|
|
(void *) &new_le, sizeof(list_entry), NULL)) {
|
|
|
|
free(ib_link);
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2004-02-20 18:59:24 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
|
|
|
|
++IBG(num_persistent);
|
|
|
|
}
|
|
|
|
ib_link->handle = db_handle;
|
2004-03-08 18:32:26 +08:00
|
|
|
ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT;
|
2004-02-20 18:59:24 +08:00
|
|
|
ib_link->tr_list = NULL;
|
|
|
|
ib_link->event_head = NULL;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
++IBG(num_links);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
register_link_resource:
|
2000-07-07 20:06:05 +08:00
|
|
|
|
2004-02-20 18:59:24 +08:00
|
|
|
/* add it to the hash */
|
|
|
|
new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
|
|
|
|
Z_TYPE(new_index_ptr) = le_index_ptr;
|
|
|
|
if (FAILURE == zend_hash_update(&EG(regular_list), hash, sizeof(hash),
|
|
|
|
(void *) &new_index_ptr, sizeof(list_entry), NULL)) {
|
|
|
|
RETURN_FALSE;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
2004-02-20 18:59:24 +08:00
|
|
|
zend_list_addref(IBG(default_link) = Z_LVAL_P(return_value));
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-12 19:24:24 +08:00
|
|
|
/* {{{ proto resource ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
|
1999-04-22 10:48:28 +08:00
|
|
|
Open a connection to an InterBase database */
|
1999-05-21 18:06:25 +08:00
|
|
|
PHP_FUNCTION(ibase_connect)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2000-03-13 03:44:23 +08:00
|
|
|
_php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-12 19:24:24 +08:00
|
|
|
/* {{{ proto resource ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
|
1999-04-22 10:48:28 +08:00
|
|
|
Open a persistent connection to an InterBase database */
|
1999-05-21 18:06:25 +08:00
|
|
|
PHP_FUNCTION(ibase_pconnect)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2004-02-20 18:59:24 +08:00
|
|
|
_php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, IBG(allow_persistent));
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-12 19:24:24 +08:00
|
|
|
/* {{{ proto bool ibase_close([resource link_identifier])
|
1999-04-22 10:48:28 +08:00
|
|
|
Close an InterBase connection */
|
1999-05-21 18:06:25 +08:00
|
|
|
PHP_FUNCTION(ibase_close)
|
1999-04-22 10:48:28 +08:00
|
|
|
{
|
2003-08-06 07:40:30 +08:00
|
|
|
zval **link_arg = NULL;
|
2000-03-13 03:44:23 +08:00
|
|
|
ibase_db_link *ib_link;
|
2000-07-07 20:06:05 +08:00
|
|
|
int link_id;
|
2004-03-07 22:25:08 +08:00
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
RESET_ERRMSG;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2000-06-06 03:47:54 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
1999-04-22 10:48:28 +08:00
|
|
|
case 0:
|
2000-03-13 03:44:23 +08:00
|
|
|
link_id = IBG(default_link);
|
2003-08-06 23:27:16 +08:00
|
|
|
IBG(default_link) = -1;
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2000-04-30 13:46:04 +08:00
|
|
|
if (zend_get_parameters_ex(1, &link_arg) == FAILURE) {
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-04-30 13:46:04 +08:00
|
|
|
convert_to_long_ex(link_arg);
|
2001-09-26 05:58:48 +08:00
|
|
|
link_id = Z_LVAL_PP(link_arg);
|
1999-04-22 10:48:28 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
2000-04-18 10:52:45 +08:00
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, link_arg, link_id, "InterBase link",
|
|
|
|
le_link, le_plink);
|
2000-03-13 03:44:23 +08:00
|
|
|
zend_list_delete(link_id);
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
/* {{{ proto bool ibase_drop_db([resource link_identifier])
|
|
|
|
Drop an InterBase database */
|
|
|
|
PHP_FUNCTION(ibase_drop_db)
|
|
|
|
{
|
2003-08-06 07:40:30 +08:00
|
|
|
zval **link_arg = NULL;
|
2003-08-05 21:17:16 +08:00
|
|
|
ibase_db_link *ib_link;
|
2003-08-06 23:27:16 +08:00
|
|
|
ibase_tr_list *l;
|
2003-08-05 21:17:16 +08:00
|
|
|
int link_id;
|
2004-03-08 18:32:26 +08:00
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
RESET_ERRMSG;
|
2004-03-08 18:32:26 +08:00
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
|
|
|
case 0:
|
|
|
|
link_id = IBG(default_link);
|
2003-08-06 23:27:16 +08:00
|
|
|
IBG(default_link) = -1;
|
2003-08-05 21:17:16 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &link_arg) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
convert_to_long_ex(link_arg);
|
|
|
|
link_id = Z_LVAL_PP(link_arg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
2003-08-06 23:27:16 +08:00
|
|
|
|
2004-02-02 00:13:07 +08:00
|
|
|
ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, link_arg, link_id, "InterBase link",
|
|
|
|
le_link, le_plink);
|
2003-08-13 02:01:59 +08:00
|
|
|
if (isc_drop_database(IB_STATUS, &ib_link->handle)) {
|
2003-08-05 21:17:16 +08:00
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-08-06 23:27:16 +08:00
|
|
|
|
|
|
|
/* isc_drop_database() doesn't invalidate the transaction handles */
|
2003-08-08 19:04:12 +08:00
|
|
|
for (l = ib_link->tr_list; l != NULL; l = l->next) {
|
2003-08-06 23:27:16 +08:00
|
|
|
if (l->trans != NULL) l->trans->handle = NULL;
|
|
|
|
}
|
|
|
|
|
2003-08-05 21:17:16 +08:00
|
|
|
zend_list_delete(link_id);
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]])
|
|
|
|
Start a transaction over one or several databases */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
#define TPB_MAX_SIZE (8*sizeof(char))
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
PHP_FUNCTION(ibase_trans)
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2004-04-05 21:22:34 +08:00
|
|
|
unsigned short i, argn, link_cnt = 0, tpb_len = 0;
|
|
|
|
char last_tpb[TPB_MAX_SIZE];
|
|
|
|
ibase_db_link **ib_link = NULL;
|
|
|
|
ibase_trans *ib_trans;
|
|
|
|
isc_tr_handle tr_handle = NULL;
|
|
|
|
ISC_STATUS result;
|
2003-08-20 20:40:05 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
RESET_ERRMSG;
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
argn = ZEND_NUM_ARGS();
|
2003-08-13 02:01:59 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* (1+argn) is an upper bound for the number of links this trans connects to */
|
|
|
|
ib_link = (ibase_db_link **) do_alloca(sizeof(ibase_db_link *) * (1+argn));
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (argn > 0) {
|
|
|
|
long trans_argl = 0;
|
|
|
|
char *tpb;
|
|
|
|
ISC_TEB *teb;
|
|
|
|
zval ***args = (zval ***) do_alloca(sizeof(zval **) * argn);
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (zend_get_parameters_array_ex(argn, args) == FAILURE) {
|
|
|
|
free_alloca(args);
|
|
|
|
free_alloca(ib_link);
|
|
|
|
RETURN_FALSE;
|
1999-04-22 10:48:28 +08:00
|
|
|
}
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
teb = (ISC_TEB *) do_alloca(sizeof(ISC_TEB) * argn);
|
|
|
|
tpb = (char *) do_alloca(TPB_MAX_SIZE * argn);
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* enumerate all the arguments: assume every non-resource argument
|
|
|
|
specifies modifiers for the link ids that follow it */
|
|
|
|
for (i = 0; i < argn; ++i) {
|
|
|
|
|
|
|
|
if (Z_TYPE_PP(args[i]) == IS_RESOURCE) {
|
|
|
|
|
|
|
|
ZEND_FETCH_RESOURCE2(ib_link[link_cnt], ibase_db_link *, args[i], -1,
|
|
|
|
"InterBase link", le_link, le_plink);
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* copy the most recent modifier string into tbp[] */
|
|
|
|
memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE);
|
2003-09-05 22:21:25 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* add a database handle to the TEB with the most recently specified set of modifiers */
|
|
|
|
teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle;
|
|
|
|
teb[link_cnt].tpb_len = tpb_len;
|
|
|
|
teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt];
|
2003-09-05 06:37:14 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
++link_cnt;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
tpb_len = 0;
|
2003-09-05 06:37:14 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
convert_to_long_ex(args[i]);
|
|
|
|
trans_argl = Z_LVAL_PP(args[i]);
|
2003-09-05 06:37:14 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (trans_argl != PHP_IBASE_DEFAULT) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_version3;
|
2004-03-07 22:25:08 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* access mode */
|
|
|
|
if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_read;
|
|
|
|
} else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_write;
|
|
|
|
}
|
2003-09-05 22:21:25 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* isolation level */
|
|
|
|
if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_read_committed;
|
|
|
|
if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_rec_version;
|
|
|
|
} else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_no_rec_version;
|
|
|
|
}
|
|
|
|
} else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_consistency;
|
|
|
|
} else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_concurrency;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lock resolution */
|
|
|
|
if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_nowait;
|
|
|
|
} else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) {
|
|
|
|
last_tpb[tpb_len++] = isc_tpb_wait;
|
|
|
|
}
|
|
|
|
}
|
2003-09-05 22:21:25 +08:00
|
|
|
}
|
2004-04-05 21:22:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (link_cnt > 0) {
|
|
|
|
result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb);
|
2003-09-05 06:37:14 +08:00
|
|
|
}
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
free_alloca(args);
|
|
|
|
free_alloca(tpb);
|
|
|
|
free_alloca(teb);
|
|
|
|
}
|
2003-09-05 06:37:14 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (link_cnt == 0) {
|
|
|
|
link_cnt = 1;
|
|
|
|
ZEND_FETCH_RESOURCE2(ib_link[0], ibase_db_link *, NULL, IBG(default_link), "InterBase link",
|
|
|
|
le_link, le_plink);
|
|
|
|
result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* start the transaction */
|
|
|
|
if (result) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
free_alloca(ib_link);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-09-05 06:37:14 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* register the transaction in our own data structures */
|
|
|
|
ib_trans = (ibase_trans *) safe_emalloc((link_cnt-1), sizeof(ibase_db_link *), sizeof(ibase_trans));
|
|
|
|
ib_trans->handle = tr_handle;
|
|
|
|
ib_trans->link_cnt = link_cnt;
|
|
|
|
ib_trans->affected_rows = 0;
|
|
|
|
for (i = 0; i < link_cnt; ++i) {
|
2003-08-13 02:01:59 +08:00
|
|
|
ibase_tr_list **l;
|
2004-04-05 21:22:34 +08:00
|
|
|
ib_trans->db_link[i] = ib_link[i];
|
2004-03-08 18:32:26 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* the first item in the connection-transaction list is reserved for the default transaction */
|
|
|
|
if (ib_link[i]->tr_list == NULL) {
|
|
|
|
ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
|
|
|
|
ib_link[i]->tr_list->trans = NULL;
|
|
|
|
ib_link[i]->tr_list->next = NULL;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
2003-08-17 20:31:55 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* link the transaction into the connection-transaction list */
|
|
|
|
for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next);
|
|
|
|
*l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
|
|
|
|
(*l)->trans = ib_trans;
|
|
|
|
(*l)->next = NULL;
|
2003-08-05 21:17:16 +08:00
|
|
|
}
|
2003-08-06 07:40:30 +08:00
|
|
|
free_alloca(ib_link);
|
2000-10-05 20:47:39 +08:00
|
|
|
ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans);
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC) /* {{{ */
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2004-04-05 21:22:34 +08:00
|
|
|
if (ib_link == NULL) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid database link");
|
|
|
|
return FAILURE;
|
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* the first item in the connection-transaction list is reserved for the default transaction */
|
|
|
|
if (ib_link->tr_list == NULL) {
|
|
|
|
ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
|
|
|
|
ib_link->tr_list->trans = NULL;
|
|
|
|
ib_link->tr_list->next = NULL;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
2000-04-30 13:46:04 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (*trans == NULL) {
|
|
|
|
ibase_trans *tr = ib_link->tr_list->trans;
|
|
|
|
|
|
|
|
if (tr == NULL) {
|
|
|
|
tr = (ibase_trans *) emalloc(sizeof(ibase_trans));
|
|
|
|
tr->handle = NULL;
|
|
|
|
tr->link_cnt = 1;
|
|
|
|
tr->affected_rows = 0;
|
|
|
|
tr->db_link[0] = ib_link;
|
|
|
|
ib_link->tr_list->trans = tr;
|
|
|
|
}
|
|
|
|
if (tr->handle == NULL) {
|
|
|
|
if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*trans = tr;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2003-08-05 21:17:16 +08:00
|
|
|
ibase_trans *trans = NULL;
|
2004-04-05 21:22:34 +08:00
|
|
|
int res_id = 0;
|
|
|
|
ISC_STATUS result;
|
2000-03-13 03:44:23 +08:00
|
|
|
|
|
|
|
RESET_ERRMSG;
|
|
|
|
|
2000-06-06 03:47:54 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
2004-04-05 21:22:34 +08:00
|
|
|
|
|
|
|
ibase_db_link *ib_link;
|
|
|
|
zval **arg;
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), "InterBase link",
|
|
|
|
le_link, le_plink);
|
|
|
|
if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
|
|
|
|
/* this link doesn't have a default transaction */
|
|
|
|
_php_ibase_module_error("Default link has no default transaction" TSRMLS_CC);
|
1999-04-22 10:48:28 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2004-04-05 21:22:34 +08:00
|
|
|
trans = ib_link->tr_list->trans;
|
2000-03-13 03:44:23 +08:00
|
|
|
break;
|
2004-04-05 21:22:34 +08:00
|
|
|
|
|
|
|
case 1:
|
|
|
|
if (zend_get_parameters_ex(1, &arg) == FAILURE) {
|
2000-03-13 03:44:23 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2004-04-05 21:22:34 +08:00
|
|
|
/* one id was passed, could be db or trans id */
|
|
|
|
_php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, arg, &ib_link, &trans);
|
|
|
|
if (trans != NULL) {
|
|
|
|
convert_to_long_ex(arg);
|
|
|
|
res_id = Z_LVAL_PP(arg);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, arg, -1, "InterBase link",
|
|
|
|
le_link, le_plink);
|
|
|
|
|
|
|
|
if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
|
|
|
|
/* this link doesn't have a default transaction */
|
|
|
|
_php_ibase_module_error("Link has no default transaction" TSRMLS_CC);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
trans = ib_link->tr_list->trans;
|
2003-08-13 02:01:59 +08:00
|
|
|
}
|
2000-03-13 03:44:23 +08:00
|
|
|
break;
|
2004-04-05 21:22:34 +08:00
|
|
|
|
2000-03-13 03:44:23 +08:00
|
|
|
default:
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
switch (commit) {
|
|
|
|
|
|
|
|
default: /* == case ROLLBACK: */
|
|
|
|
result = isc_rollback_transaction(IB_STATUS, &trans->handle);
|
|
|
|
break;
|
|
|
|
case COMMIT:
|
|
|
|
result = isc_commit_transaction(IB_STATUS, &trans->handle);
|
|
|
|
break;
|
|
|
|
#if HAVE_IBASE6_API
|
|
|
|
case (ROLLBACK | RETAIN):
|
|
|
|
result = isc_rollback_retaining(IB_STATUS, &trans->handle);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case (COMMIT | RETAIN):
|
|
|
|
result = isc_commit_retaining(IB_STATUS, &trans->handle);
|
|
|
|
break;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
if (result) {
|
|
|
|
_php_ibase_error(TSRMLS_C);
|
2000-03-13 03:44:23 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2004-04-05 21:22:34 +08:00
|
|
|
|
|
|
|
/* Don't try to destroy implicitly opened transaction from list... */
|
|
|
|
if ( (commit & RETAIN) == 0 && res_id != 0) {
|
|
|
|
zend_list_delete(res_id);
|
|
|
|
}
|
|
|
|
RETURN_TRUE;
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* {{{ proto bool ibase_commit( resource link_identifier )
|
|
|
|
Commit transaction */
|
|
|
|
PHP_FUNCTION(ibase_commit)
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2004-04-05 21:22:34 +08:00
|
|
|
_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT);
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* {{{ proto bool ibase_rollback( resource link_identifier )
|
|
|
|
Rollback transaction */
|
|
|
|
PHP_FUNCTION(ibase_rollback)
|
2000-03-13 03:44:23 +08:00
|
|
|
{
|
2004-04-05 21:22:34 +08:00
|
|
|
_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK);
|
|
|
|
}
|
|
|
|
/* }}} */
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* {{{ proto bool ibase_commit_ret( resource link_identifier )
|
|
|
|
Commit transaction and retain the transaction context */
|
|
|
|
PHP_FUNCTION(ibase_commit_ret)
|
|
|
|
{
|
|
|
|
_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN);
|
|
|
|
}
|
|
|
|
/* }}} */
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-04-05 21:22:34 +08:00
|
|
|
/* {{{ proto bool ibase_rollback_ret( resource link_identifier )
|
|
|
|
Rollback transaction and retain the transaction context */
|
|
|
|
#if HAVE_IBASE6_API
|
|
|
|
PHP_FUNCTION(ibase_rollback_ret)
|
|
|
|
{
|
|
|
|
_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN);
|
2000-03-13 03:44:23 +08:00
|
|
|
}
|
2004-04-05 21:22:34 +08:00
|
|
|
#endif
|
2000-03-13 03:44:23 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2002-07-19 17:21:29 +08:00
|
|
|
#if HAVE_STRFTIME
|
2004-03-08 18:32:26 +08:00
|
|
|
/* {{{ proto bool ibase_timefmt(string format [, int type ])
|
2000-05-12 11:02:14 +08:00
|
|
|
Sets the format of timestamp, date and time columns returned from queries */
|
2000-03-13 03:44:23 +08:00
|
|
|
PHP_FUNCTION(ibase_timefmt)
|
|
|
|
{
|
2003-03-16 13:00:50 +08:00
|
|
|
zval ***args;
|
2000-05-12 11:02:14 +08:00
|
|
|
char *fmt = NULL;
|
|
|
|
int type = PHP_IBASE_TIMESTAMP;
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2003-03-16 13:00:50 +08:00
|
|
|
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2) {
|
2000-03-13 03:44:23 +08:00
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
|
2003-08-12 08:58:52 +08:00
|
|
|
args = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);
|
2000-06-06 03:47:54 +08:00
|
|
|
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
|
2000-05-12 11:02:14 +08:00
|
|
|
efree(args);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2000-06-06 03:47:54 +08:00
|
|
|
switch (ZEND_NUM_ARGS()) {
|
2000-05-12 11:02:14 +08:00
|
|
|
case 2:
|
|
|
|
convert_to_long_ex(args[1]);
|
2001-09-26 06:49:04 +08:00
|
|
|
type = Z_LVAL_PP(args[1]);
|
2000-05-12 11:02:14 +08:00
|
|
|
case 1:
|
|
|
|
convert_to_string_ex(args[0]);
|
2001-09-26 06:49:04 +08:00
|
|
|
fmt = Z_STRVAL_PP(args[0]);
|
2000-05-12 11:02:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case PHP_IBASE_TIMESTAMP:
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timestampformat)) {
|
2000-05-12 11:02:14 +08:00
|
|
|
DL_FREE(IBG(timestampformat));
|
2003-03-16 13:00:50 +08:00
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(timestampformat) = DL_STRDUP(fmt);
|
|
|
|
break;
|
|
|
|
case PHP_IBASE_DATE:
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(dateformat)) {
|
2000-05-12 11:02:14 +08:00
|
|
|
DL_FREE(IBG(dateformat));
|
2003-03-16 13:00:50 +08:00
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(dateformat) = DL_STRDUP(fmt);
|
|
|
|
break;
|
|
|
|
case PHP_IBASE_TIME:
|
2003-03-16 13:00:50 +08:00
|
|
|
if (IBG(timeformat)) {
|
2000-05-12 11:02:14 +08:00
|
|
|
DL_FREE(IBG(timeformat));
|
2003-03-16 13:00:50 +08:00
|
|
|
}
|
2000-05-12 11:02:14 +08:00
|
|
|
IBG(timeformat) = DL_STRDUP(fmt);
|
|
|
|
break;
|
|
|
|
}
|
2003-03-16 13:00:50 +08:00
|
|
|
|
2000-05-12 11:02:14 +08:00
|
|
|
efree(args);
|
2000-03-13 03:44:23 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2002-07-19 17:21:29 +08:00
|
|
|
#endif
|
2000-03-13 03:44:23 +08:00
|
|
|
|
2004-02-17 20:53:54 +08:00
|
|
|
/* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]])
|
2003-09-24 04:58:14 +08:00
|
|
|
Increments the named generator and returns its new value */
|
|
|
|
PHP_FUNCTION(ibase_gen_id)
|
|
|
|
{
|
2004-02-17 20:53:54 +08:00
|
|
|
zval *link = NULL;
|
|
|
|
char query[128], *generator;
|
2004-03-08 18:32:26 +08:00
|
|
|
int gen_len;
|
|
|
|
long inc = 1;
|
2003-09-24 04:58:14 +08:00
|
|
|
ibase_db_link *ib_link;
|
|
|
|
ibase_trans *trans = NULL;
|
2004-02-17 20:53:54 +08:00
|
|
|
XSQLDA out_sqlda;
|
2003-09-24 04:58:14 +08:00
|
|
|
#ifdef SQL_INT64
|
|
|
|
ISC_INT64 result;
|
|
|
|
#else
|
|
|
|
ISC_LONG result;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RESET_ERRMSG;
|
|
|
|
|
2004-02-17 20:53:54 +08:00
|
|
|
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &generator, &gen_len, &inc, &link);
|
2003-09-24 04:58:14 +08:00
|
|
|
|
2004-02-17 20:53:54 +08:00
|
|
|
PHP_IBASE_LINK_TRANS(link, ib_link, trans);
|
2003-09-24 04:58:14 +08:00
|
|
|
|
2004-02-17 20:53:54 +08:00
|
|
|
sprintf(query, "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc);
|
2003-09-24 04:58:14 +08:00
|
|
|
|
|
|
|
/* allocate a minimal descriptor area */
|
|
|
|
out_sqlda.sqln = out_sqlda.sqld = 1;
|
|
|
|
out_sqlda.version = SQLDA_CURRENT_VERSION;
|
|
|
|
|
|
|
|
/* allocate the field for the result */
|
|
|
|
#ifdef SQL_INT64
|
|
|
|
out_sqlda.sqlvar[0].sqltype = SQL_INT64;
|
|
|
|
#else
|
|
|
|
out_sqlda.sqlvar[0].sqltype = SQL_LONG;
|
|
|
|
#endif
|
|
|
|
out_sqlda.sqlvar[0].sqlscale = 0;
|
|
|
|
out_sqlda.sqlvar[0].sqllen = sizeof(result);
|
|
|
|
out_sqlda.sqlvar[0].sqldata = (void*) &result;
|
|
|
|
|
|
|
|
/* execute the query */
|
2004-02-17 20:53:54 +08:00
|
|
|
if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query,
|
|
|
|
SQL_DIALECT_CURRENT, NULL, &out_sqlda)) {
|
2003-09-24 04:58:14 +08:00
|
|
|
_php_ibase_error(TSRMLS_C);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't return the generator value as a string unless it doesn't fit in a long */
|
2004-04-03 19:00:14 +08:00
|
|
|
#if SQL_INT64 && SIZEOF_LONG < 8
|
2004-02-17 20:53:54 +08:00
|
|
|
if (result < LONG_MIN || result > LONG_MAX) {
|
2003-09-24 04:58:14 +08:00
|
|
|
char res[24];
|
|
|
|
|
2004-02-17 20:53:54 +08:00
|
|
|
sprintf(res, "%" LL_MASK "d", result);
|
2003-09-24 04:58:14 +08:00
|
|
|
RETURN_STRING(res,1);
|
|
|
|
}
|
2003-09-24 07:08:59 +08:00
|
|
|
#endif
|
2003-09-24 04:58:14 +08:00
|
|
|
RETURN_LONG((long)result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
2004-04-03 19:00:14 +08:00
|
|
|
|
2002-01-27 23:31:15 +08:00
|
|
|
#endif /* HAVE_IBASE */
|
1999-04-22 10:48:28 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* tab-width: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* End:
|
2001-09-09 21:29:31 +08:00
|
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
|
|
* vim<600: sw=4 ts=4
|
1999-04-22 10:48:28 +08:00
|
|
|
*/
|