From d8c5de8d23474655198cb5758e6d0f284ad20e35 Mon Sep 17 00:00:00 2001 From: Simonov Denis Date: Sun, 4 Aug 2024 19:24:19 +0300 Subject: [PATCH 1/5] Formatting time zone types. --- ext/pdo_firebird/firebird_driver.c | 63 ++++++-- ext/pdo_firebird/firebird_statement.c | 141 ++++++++++++++++++ ext/pdo_firebird/php_pdo_firebird_int.h | 138 +++++++++++++++++ ext/pdo_firebird/tests/fb4_datatypes.phpt | 5 +- .../tests/fb4_datatypes_params.phpt | 4 +- 5 files changed, 334 insertions(+), 17 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index ddb7db9b15b2b..eab86559eb54b 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -462,14 +462,13 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa #if FB_API_VER >= 40 /* set coercing a data type */ -static void set_coercing_data_type(XSQLDA* sqlda) +static void set_coercing_input_data_types(XSQLDA* sqlda) { /* Data types introduced in Firebird 4.0 are difficult to process using the Firebird Legacy API. */ /* These data types include DECFLOAT(16), DECFLOAT(34), INT128 (NUMERIC/DECIMAL(38, x)), */ - /* TIMESTAMP WITH TIME ZONE, and TIME WITH TIME ZONE. In any case, at least the first three data types */ - /* can only be mapped to strings. The last two too, but for them it is potentially possible to set */ - /* the display format, as is done for TIMESTAMP. This function allows you to ensure minimal performance */ - /* of queries if they contain columns and parameters of the above types. */ + /* TIMESTAMP WITH TIME ZONE, and TIME WITH TIME ZONE. */ + /* This function allows you to ensure minimal performance */ + /* of queries if they contain parameters of the above types. */ unsigned int i; short dtype; short nullable; @@ -485,7 +484,7 @@ static void set_coercing_data_type(XSQLDA* sqlda) break; case SQL_DEC16: - var->sqltype = SQL_VARYING + nullable; + var->sqltype = SQL_VARYING + nullable; var->sqllen = 24; break; @@ -503,8 +502,45 @@ static void set_coercing_data_type(XSQLDA* sqlda) var->sqltype = SQL_VARYING + nullable; var->sqllen = 46; break; + + default: + break; + } + } +} + +static void set_coercing_output_data_types(XSQLDA* sqlda) +{ + /* Data types introduced in Firebird 4.0 are difficult to process using the Firebird Legacy API. */ + /* These data types include DECFLOAT(16), DECFLOAT(34), INT128 (NUMERIC/DECIMAL(38, x)). */ + /* In any case, at this data types can only be mapped to strings. */ + /* This function allows you to ensure minimal performance of queries if they contain columns of the above types. */ + unsigned int i; + short dtype; + short nullable; + XSQLVAR* var; + for (i=0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++) { + dtype = (var->sqltype & ~1); /* drop flag bit */ + nullable = (var->sqltype & 1); + switch(dtype) { + case SQL_INT128: + var->sqltype = SQL_VARYING + nullable; + var->sqllen = 46; + var->sqlscale = 0; + break; + + case SQL_DEC16: + var->sqltype = SQL_VARYING + nullable; + var->sqllen = 24; + break; + + case SQL_DEC34: + var->sqltype = SQL_VARYING + nullable; + var->sqllen = 43; + break; + default: - break; + break; } } } @@ -657,7 +693,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */ #if FB_API_VER >= 40 /* set coercing a data type */ - set_coercing_data_type(&S->out_sqlda); + set_coercing_output_data_types(&S->out_sqlda); #endif /* allocate the input descriptors */ @@ -676,7 +712,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */ #if FB_API_VER >= 40 /* set coercing a data type */ - set_coercing_data_type(S->in_sqlda); + set_coercing_input_data_types(S->in_sqlda); #endif } @@ -1245,22 +1281,23 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) ZVAL_STRING(val, tmp); return 1; } - return -1; + /* TODO Check this is correct? */ + ZEND_FALLTHROUGH; case PDO_ATTR_FETCH_TABLE_NAMES: ZVAL_BOOL(val, H->fetch_table_names); return 1; case PDO_FB_ATTR_DATE_FORMAT: - ZVAL_STRING(val, H->date_format ? H->date_format : PDO_FB_DEF_DATE_FMT); + ZVAL_STRING(val, H->date_format); return 1; case PDO_FB_ATTR_TIME_FORMAT: - ZVAL_STRING(val, H->time_format ? H->time_format : PDO_FB_DEF_TIME_FMT); + ZVAL_STRING(val, H->time_format); return 1; case PDO_FB_ATTR_TIMESTAMP_FORMAT: - ZVAL_STRING(val, H->timestamp_format ? H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT); + ZVAL_STRING(val, H->timestamp_format); return 1; case PDO_FB_TRANSACTION_ISOLATION_LEVEL: diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 7cc3236563ce7..5fd2577e640de 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -59,11 +59,142 @@ static zend_always_inline ISC_TIMESTAMP php_get_isc_timestamp_from_sqldata(const READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP, sqldata); } +static zend_always_inline ISC_TIME_TZ php_get_isc_time_tz_from_sqldata(const ISC_SCHAR *sqldata) +{ + READ_AND_RETURN_USING_MEMCPY(ISC_TIME_TZ, sqldata); +} + +static zend_always_inline ISC_TIMESTAMP_TZ php_get_isc_timestamp_tz_from_sqldata(const ISC_SCHAR *sqldata) +{ + READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP_TZ, sqldata); +} + static zend_always_inline ISC_QUAD php_get_isc_quad_from_sqldata(const ISC_SCHAR *sqldata) { READ_AND_RETURN_USING_MEMCPY(ISC_QUAD, sqldata); } +#if FB_API_VER >= 40 + +static void fb_copyStatus(struct fb_Status* status, ISC_STATUS* to, size_t maxLength) +{ + const ISC_STATUS* from = (const ISC_STATUS*)status->vtable->getErrors(status); + for(size_t i=0; i < maxLength; ++i) { + memcpy(to + i, from + i, sizeof(ISC_STATUS)); + if (from[i] == isc_arg_end) { + break; + } + } +} + +static ISC_TIME fb_encode_time(unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions) +{ + struct fb_Master* master = fb_get_master_interface(); + struct fb_Util* util = master->vtable->getUtilInterface(master); + return util->vtable->encodeTime(util, hours, minutes, seconds, fractions); +} + +static ISC_DATE fb_encode_date(unsigned year, unsigned month, unsigned day) +{ + struct fb_Master* master = fb_get_master_interface(); + struct fb_Util* util = master->vtable->getUtilInterface(master); + return util->vtable->encodeDate(util, year, month, day); +} + +static ISC_STATUS fb_decode_time_tz(ISC_STATUS* isc_status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer) +{ + struct fb_Master* master = fb_get_master_interface(); + struct fb_Status* status = master->vtable->getStatus(master); + struct fb_Util* util = master->vtable->getUtilInterface(master); + util->vtable->decodeTimeTz(util, status, timeTz, hours, minutes, seconds, fractions, + timeZoneBufferLength, timeZoneBuffer); + if (status->vtable->getState(status)) { + fb_copyStatus(status, isc_status, 20); + } + status->vtable->dispose(status); + return isc_status[1]; +} + + +static ISC_STATUS fb_decode_timestamp_tz(ISC_STATUS* isc_status, const ISC_TIMESTAMP_TZ* timestampTz, + unsigned* year, unsigned* month, unsigned* day, + unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer) +{ + struct fb_Master* master = fb_get_master_interface(); + struct fb_Status* status = master->vtable->getStatus(master); + struct fb_Util* util = master->vtable->getUtilInterface(master); + util->vtable->decodeTimeStampTz(util, status, timestampTz, year, month, day, + hours, minutes, seconds, fractions, + timeZoneBufferLength, timeZoneBuffer); + if (status->vtable->getState(status)) { + fb_copyStatus(status, isc_status, 20); + } + status->vtable->dispose(status); + return isc_status[1]; +} + +/* fetch formatted time with time zone */ +static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zval *result) +{ + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + unsigned hours = 0, minutes = 0, seconds = 0, fractions = 0; + char timeZoneBuffer[40] = {0}; + char *fmt; + struct tm t; + ISC_TIME time; + char timeBuf[80] = {0}; + char timeTzBuf[124] = {0}; + if (fb_decode_time_tz(S->H->isc_status, timeTz, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { + return 1; + } + time = fb_encode_time(hours, minutes, seconds, fractions); + isc_decode_sql_time(&time, &t); + fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT; + + size_t len = strftime(timeBuf, sizeof(timeBuf), fmt, &t); + if (len == 0) { + return 1; + } + + size_t time_tz_len = sprintf(timeTzBuf, "%s %s", timeBuf, timeZoneBuffer); + ZVAL_STRINGL(result, timeTzBuf, time_tz_len); + return 0; +} + +/* fetch formatted timestamp with time zone */ +static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* timestampTz, zval *result) +{ + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + unsigned year, month, day, hours, minutes, seconds, fractions; + char timeZoneBuffer[40] = {0}; + char *fmt; + struct tm t; + ISC_TIMESTAMP ts; + char timestampBuf[80] = {0}; + char timestampTzBuf[124] = {0}; + if (fb_decode_timestamp_tz(S->H->isc_status, timestampTz, &year, &month, &day, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { + return 1; + } + ts.timestamp_date = fb_encode_date(year, month, day); + ts.timestamp_time = fb_encode_time(hours, minutes, seconds, fractions); + isc_decode_timestamp(&ts, &t); + + fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT; + + size_t len = strftime(timestampBuf, sizeof(timestampBuf), fmt, &t); + if (len == 0) { + return 1; + } + + size_t timestamp_tz_len = sprintf(timestampTzBuf, "%s %s", timestampBuf, timeZoneBuffer); + ZVAL_STRINGL(result, timestampTzBuf, timestamp_tz_len); + return 0; +} + +#endif + /* free the allocated space for passing field values to the db and back */ static void php_firebird_free_sqlda(XSQLDA const *sqlda) /* {{{ */ { @@ -494,6 +625,16 @@ static int pdo_firebird_stmt_get_col( size_t len = strftime(buf, sizeof(buf), fmt, &t); ZVAL_STRINGL(result, buf, len); break; +#if FB_API_VER >= 40 + case SQL_TIME_TZ: { + ISC_TIME_TZ time = php_get_isc_time_tz_from_sqldata(var->sqldata); + return get_formatted_time_tz(stmt, &time, result); + } + case SQL_TIMESTAMP_TZ: { + ISC_TIMESTAMP_TZ ts = php_get_isc_timestamp_tz_from_sqldata(var->sqldata); + return get_formatted_timestamp_tz(stmt, &ts, result); + } +#endif case SQL_BLOB: { ISC_QUAD quad = php_get_isc_quad_from_sqldata(var->sqldata); return php_firebird_fetch_blob(stmt, colno, result, &quad); diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index dc1e4bb7f4086..a105a7b953ebd 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -19,6 +19,144 @@ #include +#if FB_API_VER >= 40 + +#ifndef CLOOP_EXTERN_C +#ifdef __cplusplus +#define CLOOP_EXTERN_C extern "C" +#else +#define CLOOP_EXTERN_C +#endif +#endif + +struct fb_Status; +struct fb_Master; +struct fb_Util; + +CLOOP_EXTERN_C struct fb_Master* ISC_EXPORT fb_get_master_interface(void); + +#define fb_Status_VERSION 3 + +#define fb_Status_STATE_WARNINGS ((unsigned) (0x1)) +#define fb_Status_STATE_ERRORS ((unsigned) (0x2)) +#define fb_Status_RESULT_ERROR ((int) (-1)) +#define fb_Status_RESULT_OK ((int) (0)) +#define fb_Status_RESULT_NO_DATA ((int) (1)) +#define fb_Status_RESULT_SEGMENT ((int) (2)) + +struct fb_StatusVTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct fb_Status* self); + void (*init)(struct fb_Status* self); + unsigned (*getState)(const struct fb_Status* self); + void (*setErrors2)(struct fb_Status* self, unsigned length, const intptr_t* value); + void (*setWarnings2)(struct fb_Status* self, unsigned length, const intptr_t* value); + void (*setErrors)(struct fb_Status* self, const intptr_t* value); + void (*setWarnings)(struct fb_Status* self, const intptr_t* value); + const intptr_t* (*getErrors)(const struct fb_Status* self); + const intptr_t* (*getWarnings)(const struct fb_Status* self); + struct fb_Status* (*clone)(const struct fb_Status* self); +}; + +struct fb_Status +{ + void* cloopDummy[1]; + struct fb_StatusVTable* vtable; +}; + +#define fb_Master_VERSION 2 + +struct fb_MasterVTable +{ + void* cloopDummy[1]; + uintptr_t version; + struct fb_Status* (*getStatus)(struct fb_Master* self); + /* stubs */ + void* getDispatcher; + void* getPluginManager; + void* getTimerControl; + void* getDtc; + void* registerAttachment; + void* registerTransaction; + void* getMetadataBuilder; + /* + struct fb_Status* (*getStatus)(struct fb_Master* self); + struct fb_Provider* (*getDispatcher)(struct fb_Master* self); + struct fb_PluginManager* (*getPluginManager)(struct fb_Master* self); + struct fb_TimerControl* (*getTimerControl)(struct fb_Master* self); + struct fb_Dtc* (*getDtc)(struct fb_Master* self); + struct fb_Attachment* (*registerAttachment)(struct fb_Master* self, struct fb_Provider* provider, struct fb_Attachment* attachment); + struct fb_Transaction* (*registerTransaction)(struct fb_Master* self, struct fb_Attachment* attachment, struct fb_Transaction* transaction); + struct fb_MetadataBuilder* (*getMetadataBuilder)(struct fb_Master* self, struct fb_Status* status, unsigned fieldCount); + */ + int (*serverMode)(struct fb_Master* self, int mode); + struct fb_Util* (*getUtilInterface)(struct fb_Master* self); + void* getConfigManager; + /* struct fb_ConfigManager* (*getConfigManager)(struct fb_Master* self); */ + FB_BOOLEAN (*getProcessExiting)(struct fb_Master* self); +}; + +struct fb_Master +{ + void* cloopDummy[1]; + struct fb_MasterVTable* vtable; +}; + +#define fb_Util_VERSION 4 + +struct fb_UtilVTable +{ + void* cloopDummy[1]; + uintptr_t version; + /* stubs */ + void* getFbVersion; + void* loadBlob; + void* dumpBlob; + void* getPerfCounters; + void* executeCreateDatabase; + /* + void (*getFbVersion)(struct fb_Util* self, struct fb_Status* status, struct fb_Attachment* att, struct fb_VersionCallback* callback); + void (*loadBlob)(struct fb_Util* self, struct fb_Status* status, ISC_QUAD* blobId, struct fb_Attachment* att, struct fb_Transaction* tra, const char* file, FB_BOOLEAN txt); + void (*dumpBlob)(struct fb_Util* self, struct fb_Status* status, ISC_QUAD* blobId, struct fb_Attachment* att, struct fb_Transaction* tra, const char* file, FB_BOOLEAN txt); + void (*getPerfCounters)(struct fb_Util* self, struct fb_Status* status, struct fb_Attachment* att, const char* countersSet, ISC_INT64* counters); + struct fb_Attachment* (*executeCreateDatabase)(struct fb_Util* self, struct fb_Status* status, unsigned stmtLength, const char* creatDBstatement, unsigned dialect, FB_BOOLEAN* stmtIsCreateDb); + */ + void (*decodeDate)(struct fb_Util* self, ISC_DATE date, unsigned* year, unsigned* month, unsigned* day); + void (*decodeTime)(struct fb_Util* self, ISC_TIME time, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions); + ISC_DATE (*encodeDate)(struct fb_Util* self, unsigned year, unsigned month, unsigned day); + ISC_TIME (*encodeTime)(struct fb_Util* self, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions); + unsigned (*formatStatus)(struct fb_Util* self, char* buffer, unsigned bufferSize, struct fb_Status* status); + unsigned (*getClientVersion)(struct fb_Util* self); + /* + struct fb_XpbBuilder* (*getXpbBuilder)(struct fb_Util* self, struct fb_Status* status, unsigned kind, const unsigned char* buf, unsigned len); + unsigned (*setOffsets)(struct fb_Util* self, struct fb_Status* status, struct fb_MessageMetadata* metadata, struct fb_OffsetsCallback* callback); + struct fb_DecFloat16* (*getDecFloat16)(struct fb_Util* self, struct fb_Status* status); + struct fb_DecFloat34* (*getDecFloat34)(struct fb_Util* self, struct fb_Status* status); + */ + void* getXpbBuilder; + void* setOffsets; + void* getDecFloat16; + void* getDecFloat34; + void (*decodeTimeTz)(struct fb_Util* self, struct fb_Status* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); + void (*decodeTimeStampTz)(struct fb_Util* self, struct fb_Status* status, const ISC_TIMESTAMP_TZ* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); + void (*encodeTimeTz)(struct fb_Util* self, struct fb_Status* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone); + void (*encodeTimeStampTz)(struct fb_Util* self, struct fb_Status* status, ISC_TIMESTAMP_TZ* timeStampTz, unsigned year, unsigned month, unsigned day, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone); + /* struct fb_Int128* (*getInt128)(struct fb_Util* self, struct fb_Status* status); */ + void* getInt128; + void (*decodeTimeTzEx)(struct fb_Util* self, struct fb_Status* status, const ISC_TIME_TZ_EX* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); + void (*decodeTimeStampTzEx)(struct fb_Util* self, struct fb_Status* status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); +}; + +struct fb_Util +{ + void* cloopDummy[1]; + struct fb_UtilVTable* vtable; +}; + +#endif + #ifdef SQLDA_VERSION #define PDO_FB_SQLDA_VERSION SQLDA_VERSION #else diff --git a/ext/pdo_firebird/tests/fb4_datatypes.phpt b/ext/pdo_firebird/tests/fb4_datatypes.phpt index 3ae452d5eb4e4..cac77e85fdbcc 100644 --- a/ext/pdo_firebird/tests/fb4_datatypes.phpt +++ b/ext/pdo_firebird/tests/fb4_datatypes.phpt @@ -31,6 +31,7 @@ $sql = <<<'SQL' SQL; $dbh = getDbConnection(); +$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare($sql); $stmt->execute(); @@ -47,9 +48,9 @@ echo "\ndone\n"; "N": "123.97", "N2": "123.97", "TS": "2024-05-04 12:59:34", - "TS_TZ": "%s 12:59:34.2390 Europe\/Moscow", + "TS_TZ": "2024-05-04 12:59:34 Europe\/Moscow", "T": "12:59:34", - "T_TZ": "12:59:34.2390 Europe\/Moscow", + "T_TZ": "12:59:34 Europe\/Moscow", "DF16": "1.128", "DF34": "1.128" } diff --git a/ext/pdo_firebird/tests/fb4_datatypes_params.phpt b/ext/pdo_firebird/tests/fb4_datatypes_params.phpt index f1b4827b9e724..adf049560d3ac 100644 --- a/ext/pdo_firebird/tests/fb4_datatypes_params.phpt +++ b/ext/pdo_firebird/tests/fb4_datatypes_params.phpt @@ -42,8 +42,8 @@ echo "\ndone\n"; "I128": "12", "N1": "12.34", "N2": "12.34", - "TS_TZ": "%s 12:59:34.2390 Europe\/Moscow", - "T_TZ": "12:59:00.0000 Europe\/Moscow", + "TS_TZ": "2024-05-04 12:59:34 Europe\/Moscow", + "T_TZ": "12:59:00 Europe\/Moscow", "DF16": "12.34", "DF34": "12.34" } From 731460d2c8cd21363af7115ab9e93f2414368664 Mon Sep 17 00:00:00 2001 From: Simonov Denis Date: Sun, 4 Aug 2024 19:47:31 +0300 Subject: [PATCH 2/5] correction --- ext/pdo_firebird/firebird_driver.c | 6 +++--- ext/pdo_firebird/tests/fb4_datatypes.phpt | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index eab86559eb54b..afb8f8298c7d2 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -1289,15 +1289,15 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) return 1; case PDO_FB_ATTR_DATE_FORMAT: - ZVAL_STRING(val, H->date_format); + ZVAL_STRING(val, H->date_format ? H->date_format : PDO_FB_DEF_DATE_FMT); return 1; case PDO_FB_ATTR_TIME_FORMAT: - ZVAL_STRING(val, H->time_format); + ZVAL_STRING(val, H->time_format ? H->time_format : PDO_FB_DEF_TIME_FMT); return 1; case PDO_FB_ATTR_TIMESTAMP_FORMAT: - ZVAL_STRING(val, H->timestamp_format); + ZVAL_STRING(val, H->timestamp_format ? H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT); return 1; case PDO_FB_TRANSACTION_ISOLATION_LEVEL: diff --git a/ext/pdo_firebird/tests/fb4_datatypes.phpt b/ext/pdo_firebird/tests/fb4_datatypes.phpt index cac77e85fdbcc..02bde1e7b2c25 100644 --- a/ext/pdo_firebird/tests/fb4_datatypes.phpt +++ b/ext/pdo_firebird/tests/fb4_datatypes.phpt @@ -31,7 +31,6 @@ $sql = <<<'SQL' SQL; $dbh = getDbConnection(); -$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare($sql); $stmt->execute(); From f88e9954f69d919f8fca84af08d9c723372cc380 Mon Sep 17 00:00:00 2001 From: Simonov Denis Date: Sun, 4 Aug 2024 20:16:32 +0300 Subject: [PATCH 3/5] Fixed build when FB_API_VER < 40 --- ext/pdo_firebird/firebird_statement.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 5fd2577e640de..36154acb33fc1 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -59,6 +59,13 @@ static zend_always_inline ISC_TIMESTAMP php_get_isc_timestamp_from_sqldata(const READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP, sqldata); } +static zend_always_inline ISC_QUAD php_get_isc_quad_from_sqldata(const ISC_SCHAR *sqldata) +{ + READ_AND_RETURN_USING_MEMCPY(ISC_QUAD, sqldata); +} + +#if FB_API_VER >= 40 + static zend_always_inline ISC_TIME_TZ php_get_isc_time_tz_from_sqldata(const ISC_SCHAR *sqldata) { READ_AND_RETURN_USING_MEMCPY(ISC_TIME_TZ, sqldata); @@ -69,13 +76,6 @@ static zend_always_inline ISC_TIMESTAMP_TZ php_get_isc_timestamp_tz_from_sqldata READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP_TZ, sqldata); } -static zend_always_inline ISC_QUAD php_get_isc_quad_from_sqldata(const ISC_SCHAR *sqldata) -{ - READ_AND_RETURN_USING_MEMCPY(ISC_QUAD, sqldata); -} - -#if FB_API_VER >= 40 - static void fb_copyStatus(struct fb_Status* status, ISC_STATUS* to, size_t maxLength) { const ISC_STATUS* from = (const ISC_STATUS*)status->vtable->getErrors(status); From a719b11e4cc5996c2b881cb54035b5cbaf49dac0 Mon Sep 17 00:00:00 2001 From: Simonov Denis Date: Sat, 10 Aug 2024 17:51:21 +0300 Subject: [PATCH 4/5] use C++ OO API --- ext/pdo_firebird/config.m4 | 17 ++- ext/pdo_firebird/config.w32 | 2 +- ext/pdo_firebird/firebird_driver.c | 21 ++++ ext/pdo_firebird/firebird_statement.c | 60 +---------- ext/pdo_firebird/pdo_firebird_utils.cpp | 92 ++++++++++++++++ ext/pdo_firebird/pdo_firebird_utils.h | 48 +++++++++ ext/pdo_firebird/php_pdo_firebird_int.h | 138 ------------------------ 7 files changed, 179 insertions(+), 199 deletions(-) create mode 100644 ext/pdo_firebird/pdo_firebird_utils.cpp create mode 100644 ext/pdo_firebird/pdo_firebird_utils.h diff --git a/ext/pdo_firebird/config.m4 b/ext/pdo_firebird/config.m4 index bb34df0bec23b..f80c28ba87a12 100644 --- a/ext/pdo_firebird/config.m4 +++ b/ext/pdo_firebird/config.m4 @@ -50,9 +50,24 @@ if test "$PHP_PDO_FIREBIRD" != "no"; then PHP_CHECK_PDO_INCLUDES + + PHP_PDO_FIREBIRD_COMMON_FLAGS="" PHP_NEW_EXTENSION([pdo_firebird], [pdo_firebird.c firebird_driver.c firebird_statement.c], - [$ext_shared]) + [$ext_shared],, + [$PHP_PDO_FIREBIRD_COMMON_FLAGS], + [cxx]) PHP_SUBST([PDO_FIREBIRD_SHARED_LIBADD]) PHP_ADD_EXTENSION_DEP(pdo_firebird, pdo) + + PHP_PDO_FIREBIRD_CXX_SOURCES="pdo_firebird_utils.cpp" + + PHP_REQUIRE_CXX() + PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_PDO_FIREBIRD_STDCXX) + PHP_PDO_FIREBIRD_CXX_FLAGS="$PHP_PDO_FIREBIRD_COMMON_FLAGS $PHP_PDO_FIREBIRD_STDCXX" + + PHP_ADD_SOURCES([$ext_dir], + [$PHP_PDO_FIREBIRD_CXX_SOURCES], + [$PHP_PDO_FIREBIRD_CXX_FLAGS]) + fi diff --git a/ext/pdo_firebird/config.w32 b/ext/pdo_firebird/config.w32 index 634ac4c8e984c..9a8197c2655d0 100644 --- a/ext/pdo_firebird/config.w32 +++ b/ext/pdo_firebird/config.w32 @@ -10,7 +10,7 @@ if (PHP_PDO_FIREBIRD != "no") { PHP_PHP_BUILD + "\\include\\interbase;" + PHP_PHP_BUILD + "\\interbase\\include;" + PHP_PDO_FIREBIRD) ) { - EXTENSION("pdo_firebird", "pdo_firebird.c firebird_driver.c firebird_statement.c"); + EXTENSION("pdo_firebird", "pdo_firebird.c firebird_driver.c firebird_statement.c pdo_firebird_utils.cpp"); } else { WARNING("pdo_firebird not enabled; libraries and headers not found"); } diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index afb8f8298c7d2..a044cd6400519 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -30,6 +30,7 @@ #include "ext/pdo/php_pdo_driver.h" #include "php_pdo_firebird.h" #include "php_pdo_firebird_int.h" +#include "pdo_firebird_utils.h" static int php_firebird_alloc_prepare_stmt(pdo_dbh_t*, const zend_string*, XSQLDA*, isc_stmt_handle*, HashTable*); @@ -519,6 +520,8 @@ static void set_coercing_output_data_types(XSQLDA* sqlda) short dtype; short nullable; XSQLVAR* var; + unsigned fb_client_version = fb_get_client_version(); + unsigned fb_client_major_version = (fb_client_version >> 8) & 0xFF; for (i=0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++) { dtype = (var->sqltype & ~1); /* drop flag bit */ nullable = (var->sqltype & 1); @@ -539,6 +542,24 @@ static void set_coercing_output_data_types(XSQLDA* sqlda) var->sqllen = 43; break; + case SQL_TIMESTAMP_TZ: + if (fb_client_major_version < 4) { + /* If the client version is below 4.0, then it is impossible to handle time zones natively, */ + /* so we convert these types to a string. */ + var->sqltype = SQL_VARYING + nullable; + var->sqllen = 58; + } + break; + + case SQL_TIME_TZ: + if (fb_client_major_version < 4) { + /* If the client version is below 4.0, then it is impossible to handle time zones natively, */ + /* so we convert these types to a string. */ + var->sqltype = SQL_VARYING + nullable; + var->sqllen = 46; + } + break; + default: break; } diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 36154acb33fc1..b2a2a34322df2 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -25,6 +25,7 @@ #include "ext/pdo/php_pdo_driver.h" #include "php_pdo_firebird.h" #include "php_pdo_firebird_int.h" +#include "pdo_firebird_utils.h" #include @@ -76,65 +77,6 @@ static zend_always_inline ISC_TIMESTAMP_TZ php_get_isc_timestamp_tz_from_sqldata READ_AND_RETURN_USING_MEMCPY(ISC_TIMESTAMP_TZ, sqldata); } -static void fb_copyStatus(struct fb_Status* status, ISC_STATUS* to, size_t maxLength) -{ - const ISC_STATUS* from = (const ISC_STATUS*)status->vtable->getErrors(status); - for(size_t i=0; i < maxLength; ++i) { - memcpy(to + i, from + i, sizeof(ISC_STATUS)); - if (from[i] == isc_arg_end) { - break; - } - } -} - -static ISC_TIME fb_encode_time(unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions) -{ - struct fb_Master* master = fb_get_master_interface(); - struct fb_Util* util = master->vtable->getUtilInterface(master); - return util->vtable->encodeTime(util, hours, minutes, seconds, fractions); -} - -static ISC_DATE fb_encode_date(unsigned year, unsigned month, unsigned day) -{ - struct fb_Master* master = fb_get_master_interface(); - struct fb_Util* util = master->vtable->getUtilInterface(master); - return util->vtable->encodeDate(util, year, month, day); -} - -static ISC_STATUS fb_decode_time_tz(ISC_STATUS* isc_status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, - unsigned timeZoneBufferLength, char* timeZoneBuffer) -{ - struct fb_Master* master = fb_get_master_interface(); - struct fb_Status* status = master->vtable->getStatus(master); - struct fb_Util* util = master->vtable->getUtilInterface(master); - util->vtable->decodeTimeTz(util, status, timeTz, hours, minutes, seconds, fractions, - timeZoneBufferLength, timeZoneBuffer); - if (status->vtable->getState(status)) { - fb_copyStatus(status, isc_status, 20); - } - status->vtable->dispose(status); - return isc_status[1]; -} - - -static ISC_STATUS fb_decode_timestamp_tz(ISC_STATUS* isc_status, const ISC_TIMESTAMP_TZ* timestampTz, - unsigned* year, unsigned* month, unsigned* day, - unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, - unsigned timeZoneBufferLength, char* timeZoneBuffer) -{ - struct fb_Master* master = fb_get_master_interface(); - struct fb_Status* status = master->vtable->getStatus(master); - struct fb_Util* util = master->vtable->getUtilInterface(master); - util->vtable->decodeTimeStampTz(util, status, timestampTz, year, month, day, - hours, minutes, seconds, fractions, - timeZoneBufferLength, timeZoneBuffer); - if (status->vtable->getState(status)) { - fb_copyStatus(status, isc_status, 20); - } - status->vtable->dispose(status); - return isc_status[1]; -} - /* fetch formatted time with time zone */ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zval *result) { diff --git a/ext/pdo_firebird/pdo_firebird_utils.cpp b/ext/pdo_firebird/pdo_firebird_utils.cpp new file mode 100644 index 0000000000000..1c399e3f3f6e2 --- /dev/null +++ b/ext/pdo_firebird/pdo_firebird_utils.cpp @@ -0,0 +1,92 @@ +/* + +----------------------------------------------------------------------+ + | 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: Ard Biesheuvel | + +----------------------------------------------------------------------+ +*/ + +#include "pdo_firebird_utils.h" +#include +#include + +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; + } + } +} + +/* 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 + +/* Decodes a time with time zone into its time components. */ +extern "C" ISC_STATUS fb_decode_time_tz(ISC_STATUS* isc_status, 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); + if (st.hasData()) { + fb_copy_status((const ISC_STATUS*)st.getErrors(), isc_status, 20); + } + status->dispose(); + return isc_status[1]; +} + +/* Decodes a timestamp with time zone into its date and time components */ +extern "C" ISC_STATUS fb_decode_timestamp_tz(ISC_STATUS* isc_status, 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); + if (st.hasData()) { + fb_copy_status((const ISC_STATUS*)st.getErrors(), isc_status, 20); + } + status->dispose(); + return isc_status[1]; +} + +#endif diff --git a/ext/pdo_firebird/pdo_firebird_utils.h b/ext/pdo_firebird/pdo_firebird_utils.h new file mode 100644 index 0000000000000..8685dfd47f441 --- /dev/null +++ b/ext/pdo_firebird/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: Ard Biesheuvel | + +----------------------------------------------------------------------+ +*/ + +#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 + +ISC_STATUS fb_decode_time_tz(ISC_STATUS* isc_status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, + unsigned timeZoneBufferLength, char* timeZoneBuffer); + +ISC_STATUS fb_decode_timestamp_tz(ISC_STATUS* isc_status, 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/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index a105a7b953ebd..dc1e4bb7f4086 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -19,144 +19,6 @@ #include -#if FB_API_VER >= 40 - -#ifndef CLOOP_EXTERN_C -#ifdef __cplusplus -#define CLOOP_EXTERN_C extern "C" -#else -#define CLOOP_EXTERN_C -#endif -#endif - -struct fb_Status; -struct fb_Master; -struct fb_Util; - -CLOOP_EXTERN_C struct fb_Master* ISC_EXPORT fb_get_master_interface(void); - -#define fb_Status_VERSION 3 - -#define fb_Status_STATE_WARNINGS ((unsigned) (0x1)) -#define fb_Status_STATE_ERRORS ((unsigned) (0x2)) -#define fb_Status_RESULT_ERROR ((int) (-1)) -#define fb_Status_RESULT_OK ((int) (0)) -#define fb_Status_RESULT_NO_DATA ((int) (1)) -#define fb_Status_RESULT_SEGMENT ((int) (2)) - -struct fb_StatusVTable -{ - void* cloopDummy[1]; - uintptr_t version; - void (*dispose)(struct fb_Status* self); - void (*init)(struct fb_Status* self); - unsigned (*getState)(const struct fb_Status* self); - void (*setErrors2)(struct fb_Status* self, unsigned length, const intptr_t* value); - void (*setWarnings2)(struct fb_Status* self, unsigned length, const intptr_t* value); - void (*setErrors)(struct fb_Status* self, const intptr_t* value); - void (*setWarnings)(struct fb_Status* self, const intptr_t* value); - const intptr_t* (*getErrors)(const struct fb_Status* self); - const intptr_t* (*getWarnings)(const struct fb_Status* self); - struct fb_Status* (*clone)(const struct fb_Status* self); -}; - -struct fb_Status -{ - void* cloopDummy[1]; - struct fb_StatusVTable* vtable; -}; - -#define fb_Master_VERSION 2 - -struct fb_MasterVTable -{ - void* cloopDummy[1]; - uintptr_t version; - struct fb_Status* (*getStatus)(struct fb_Master* self); - /* stubs */ - void* getDispatcher; - void* getPluginManager; - void* getTimerControl; - void* getDtc; - void* registerAttachment; - void* registerTransaction; - void* getMetadataBuilder; - /* - struct fb_Status* (*getStatus)(struct fb_Master* self); - struct fb_Provider* (*getDispatcher)(struct fb_Master* self); - struct fb_PluginManager* (*getPluginManager)(struct fb_Master* self); - struct fb_TimerControl* (*getTimerControl)(struct fb_Master* self); - struct fb_Dtc* (*getDtc)(struct fb_Master* self); - struct fb_Attachment* (*registerAttachment)(struct fb_Master* self, struct fb_Provider* provider, struct fb_Attachment* attachment); - struct fb_Transaction* (*registerTransaction)(struct fb_Master* self, struct fb_Attachment* attachment, struct fb_Transaction* transaction); - struct fb_MetadataBuilder* (*getMetadataBuilder)(struct fb_Master* self, struct fb_Status* status, unsigned fieldCount); - */ - int (*serverMode)(struct fb_Master* self, int mode); - struct fb_Util* (*getUtilInterface)(struct fb_Master* self); - void* getConfigManager; - /* struct fb_ConfigManager* (*getConfigManager)(struct fb_Master* self); */ - FB_BOOLEAN (*getProcessExiting)(struct fb_Master* self); -}; - -struct fb_Master -{ - void* cloopDummy[1]; - struct fb_MasterVTable* vtable; -}; - -#define fb_Util_VERSION 4 - -struct fb_UtilVTable -{ - void* cloopDummy[1]; - uintptr_t version; - /* stubs */ - void* getFbVersion; - void* loadBlob; - void* dumpBlob; - void* getPerfCounters; - void* executeCreateDatabase; - /* - void (*getFbVersion)(struct fb_Util* self, struct fb_Status* status, struct fb_Attachment* att, struct fb_VersionCallback* callback); - void (*loadBlob)(struct fb_Util* self, struct fb_Status* status, ISC_QUAD* blobId, struct fb_Attachment* att, struct fb_Transaction* tra, const char* file, FB_BOOLEAN txt); - void (*dumpBlob)(struct fb_Util* self, struct fb_Status* status, ISC_QUAD* blobId, struct fb_Attachment* att, struct fb_Transaction* tra, const char* file, FB_BOOLEAN txt); - void (*getPerfCounters)(struct fb_Util* self, struct fb_Status* status, struct fb_Attachment* att, const char* countersSet, ISC_INT64* counters); - struct fb_Attachment* (*executeCreateDatabase)(struct fb_Util* self, struct fb_Status* status, unsigned stmtLength, const char* creatDBstatement, unsigned dialect, FB_BOOLEAN* stmtIsCreateDb); - */ - void (*decodeDate)(struct fb_Util* self, ISC_DATE date, unsigned* year, unsigned* month, unsigned* day); - void (*decodeTime)(struct fb_Util* self, ISC_TIME time, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions); - ISC_DATE (*encodeDate)(struct fb_Util* self, unsigned year, unsigned month, unsigned day); - ISC_TIME (*encodeTime)(struct fb_Util* self, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions); - unsigned (*formatStatus)(struct fb_Util* self, char* buffer, unsigned bufferSize, struct fb_Status* status); - unsigned (*getClientVersion)(struct fb_Util* self); - /* - struct fb_XpbBuilder* (*getXpbBuilder)(struct fb_Util* self, struct fb_Status* status, unsigned kind, const unsigned char* buf, unsigned len); - unsigned (*setOffsets)(struct fb_Util* self, struct fb_Status* status, struct fb_MessageMetadata* metadata, struct fb_OffsetsCallback* callback); - struct fb_DecFloat16* (*getDecFloat16)(struct fb_Util* self, struct fb_Status* status); - struct fb_DecFloat34* (*getDecFloat34)(struct fb_Util* self, struct fb_Status* status); - */ - void* getXpbBuilder; - void* setOffsets; - void* getDecFloat16; - void* getDecFloat34; - void (*decodeTimeTz)(struct fb_Util* self, struct fb_Status* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); - void (*decodeTimeStampTz)(struct fb_Util* self, struct fb_Status* status, const ISC_TIMESTAMP_TZ* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); - void (*encodeTimeTz)(struct fb_Util* self, struct fb_Status* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone); - void (*encodeTimeStampTz)(struct fb_Util* self, struct fb_Status* status, ISC_TIMESTAMP_TZ* timeStampTz, unsigned year, unsigned month, unsigned day, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone); - /* struct fb_Int128* (*getInt128)(struct fb_Util* self, struct fb_Status* status); */ - void* getInt128; - void (*decodeTimeTzEx)(struct fb_Util* self, struct fb_Status* status, const ISC_TIME_TZ_EX* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); - void (*decodeTimeStampTzEx)(struct fb_Util* self, struct fb_Status* status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); -}; - -struct fb_Util -{ - void* cloopDummy[1]; - struct fb_UtilVTable* vtable; -}; - -#endif - #ifdef SQLDA_VERSION #define PDO_FB_SQLDA_VERSION SQLDA_VERSION #else From 2622961e3dbf8b500ad8220860c6a687f7ff8ba8 Mon Sep 17 00:00:00 2001 From: Simonov Denis Date: Mon, 12 Aug 2024 19:59:12 +0300 Subject: [PATCH 5/5] Correction according to cmb69 --- ext/pdo_firebird/config.w32 | 1 + ext/pdo_firebird/pdo_firebird_utils.cpp | 2 +- ext/pdo_firebird/pdo_firebird_utils.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/pdo_firebird/config.w32 b/ext/pdo_firebird/config.w32 index 9a8197c2655d0..f7cd342120ff2 100644 --- a/ext/pdo_firebird/config.w32 +++ b/ext/pdo_firebird/config.w32 @@ -11,6 +11,7 @@ if (PHP_PDO_FIREBIRD != "no") { ) { EXTENSION("pdo_firebird", "pdo_firebird.c firebird_driver.c firebird_statement.c pdo_firebird_utils.cpp"); + ADD_FLAG("CFLAGS_PDO_FIREBIRD", "/EHsc"); } else { WARNING("pdo_firebird not enabled; libraries and headers not found"); } diff --git a/ext/pdo_firebird/pdo_firebird_utils.cpp b/ext/pdo_firebird/pdo_firebird_utils.cpp index 1c399e3f3f6e2..1ec10e0a2a082 100644 --- a/ext/pdo_firebird/pdo_firebird_utils.cpp +++ b/ext/pdo_firebird/pdo_firebird_utils.cpp @@ -10,7 +10,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | + | Author: Simonov Denis | +----------------------------------------------------------------------+ */ diff --git a/ext/pdo_firebird/pdo_firebird_utils.h b/ext/pdo_firebird/pdo_firebird_utils.h index 8685dfd47f441..9fe4e2eca5948 100644 --- a/ext/pdo_firebird/pdo_firebird_utils.h +++ b/ext/pdo_firebird/pdo_firebird_utils.h @@ -10,7 +10,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | + | Author: Simonov Denis | +----------------------------------------------------------------------+ */