diff --git a/.gitignore b/.gitignore index 684a972..110ac07 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ yaml.loT .FBCIndex .FBCLockFolder core +*.dep # Test specific Ignores tests/*.diff diff --git a/config.m4 b/config.m4 index 74e62e8..0ba0ca9 100644 --- a/config.m4 +++ b/config.m4 @@ -54,6 +54,22 @@ if test "$PHP_INTERBASE" != "no"; then fi AC_DEFINE(HAVE_IBASE,1,[ ]) - PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,[cxx]) PHP_SUBST(INTERBASE_SHARED_LIBADD) + + PHP_REQUIRE_CXX() + PHP_CXX_COMPILE_STDCXX([11], [mandatory], [PHP_INTERBASE_STDCXX]) + + PHP_INTERBASE_CXX_SOURCES="pdo_firebird_utils.cpp" + + AS_VAR_IF([ext_shared], [no], + [PHP_ADD_SOURCES([$ext_dir], + [$PHP_INTERBASE_CXX_SOURCES], + [$PHP_INTERBASE_STDCXX])], + [PHP_ADD_SOURCES_X([$ext_dir], + [$PHP_INTERBASE_CXX_SOURCES], + [$PHP_INTERBASE_STDCXX], + [shared_objects_interbase], + [yes])]) + fi diff --git a/config.w32 b/config.w32 index c1f5a91..883e189 100644 --- a/config.w32 +++ b/config.w32 @@ -3,13 +3,13 @@ ARG_WITH("interbase", "InterBase support", "no"); if (PHP_INTERBASE != "no") { - - if (CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_INTERBASE", - PHP_PHP_BUILD + "\\include\\interbase;" + PHP_PHP_BUILD + "\\interbase\\include;" + PHP_INTERBASE) && - (CHECK_LIB("fbclient_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE) || - CHECK_LIB("gds32_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE))) { - - EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c", PHP_INTERBASE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + if ( + CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_INTERBASE", PHP_INTERBASE + "\\include") && ( + CHECK_LIB("fbclient_ms.lib", "interbase", PHP_INTERBASE + "\\lib") || + CHECK_LIB("gds32_ms.lib", "interbase", PHP_INTERBASE + "\\lib") + ) + ) { + EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c pdo_firebird_utils.cpp", PHP_INTERBASE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE('HAVE_IBASE', 1, 'Have interbase library'); } else { WARNING("interbase not enabled; libraries and headers not found"); diff --git a/ibase_query.c b/ibase_query.c index f959848..2e07a94 100644 --- a/ibase_query.c +++ b/ibase_query.c @@ -37,15 +37,16 @@ #include "ext/standard/php_standard.h" #include "php_interbase.h" #include "php_ibase_includes.h" +#include "pdo_firebird_utils.h" -#define ISC_LONG_MIN INT_MIN -#define ISC_LONG_MAX INT_MAX +#define ISC_LONG_MIN INT_MIN +#define ISC_LONG_MAX INT_MAX -#define QUERY_RESULT 1 -#define EXECUTE_RESULT 2 +#define QUERY_RESULT 1 +#define EXECUTE_RESULT 2 -#define FETCH_ROW 1 -#define FETCH_ARRAY 2 +#define FETCH_ROW 1 +#define FETCH_ARRAY 2 typedef struct { ISC_ARRAY_DESC ar_desc; @@ -96,7 +97,7 @@ typedef struct { union { // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - FB_BOOLEAN bval; + FB_BOOLEAN bval; #endif short sval; float fval; @@ -220,9 +221,9 @@ void php_ibase_query_minit(INIT_FUNC_ARGS) /* {{{ */ le_statement = zend_register_list_destructors_ex(_php_ibase_free_statement, NULL, "interbase statement", module_number); le_result = zend_register_list_destructors_ex(_php_ibase_free_result, NULL, - "interbase result", module_number); + "interbase result", module_number); le_query = zend_register_list_destructors_ex(php_ibase_free_query_rsrc, NULL, - "interbase query", module_number); + "interbase query", module_number); } /* }}} */ @@ -266,10 +267,10 @@ static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ break; // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case blr_bool: - a->el_type = SQL_BOOLEAN; - a->el_size = sizeof(FB_BOOLEAN); - break; + case blr_bool: + a->el_type = SQL_BOOLEAN; + a->el_size = sizeof(FB_BOOLEAN); + break; #endif case blr_short: a->el_type = SQL_SHORT; @@ -303,6 +304,20 @@ static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ a->el_type = SQL_TYPE_TIME; a->el_size = sizeof(ISC_TIME); break; +#if FB_API_VER >= 40 + // These are converted to VARCHAR via isc_dpb_set_bind tag at connect + // blr_dec64 + // blr_dec128 + // blr_int128 + case blr_sql_time_tz: + a->el_type = SQL_TIME_TZ; + a->el_size = sizeof(ISC_TIME_TZ); + break; + case blr_timestamp_tz: + a->el_type = SQL_TIMESTAMP_TZ; + a->el_size = sizeof(ISC_TIMESTAMP_TZ); + break; +#endif case blr_varying: case blr_varying2: /** @@ -614,17 +629,19 @@ static int _php_ibase_bind_array(zval *val, char *buf, zend_ulong buf_size, /* { break; // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case SQL_BOOLEAN: - convert_to_boolean(val); - // On Windows error unresolved symbol Z_BVAL_P is thrown, so we use Z_LVAL_P - *(FB_BOOLEAN*) buf = Z_LVAL_P(val); - break; + case SQL_BOOLEAN: + convert_to_boolean(val); + // On Windows error unresolved symbol Z_BVAL_P is thrown, so we use Z_LVAL_P + *(FB_BOOLEAN*) buf = Z_LVAL_P(val); + break; #endif case SQL_DOUBLE: convert_to_double(val); *(double*) buf = Z_DVAL_P(val); break; case SQL_TIMESTAMP: + // TODO: + // case SQL_TIMESTAMP_TZ: convert_to_string(val); #ifdef HAVE_STRPTIME strptime(Z_STRVAL_P(val), INI_STR("ibase.timestampformat"), &t); @@ -660,6 +677,8 @@ static int _php_ibase_bind_array(zval *val, char *buf, zend_ulong buf_size, /* { isc_encode_sql_date(&t, (ISC_DATE *) buf); break; case SQL_TYPE_TIME: + // TODO: + // case SQL_TIME_TZ: convert_to_string(val); #ifdef HAVE_STRPTIME strptime(Z_STRVAL_P(val), INI_STR("ibase.timeformat"), &t); @@ -714,6 +733,13 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ case SQL_TIMESTAMP: case SQL_TYPE_DATE: case SQL_TYPE_TIME: +#if FB_API_VER >= 40 + case SQL_INT128: + case SQL_DEC16: + case SQL_DEC34: + case SQL_TIMESTAMP_TZ: + case SQL_TIME_TZ: +#endif force_null = (Z_STRLEN_P(b_var) == 0); } @@ -721,6 +747,7 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ case IS_NULL: buf[i].sqlind = -1; + sqlda->sqlvar->sqldata = NULL; if (var->sqltype & SQL_ARRAY) ++array_cnt; @@ -737,6 +764,9 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ struct tm t; case SQL_TIMESTAMP: + // TODO: + // case SQL_TIMESTAMP_TZ: + // case SQL_TIME_TZ: case SQL_TYPE_DATE: case SQL_TYPE_TIME: if (Z_TYPE_P(b_var) == IS_LONG) { @@ -756,6 +786,8 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ format = INI_STR("ibase.dateformat"); break; case SQL_TYPE_TIME: + // TODO: + // case SQL_TIME_TZ: format = INI_STR("ibase.timeformat"); } if (!strptime(Z_STRVAL_P(b_var), format, &t)) { @@ -775,6 +807,8 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ isc_encode_sql_date(&t, &buf[i].val.dtval); break; case SQL_TYPE_TIME: + // TODO: + // case SQL_TIME_TZ: isc_encode_sql_time(&t, &buf[i].val.tmval); break; } @@ -922,9 +956,9 @@ static void _php_ibase_alloc_xsqlda(XSQLDA *sqlda) /* {{{ */ break; // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case SQL_BOOLEAN: - var->sqldata = emalloc(sizeof(FB_BOOLEAN)); - break; + case SQL_BOOLEAN: + var->sqldata = emalloc(sizeof(FB_BOOLEAN)); + break; #endif case SQL_SHORT: var->sqldata = emalloc(sizeof(short)); @@ -954,6 +988,21 @@ static void _php_ibase_alloc_xsqlda(XSQLDA *sqlda) /* {{{ */ case SQL_ARRAY: var->sqldata = emalloc(sizeof(ISC_QUAD)); break; +#if FB_API_VER >= 40 + // These are converted to VARCHAR via isc_dpb_set_bind tag at connect + // case SQL_DEC16: + // case SQL_DEC34: + // case SQL_INT128: + case SQL_TIMESTAMP_TZ: + var->sqldata = emalloc(sizeof(ISC_TIMESTAMP_TZ)); + break; + case SQL_TIME_TZ: + var->sqldata = emalloc(sizeof(ISC_TIME_TZ)); + break; +#endif + default: + php_error(E_WARNING, "Unhandled sqltype: %d for sqlname %s %s:%d", var->sqltype, var->sqlname, __FILE__, __LINE__); + break; } /* switch */ if (var->sqltype & 1) { /* sql NULL flag */ @@ -1055,7 +1104,7 @@ static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resul res->trans = ib_query->trans; res->stmt = ib_query->stmt; GC_ADDREF(res->stmt_res = ib_query->stmt_res); - + res->statement_type = ib_query->statement_type; res->has_more_rows = 1; @@ -1183,7 +1232,7 @@ PHP_FUNCTION(ibase_query) zend_long l; default: - if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3, "rrs", + if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3, "rrs", &zlink, &ztrans, &query, &query_len)) { ib_link = (ibase_db_link*)zend_fetch_resource2_ex(zlink, LE_LINK, le_link, le_plink); @@ -1192,7 +1241,7 @@ PHP_FUNCTION(ibase_query) trans_res = Z_RES_P(ztrans); bind_i = 3; break; - } + } case 2: if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2, "rs", &zlink, &query, &query_len)) { @@ -1260,7 +1309,7 @@ PHP_FUNCTION(ibase_query) do { int bind_n = ZEND_NUM_ARGS() - bind_i, - expected_n = ib_query.in_sqlda ? ib_query.in_sqlda->sqld : 0; + expected_n = ib_query.in_sqlda ? ib_query.in_sqlda->sqld : 0; if (bind_n != expected_n) { php_error_docref(NULL, (bind_n < expected_n) ? E_WARNING : E_NOTICE, @@ -1427,9 +1476,9 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ break; // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case SQL_BOOLEAN: - ZVAL_BOOL(val, *(FB_BOOLEAN *) data); - break; + case SQL_BOOLEAN: + ZVAL_BOOL(val, *(FB_BOOLEAN *) data); + break; #endif case SQL_SHORT: n = *(short *) data; @@ -1480,6 +1529,44 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ case SQL_DOUBLE: ZVAL_DOUBLE(val, *(double *) data); break; +#if FB_API_VER >= 40 + // These are converted to VARCHAR via isc_dpb_set_bind tag at connect + // case SQL_DEC16: + // case SQL_DEC34: + // case SQL_INT128: + case SQL_TIME_TZ: + case SQL_TIMESTAMP_TZ: + char timeZoneBuffer[40] = {0}; + unsigned year, month, day, hours, minutes, seconds, fractions; + + if((type & ~1) == SQL_TIME_TZ){ + format = INI_STR("ibase.timeformat"); + fb_decode_time_tz((ISC_TIME_TZ *) data, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer); + ISC_TIME time = fb_encode_time(hours, minutes, seconds, fractions); + isc_decode_sql_time(&time, &t); + } else { + format = INI_STR("ibase.timestampformat"); + fb_decode_timestamp_tz((ISC_TIMESTAMP_TZ *) data, &year, &month, &day, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer); + ISC_TIMESTAMP ts; + ts.timestamp_date = fb_encode_date(year, month, day); + ts.timestamp_time = fb_encode_time(hours, minutes, seconds, fractions); + isc_decode_timestamp(&ts, &t); + } + + if (flag & PHP_IBASE_UNIXTIME) { + ZVAL_LONG(val, mktime(&t)); + } else { + char timeBuf[80] = {0}; + l = strftime(timeBuf, sizeof(timeBuf), format, &t); + if (l == 0) { + return FAILURE; + } + + size_t l = sprintf(string_data, "%s %s", timeBuf, timeZoneBuffer); + ZVAL_STRINGL(val, string_data, l); + } + break; +#endif case SQL_DATE: /* == case SQL_TIMESTAMP: */ format = INI_STR("ibase.timestampformat"); isc_decode_timestamp((ISC_TIMESTAMP *) data, &t); @@ -1811,12 +1898,12 @@ PHP_FUNCTION(ibase_free_result) ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result); zend_list_delete(Z_RES_P(result_arg)); - - /* - * Bugfix of issue #40 - * Reset pointer after freeing to NULL - */ - Z_RES_P(result_arg)->ptr = NULL; + + /* + * Bugfix of issue #40 + * Reset pointer after freeing to NULL + */ + Z_RES_P(result_arg)->ptr = NULL; RETURN_TRUE; } @@ -1919,9 +2006,8 @@ PHP_FUNCTION(ibase_execute) ib_query->result_res = NULL; } - if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, ib_query, - args)) { - break; + if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, ib_query, args)) { + break; } /* free the query if trans handle was released */ @@ -2037,9 +2123,9 @@ static void _php_ibase_field_info(zval *return_value, XSQLVAR *var) /* {{{ */ switch (var->sqltype & ~1) { // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case SQL_BOOLEAN: - precision = 1; - break; + case SQL_BOOLEAN: + precision = 1; + break; #endif case SQL_SHORT: precision = 4; @@ -2067,9 +2153,9 @@ static void _php_ibase_field_info(zval *return_value, XSQLVAR *var) /* {{{ */ break; // Boolean data type exists since FB 3.0 #ifdef SQL_BOOLEAN - case SQL_BOOLEAN: - s = "BOOLEAN"; - break; + case SQL_BOOLEAN: + s = "BOOLEAN"; + break; #endif case SQL_LONG: s = "INTEGER"; @@ -2102,6 +2188,18 @@ static void _php_ibase_field_info(zval *return_value, XSQLVAR *var) /* {{{ */ case SQL_QUAD: s = "QUAD"; break; +#if FB_API_VER >= 40 + // These are converted to VARCHAR via isc_dpb_set_bind tag at connect and will appear to clients as VARCHAR + // case SQL_DEC16: + // case SQL_DEC34: + // case SQL_INT128: + case SQL_TIMESTAMP_TZ: + s = "TIMESTAMP_TZ"; + break; + case SQL_TIME_TZ: + s = "TIME_TZ"; + break; +#endif } add_index_string(return_value, 4, s); add_assoc_string(return_value, "type", s); diff --git a/interbase.c b/interbase.c index f34d59b..3d93ac0 100644 --- a/interbase.c +++ b/interbase.c @@ -45,9 +45,9 @@ #include -#define ROLLBACK 0 -#define COMMIT 1 -#define RETAIN 2 +#define ROLLBACK 0 +#define COMMIT 1 +#define RETAIN 2 #define CHECK_LINK(link) { if (link==NULL) { php_error_docref(NULL, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } @@ -90,8 +90,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0) - ZEND_ARG_INFO(0, link_identifier) - ZEND_ARG_INFO(0, trans_args) + ZEND_ARG_VARIADIC_INFO(0, trans_args) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 0) @@ -707,6 +706,67 @@ static PHP_INI_DISP(php_ibase_password_displayer_cb) } } +#define PUTS_TP(str) do { \ + if(has_puts) { \ + PUTS(" | "); \ + } \ + PUTS(str); \ + has_puts = true; \ +} while (0) + +static PHP_INI_DISP(php_ibase_trans_displayer) +{ + bool has_puts = false; + char *value; + + if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) { + value = ZSTR_VAL(ini_entry->orig_value); + } else if (ini_entry->value) { + value = ZSTR_VAL(ini_entry->value); + } else { + value = NULL; + } + + if (value) { + zend_long trans_argl = atol(value); + + if (trans_argl != PHP_IBASE_DEFAULT) { + /* access mode */ + if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) { + PUTS_TP("IBASE_READ"); + } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) { + PUTS_TP("IBASE_WRITE"); + } + + /* isolation level */ + if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) { + PUTS_TP("IBASE_COMMITTED"); + if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) { + PUTS_TP("IBASE_REC_VERSION"); + } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) { + PUTS_TP("IBASE_REC_NO_VERSION"); + } + } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) { + PUTS_TP("IBASE_CONSISTENCY"); + } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) { + PUTS_TP("IBASE_CONCURRENCY"); + } + + /* lock resolution */ + if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) { + PUTS_TP("IBASE_NOWAIT"); + } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) { + PUTS_TP("IBASE_WAIT"); + if (PHP_IBASE_LOCK_TIMEOUT == (trans_argl & PHP_IBASE_LOCK_TIMEOUT)) { + PUTS_TP("IBASE_LOCK_TIMEOUT"); + } + } + } else { + PUTS_TP("IBASE_DEFAULT"); + } + } +} + /* {{{ startup, shutdown and info functions */ PHP_INI_BEGIN() PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb) @@ -719,6 +779,8 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL) PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) + STD_PHP_INI_ENTRY_EX("ibase.default_trans_params", "0", PHP_INI_ALL, OnUpdateLongGEZero, default_trans_params, zend_ibase_globals, ibase_globals, php_ibase_trans_displayer) + STD_PHP_INI_ENTRY_EX("ibase.default_lock_timeout", "0", PHP_INI_ALL, OnUpdateLongGEZero, default_lock_timeout, zend_ibase_globals, ibase_globals, display_link_numbers) PHP_INI_END() static PHP_GINIT_FUNCTION(ibase) @@ -884,6 +946,15 @@ int _php_ibase_attach_db(char **args, size_t *len, zend_long *largs, isc_db_hand dpb += dpb_len; buf_len -= dpb_len; } + +#if FB_API_VER >= 40 + // Do not handle directly INT128 or DECFLOAT, convert to VARCHAR at server instead + const char *compat = "int128 to varchar;decfloat to varchar"; + dpb_len = slprintf(dpb, buf_len, "%c%c%s", isc_dpb_set_bind, strlen(compat), compat); + dpb += dpb_len; + buf_len -= dpb_len; +#endif + if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) { _php_ibase_error(); return FAILURE; @@ -1133,6 +1204,54 @@ PHP_FUNCTION(ibase_drop_db) #define TPB_MAX_SIZE (8*sizeof(char)) +void _php_ibase_populate_trans(zend_long trans_argl, zend_long trans_timeout, char *last_tpb, unsigned short *len) /* {{{ */ +{ + unsigned short tpb_len = 0; + if (trans_argl != PHP_IBASE_DEFAULT) { + last_tpb[tpb_len++] = isc_tpb_version3; + + /* 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; + } + + /* 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; + if (PHP_IBASE_LOCK_TIMEOUT == (trans_argl & PHP_IBASE_LOCK_TIMEOUT)) { + if (trans_timeout <= 0 || trans_timeout > 0x7FFF) { + php_error_docref(NULL, E_WARNING, "Invalid timeout parameter"); + } else { + last_tpb[tpb_len++] = isc_tpb_lock_timeout; + last_tpb[tpb_len++] = sizeof(ISC_SHORT); + last_tpb[tpb_len] = (ISC_SHORT)trans_timeout; + tpb_len += sizeof(ISC_SHORT); + } + } + } + } + *len = tpb_len; +} +/* }}} */ + PHP_FUNCTION(ibase_trans) { unsigned short i, link_cnt = 0, tpb_len = 0; @@ -1192,55 +1311,20 @@ PHP_FUNCTION(ibase_trans) convert_to_long_ex(&args[i]); trans_argl = Z_LVAL(args[i]); - if (trans_argl != PHP_IBASE_DEFAULT) { - last_tpb[tpb_len++] = isc_tpb_version3; - - /* 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; - } - - /* 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; + // Skip conflicting parameters + if (PHP_IBASE_NOWAIT != (trans_argl & PHP_IBASE_NOWAIT) && PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) { if (PHP_IBASE_LOCK_TIMEOUT == (trans_argl & PHP_IBASE_LOCK_TIMEOUT)) { if((i + 1 < argn) && (Z_TYPE(args[i + 1]) == IS_LONG)){ i++; convert_to_long_ex(&args[i]); trans_timeout = Z_LVAL(args[i]); - - if (trans_timeout <= 0 || trans_timeout > 0x7FFF) { - php_error_docref(NULL, E_WARNING, "Invalid timeout parameter"); - } else { - last_tpb[tpb_len++] = isc_tpb_lock_timeout; - last_tpb[tpb_len++] = sizeof(ISC_SHORT); - last_tpb[tpb_len] = (ISC_SHORT)trans_timeout; - tpb_len += sizeof(ISC_SHORT); - } } else { php_error_docref(NULL, E_WARNING, "IBASE_LOCK_TIMEOUT expects next argument to be timeout value"); } } } + _php_ibase_populate_trans(trans_argl, trans_timeout, last_tpb, &tpb_len); } } } @@ -1323,7 +1407,20 @@ int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans) /* {{{ */ ib_link->tr_list->trans = tr; } if (tr->handle == 0) { - if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) { + ISC_STATUS result; + zend_long trans_argl = IBG(default_trans_params); + + if(trans_argl == PHP_IBASE_DEFAULT){ + result = isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL); + } else { + zend_long trans_timeout = IBG(default_lock_timeout); + char last_tpb[TPB_MAX_SIZE]; + unsigned short tpb_len = 0; + _php_ibase_populate_trans(trans_argl, trans_timeout, last_tpb, &tpb_len); + result = isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, tpb_len, last_tpb); + } + + if (result) { _php_ibase_error(); return FAILURE; } diff --git a/pdo_firebird_utils.cpp b/pdo_firebird_utils.cpp new file mode 100644 index 0000000..fc1bde5 --- /dev/null +++ b/pdo_firebird_utils.cpp @@ -0,0 +1,81 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Simonov Denis | + +----------------------------------------------------------------------+ +*/ + +#include "pdo_firebird_utils.h" +#include +#include + +/* Returns the client version. 0 bytes are minor version, 1 bytes are major version. */ +extern "C" unsigned fb_get_client_version(void) +{ + Firebird::IMaster* master = Firebird::fb_get_master_interface(); + Firebird::IUtil* util = master->getUtilInterface(); + return util->getClientVersion(); +} + +extern "C" ISC_TIME fb_encode_time(unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions) +{ + Firebird::IMaster* master = Firebird::fb_get_master_interface(); + Firebird::IUtil* util = master->getUtilInterface(); + return util->encodeTime(hours, minutes, seconds, fractions); +} + +extern "C" ISC_DATE fb_encode_date(unsigned year, unsigned month, unsigned day) +{ + Firebird::IMaster* master = Firebird::fb_get_master_interface(); + Firebird::IUtil* util = master->getUtilInterface(); + return util->encodeDate(year, month, day); +} + +#if FB_API_VER >= 40 +static void fb_copy_status(const ISC_STATUS* from, ISC_STATUS* to, size_t maxLength) +{ + for(size_t i=0; i < maxLength; ++i) { + memcpy(to + i, from + i, sizeof(ISC_STATUS)); + if (from[i] == isc_arg_end) { + break; + } + } +} + +/* Decodes a time with time zone into its time components. */ +extern "C" void fb_decode_time_tz(const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer) +{ + Firebird::IMaster* master = Firebird::fb_get_master_interface(); + Firebird::IUtil* util = master->getUtilInterface(); + Firebird::IStatus* status = master->getStatus(); + Firebird::CheckStatusWrapper st(status); + util->decodeTimeTz(&st, timeTz, hours, minutes, seconds, fractions, + timeZoneBufferLength, timeZoneBuffer); +} + +/* Decodes a timestamp with time zone into its date and time components */ +extern "C" void fb_decode_timestamp_tz(const ISC_TIMESTAMP_TZ* timestampTz, + unsigned* year, unsigned* month, unsigned* day, + unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer) +{ + Firebird::IMaster* master = Firebird::fb_get_master_interface(); + Firebird::IUtil* util = master->getUtilInterface(); + Firebird::IStatus* status = master->getStatus(); + Firebird::CheckStatusWrapper st(status); + util->decodeTimeStampTz(&st, timestampTz, year, month, day, + hours, minutes, seconds, fractions, + timeZoneBufferLength, timeZoneBuffer); +} + +#endif diff --git a/pdo_firebird_utils.h b/pdo_firebird_utils.h new file mode 100644 index 0000000..197b279 --- /dev/null +++ b/pdo_firebird_utils.h @@ -0,0 +1,48 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Simonov Denis | + +----------------------------------------------------------------------+ +*/ + +#ifndef PDO_FIREBIRD_UTILS_H +#define PDO_FIREBIRD_UTILS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned fb_get_client_version(void); + +ISC_TIME fb_encode_time(unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions); + +ISC_DATE fb_encode_date(unsigned year, unsigned month, unsigned day); + +#if FB_API_VER >= 40 + +void fb_decode_time_tz(const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer); + +void fb_decode_timestamp_tz(const ISC_TIMESTAMP_TZ* timestampTz, + unsigned* year, unsigned* month, unsigned* day, + unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PDO_FIREBIRD_UTILS_H */ diff --git a/php_ibase_includes.h b/php_ibase_includes.h index b55fee6..f162310 100644 --- a/php_ibase_includes.h +++ b/php_ibase_includes.h @@ -41,7 +41,7 @@ #define IB_STATUS (IBG(status)) #ifdef IBASE_DEBUG -#define IBDEBUG(a) php_printf("::: %s (%d)\n", a, __LINE__); +#define IBDEBUG(a) php_printf("::: %s (%s:%d)\n", a, __FILE__, __LINE__); #endif #ifndef IBDEBUG @@ -69,6 +69,8 @@ ZEND_BEGIN_MODULE_GLOBALS(ibase) zend_long num_links, num_persistent; char errmsg[MAX_ERRMSG]; zend_long sql_code; + zend_long default_trans_params; + zend_long default_lock_timeout; // only used togetger with trans_param IBASE_LOCK_TIMEOUT ZEND_END_MODULE_GLOBALS(ibase) ZEND_EXTERN_MODULE_GLOBALS(ibase) @@ -112,25 +114,25 @@ typedef struct event { } ibase_event; enum php_interbase_option { - PHP_IBASE_DEFAULT = 0, - PHP_IBASE_CREATE = 0, + PHP_IBASE_DEFAULT = 0, + PHP_IBASE_CREATE = 0, /* fetch flags */ - PHP_IBASE_FETCH_BLOBS = 1, - PHP_IBASE_FETCH_ARRAYS = 2, - PHP_IBASE_UNIXTIME = 4, + PHP_IBASE_FETCH_BLOBS = 1, + PHP_IBASE_FETCH_ARRAYS = 2, + PHP_IBASE_UNIXTIME = 4, /* transaction access mode */ - PHP_IBASE_WRITE = 1, - PHP_IBASE_READ = 2, + PHP_IBASE_WRITE = 1, + PHP_IBASE_READ = 2, /* transaction isolation level */ - PHP_IBASE_CONCURRENCY = 4, - PHP_IBASE_COMMITTED = 8, - PHP_IBASE_REC_NO_VERSION = 32, - PHP_IBASE_REC_VERSION = 64, - PHP_IBASE_CONSISTENCY = 16, + PHP_IBASE_CONCURRENCY = 4, + PHP_IBASE_COMMITTED = 8, + PHP_IBASE_REC_NO_VERSION = 32, + PHP_IBASE_REC_VERSION = 64, + PHP_IBASE_CONSISTENCY = 16, /* transaction lock resolution */ - PHP_IBASE_WAIT = 128, - PHP_IBASE_NOWAIT = 256, - PHP_IBASE_LOCK_TIMEOUT = 512, + PHP_IBASE_WAIT = 128, + PHP_IBASE_NOWAIT = 256, + PHP_IBASE_LOCK_TIMEOUT = 512, }; #define IBG(v) ZEND_MODULE_GLOBALS_ACCESSOR(ibase, v) @@ -139,12 +141,11 @@ enum php_interbase_option { ZEND_TSRMLS_CACHE_EXTERN() #endif -#define BLOB_ID_LEN 18 -#define BLOB_ID_MASK "0x%" LL_MASK "x" - -#define BLOB_INPUT 1 -#define BLOB_OUTPUT 2 +#define BLOB_ID_LEN 18 +#define BLOB_ID_MASK "0x%" LL_MASK "x" +#define BLOB_INPUT 1 +#define BLOB_OUTPUT 2 #ifdef PHP_WIN32 // Case switch, because of troubles on Windows and PHP 8.0 @@ -166,11 +167,11 @@ void _php_ibase_module_error(char *, ...) PHP_ATTRIBUTE_FORMAT(printf,1,2); /* determine if a resource is a link or transaction handle */ -#define PHP_IBASE_LINK_TRANS(zv, lh, th) \ +#define PHP_IBASE_LINK_TRANS(zv, lh, th) \ do { \ if (!zv) { \ lh = (ibase_db_link *)zend_fetch_resource2( \ - IBG(default_link), "InterBase link", le_link, le_plink); \ + IBG(default_link), "InterBase link", le_link, le_plink); \ } else { \ _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zv, &lh, &th); \ } \ diff --git a/tests/config.inc b/tests/config.inc index 3cbe601..622d196 100644 --- a/tests/config.inc +++ b/tests/config.inc @@ -2,5 +2,6 @@ $user = 'SYSDBA'; $password = 'masterkey'; +$host = ""; ini_set('ibase.default_user',$user); ini_set('ibase.default_password',$password); diff --git a/tests/ibase_drop_db_001.phpt b/tests/ibase_drop_db_001.phpt index bdad766..64efeae 100644 --- a/tests/ibase_drop_db_001.phpt +++ b/tests/ibase_drop_db_001.phpt @@ -8,7 +8,7 @@ ibase_drop_db(): Basic test require("config.inc"); unlink($file = tempnam('/tmp',"php_ibase_test")); - +if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, sprintf("CREATE SCHEMA '%s' USER '%s' PASSWORD '%s' DEFAULT CHARACTER SET %s",$file, diff --git a/tests/ibase_drop_db_003.phpt b/tests/ibase_drop_db_003.phpt index a2f2d38..1269412 100644 --- a/tests/ibase_drop_db_003.phpt +++ b/tests/ibase_drop_db_003.phpt @@ -11,6 +11,7 @@ include("skipif-php7-or-older.inc"); require("config.inc"); unlink($file = tempnam('/tmp',"php_ibase_test")); +if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, sprintf("CREATE SCHEMA '%s' USER '%s' PASSWORD '%s' DEFAULT CHARACTER SET %s",$file, diff --git a/tests/ibase_drop_db_004.phpt b/tests/ibase_drop_db_004.phpt index adc4923..b91202f 100644 --- a/tests/ibase_drop_db_004.phpt +++ b/tests/ibase_drop_db_004.phpt @@ -11,6 +11,7 @@ include("skipif-php7-or-older.inc"); require("config.inc"); unlink($file = tempnam('/tmp',"php_ibase_test")); +if(!empty($host))$file = "$host:$file"; $db = ibase_query(IBASE_CREATE, sprintf("CREATE SCHEMA '%s' USER '%s' PASSWORD '%s' DEFAULT CHARACTER SET %s",$file, diff --git a/tests/ibase_num_params_004.phpt b/tests/ibase_num_params_004.phpt index daaf849..83f8db4 100644 --- a/tests/ibase_num_params_004.phpt +++ b/tests/ibase_num_params_004.phpt @@ -24,4 +24,4 @@ int(2) Warning: ibase_prepare(): Dynamic SQL Error SQL error code = -%d Column unknown X At line %d, column %d %s -Fatal error: Uncaught TypeError: ibase_num_params(): Argument #1 ($query) must be of type resource, bool given in %a \ No newline at end of file +Fatal error: Uncaught TypeError: ibase_num_params(): Argument #1 ($query) must be of type resource, %a \ No newline at end of file diff --git a/tests/interbase.inc b/tests/interbase.inc index 9b47417..254dab9 100644 --- a/tests/interbase.inc +++ b/tests/interbase.inc @@ -5,6 +5,7 @@ require('functions.inc'); /* we need just the generated name, not the file itself */ unlink($test_base = tempnam(sys_get_temp_dir(),"php_ibase_test")); +if(!empty($host))$test_base = "$host:$test_base"; function init_db() { @@ -31,5 +32,3 @@ function cleanup_db() register_shutdown_function('cleanup_db'); init_db(); - -?> diff --git a/win_build_scripts/README.md b/win_build_scripts/README.md index 5253401..807d158 100644 --- a/win_build_scripts/README.md +++ b/win_build_scripts/README.md @@ -12,7 +12,7 @@ Make sure you got ~20GB free disk space to build for all PHP versions. Make sure ``git`` is in you PATH -1. Set up Microsoft Visual Studio vc15 and vs16. +1. Set up Microsoft Visual Studio vc15, vs16 and vs17 (for PHP8.4+). 2. Set up Firebird 32-bit and 64-bit installations or libraries. 3. Set up PHP-SDK according to https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 4. Clone php-firebird extension source somewhere. diff --git a/win_build_scripts/php-fb-build-all.bat b/win_build_scripts/php-fb-build-all.bat index b84b8e5..c805f23 100644 --- a/win_build_scripts/php-fb-build-all.bat +++ b/win_build_scripts/php-fb-build-all.bat @@ -6,4 +6,5 @@ call php-fb-build.bat 8.0 vs16 || exit /B %ERRORLEVEL% call php-fb-build.bat 8.1 vs16 || exit /B %ERRORLEVEL% call php-fb-build.bat 8.2 vs16 || exit /B %ERRORLEVEL% call php-fb-build.bat 8.3 vs16 || exit /B %ERRORLEVEL% -call php-fb-build.bat master vs16 || exit /B %ERRORLEVEL% +call php-fb-build.bat 8.4 vs17 || exit /B %ERRORLEVEL% +call php-fb-build.bat master vs17 || exit /B %ERRORLEVEL% diff --git a/win_build_scripts/php-fb-build.bat b/win_build_scripts/php-fb-build.bat index 41ac12c..accc387 100644 --- a/win_build_scripts/php-fb-build.bat +++ b/win_build_scripts/php-fb-build.bat @@ -57,10 +57,15 @@ set pfb_build_root=php%pfb_php_vers%\%pfb_cpp_vers%\ @REM check if ibase_connect() function exists in newly compiled extension set check_code="if(!function_exists('ibase_connect'))exit(1);" + +set TPATH=%PATH% +set PATH=%FB64_DIR%;%TPATH% "%pfb_build_root%x64\php-src\x64\Release_TS\php.exe" -dextension=.\php_interbase.dll -r %check_code% || goto :error "%pfb_build_root%x64\php-src\x64\Release\php.exe" -dextension=.\php_interbase.dll -r %check_code% || goto :error +set PATH=%FB32_DIR%;%TPATH% "%pfb_build_root%x86\php-src\Release_TS\php.exe" -dextension=.\php_interbase.dll -r %check_code% || goto :error "%pfb_build_root%x86\php-src\Release\php.exe" -dextension=.\php_interbase.dll -r %check_code% || goto :error +set PATH=%TPATH% call :log "PHP %pfb_php_vers% build OK" diff --git a/win_build_scripts/php-fb-config.bat b/win_build_scripts/php-fb-config.bat index 0c8dd70..c194371 100644 --- a/win_build_scripts/php-fb-config.bat +++ b/win_build_scripts/php-fb-config.bat @@ -2,15 +2,17 @@ @REM git command must be in PATH @REM +@REM php-firebird source directory +set PFB_SOURCE_DIR=D:\php-firebird\ + +for /f %%i in ('git -C %PFB_SOURCE_DIR%\php-firebird\ rev-parse --short HEAD') do set GIT_HASH=%%i + @REM sets php-firebird version part in extension file, for example, php_interbase-<<3.0.1-ba8e63b>>-7.3-vc15.dll -set PFB_VERS=3.0.1-ba8e63b +set PFB_VERS=3.0.1-%GIT_HASH% @REM Directory where all compiled files will be copied set PFB_OUTPUT_DIR=D:\php-firebird\releases\ @REM FB 32-bit and 64-bit libraries -set PFB_FB32_DIR=C:\Program Files\Firebird\Firebird_3_0-x86\ -set PFB_FB64_DIR=C:\Program Files\Firebird\Firebird_3_0\ - -@REM php-firebird source directory -set PFB_SOURCE_DIR=D:\php-firebird\ba8e63b\ +set FB32_DIR=C:\Program Files\Firebird\Firebird_5_0-x86 +set FB64_DIR=C:\Program Files\Firebird\Firebird_5_0 diff --git a/win_build_scripts/php-fb-sdk-build.bat b/win_build_scripts/php-fb-sdk-build.bat index 6b4c1ef..61c2b73 100644 --- a/win_build_scripts/php-fb-sdk-build.bat +++ b/win_build_scripts/php-fb-sdk-build.bat @@ -3,13 +3,13 @@ @REM Must be called under phpsdk--.bat @REM @REM Calling script should set variables: -@REM [pfb_nts] [pfb_x86] +@REM [pfb_nts] [pfb_x86] @REM @REM set pfb_php_vers=7.4 @REM set pfb_nts=1 if nts expected, 0 if ts @REM set pfb_x86=1 if linking to x86 fbclient, o if x64 @REM -@REM all set in php-fb-config.bat +@REM all set in php-fb-config.bat @REM goto :MAIN @@ -41,10 +41,10 @@ exit /B ) if "%pfb_x86%" gtr "0" ( - set with_interbase="shared,%PFB_FB32_DIR%lib;%PFB_FB32_DIR%include" + set with_interbase="shared,%FB32_DIR%" set build_msg=%build_msg% x86 ) else ( - set with_interbase="shared,%PFB_FB64_DIR%lib;%PFB_FB64_DIR%include" + set with_interbase="shared,%FB64_DIR%" set build_msg=%build_msg% x86_64 )