mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
pdo_firebird: Formatting time zone types
As a follow-up to the commit which introduced support for Firebird 4.0+ data types[1], we add support for formats for types with time zones. Since this uses the newer Firebird C++ API, pdo_firebird now requires a C++ compiler to be built. [1] <https://github.com/php/php-src/pull/14897> Co-authored-by: Christoph M. Becker <cmbecker69@gmx.de> Closes GH-15230.
This commit is contained in:
parent
5478d4b2c1
commit
225034dbbc
10 changed files with 318 additions and 16 deletions
3
NEWS
3
NEWS
|
@ -50,6 +50,9 @@ PHP NEWS
|
||||||
deprecated. As the MYSQLI_STORE_RESULT_COPY_DATA constant was only used in
|
deprecated. As the MYSQLI_STORE_RESULT_COPY_DATA constant was only used in
|
||||||
conjunction with this function it has also been deprecated. (Girgias)
|
conjunction with this function it has also been deprecated. (Girgias)
|
||||||
|
|
||||||
|
- PDO_Firebird:
|
||||||
|
. Support proper formatting of time zone types. (sim1984)
|
||||||
|
|
||||||
- PHPDBG:
|
- PHPDBG:
|
||||||
. array out of bounds, stack overflow handled for segfault handler on windows.
|
. array out of bounds, stack overflow handled for segfault handler on windows.
|
||||||
(David Carlier)
|
(David Carlier)
|
||||||
|
|
|
@ -121,6 +121,8 @@ PHP 8.4 UPGRADE NOTES
|
||||||
have been changed to set value as a bool.
|
have been changed to set value as a bool.
|
||||||
|
|
||||||
- PDO_FIREBIRD:
|
- PDO_FIREBIRD:
|
||||||
|
. Since some Firebird C++ APIs are used now, this extension requires a C++
|
||||||
|
compiler to be built.
|
||||||
. getAttribute, ATTR_AUTOCOMMIT has been changed to get the value as a bool.
|
. getAttribute, ATTR_AUTOCOMMIT has been changed to get the value as a bool.
|
||||||
|
|
||||||
- PDO_MYSQL:
|
- PDO_MYSQL:
|
||||||
|
|
|
@ -45,9 +45,24 @@ if test "$PHP_PDO_FIREBIRD" != "no"; then
|
||||||
|
|
||||||
PHP_CHECK_PDO_INCLUDES
|
PHP_CHECK_PDO_INCLUDES
|
||||||
|
|
||||||
|
|
||||||
|
PHP_PDO_FIREBIRD_COMMON_FLAGS=""
|
||||||
PHP_NEW_EXTENSION([pdo_firebird],
|
PHP_NEW_EXTENSION([pdo_firebird],
|
||||||
[pdo_firebird.c firebird_driver.c firebird_statement.c],
|
[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_SUBST([PDO_FIREBIRD_SHARED_LIBADD])
|
||||||
PHP_ADD_EXTENSION_DEP(pdo_firebird, pdo)
|
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
|
fi
|
||||||
|
|
|
@ -10,7 +10,8 @@ if (PHP_PDO_FIREBIRD != "no") {
|
||||||
PHP_PHP_BUILD + "\\include\\interbase;" + PHP_PHP_BUILD + "\\interbase\\include;" + PHP_PDO_FIREBIRD)
|
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");
|
||||||
|
ADD_FLAG("CFLAGS_PDO_FIREBIRD", "/EHsc");
|
||||||
} else {
|
} else {
|
||||||
WARNING("pdo_firebird not enabled; libraries and headers not found");
|
WARNING("pdo_firebird not enabled; libraries and headers not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "ext/pdo/php_pdo_driver.h"
|
#include "ext/pdo/php_pdo_driver.h"
|
||||||
#include "php_pdo_firebird.h"
|
#include "php_pdo_firebird.h"
|
||||||
#include "php_pdo_firebird_int.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*,
|
static int php_firebird_alloc_prepare_stmt(pdo_dbh_t*, const zend_string*, XSQLDA*, isc_stmt_handle*,
|
||||||
HashTable*);
|
HashTable*);
|
||||||
|
@ -462,14 +463,13 @@ static int php_firebird_preprocess(const zend_string* sql, char* sql_out, HashTa
|
||||||
|
|
||||||
#if FB_API_VER >= 40
|
#if FB_API_VER >= 40
|
||||||
/* set coercing a data type */
|
/* 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. */
|
/* 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)), */
|
/* 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 */
|
/* TIMESTAMP WITH TIME ZONE, and TIME WITH TIME ZONE. */
|
||||||
/* can only be mapped to strings. The last two too, but for them it is potentially possible to set */
|
/* This function allows you to ensure minimal performance */
|
||||||
/* the display format, as is done for TIMESTAMP. This function allows you to ensure minimal performance */
|
/* of queries if they contain parameters of the above types. */
|
||||||
/* of queries if they contain columns and parameters of the above types. */
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
short dtype;
|
short dtype;
|
||||||
short nullable;
|
short nullable;
|
||||||
|
@ -503,6 +503,63 @@ static void set_coercing_data_type(XSQLDA* sqlda)
|
||||||
var->sqltype = SQL_VARYING + nullable;
|
var->sqltype = SQL_VARYING + nullable;
|
||||||
var->sqllen = 46;
|
var->sqllen = 46;
|
||||||
break;
|
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;
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
|
||||||
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +714,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
|
||||||
|
|
||||||
#if FB_API_VER >= 40
|
#if FB_API_VER >= 40
|
||||||
/* set coercing a data type */
|
/* set coercing a data type */
|
||||||
set_coercing_data_type(&S->out_sqlda);
|
set_coercing_output_data_types(&S->out_sqlda);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* allocate the input descriptors */
|
/* allocate the input descriptors */
|
||||||
|
@ -676,7 +733,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
|
||||||
|
|
||||||
#if FB_API_VER >= 40
|
#if FB_API_VER >= 40
|
||||||
/* set coercing a data type */
|
/* set coercing a data type */
|
||||||
set_coercing_data_type(S->in_sqlda);
|
set_coercing_input_data_types(S->in_sqlda);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,7 +1302,8 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
|
||||||
ZVAL_STRING(val, tmp);
|
ZVAL_STRING(val, tmp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
/* TODO Check this is correct? */
|
||||||
|
ZEND_FALLTHROUGH;
|
||||||
|
|
||||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||||
ZVAL_BOOL(val, H->fetch_table_names);
|
ZVAL_BOOL(val, H->fetch_table_names);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ext/pdo/php_pdo_driver.h"
|
#include "ext/pdo/php_pdo_driver.h"
|
||||||
#include "php_pdo_firebird.h"
|
#include "php_pdo_firebird.h"
|
||||||
#include "php_pdo_firebird_int.h"
|
#include "php_pdo_firebird_int.h"
|
||||||
|
#include "pdo_firebird_utils.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -64,6 +65,78 @@ static zend_always_inline ISC_QUAD php_get_isc_quad_from_sqldata(const ISC_SCHAR
|
||||||
READ_AND_RETURN_USING_MEMCPY(ISC_QUAD, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* free the allocated space for passing field values to the db and back */
|
||||||
static void php_firebird_free_sqlda(XSQLDA const *sqlda) /* {{{ */
|
static void php_firebird_free_sqlda(XSQLDA const *sqlda) /* {{{ */
|
||||||
{
|
{
|
||||||
|
@ -494,6 +567,16 @@ static int pdo_firebird_stmt_get_col(
|
||||||
size_t len = strftime(buf, sizeof(buf), fmt, &t);
|
size_t len = strftime(buf, sizeof(buf), fmt, &t);
|
||||||
ZVAL_STRINGL(result, buf, len);
|
ZVAL_STRINGL(result, buf, len);
|
||||||
break;
|
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: {
|
case SQL_BLOB: {
|
||||||
ISC_QUAD quad = php_get_isc_quad_from_sqldata(var->sqldata);
|
ISC_QUAD quad = php_get_isc_quad_from_sqldata(var->sqldata);
|
||||||
return php_firebird_fetch_blob(stmt, colno, result, &quad);
|
return php_firebird_fetch_blob(stmt, colno, result, &quad);
|
||||||
|
|
92
ext/pdo_firebird/pdo_firebird_utils.cpp
Normal file
92
ext/pdo_firebird/pdo_firebird_utils.cpp
Normal file
|
@ -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: Simonov Denis <sim-mail@list.ru> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pdo_firebird_utils.h"
|
||||||
|
#include <firebird/Interface.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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
|
48
ext/pdo_firebird/pdo_firebird_utils.h
Normal file
48
ext/pdo_firebird/pdo_firebird_utils.h
Normal file
|
@ -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 <sim-mail@list.ru> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PDO_FIREBIRD_UTILS_H
|
||||||
|
#define PDO_FIREBIRD_UTILS_H
|
||||||
|
|
||||||
|
#include <ibase.h>
|
||||||
|
|
||||||
|
#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 */
|
|
@ -54,9 +54,9 @@ echo "\ndone\n";
|
||||||
"N": "123.97",
|
"N": "123.97",
|
||||||
"N2": "123.97",
|
"N2": "123.97",
|
||||||
"TS": "2024-05-04 12:59:34",
|
"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": "12:59:34",
|
||||||
"T_TZ": "12:59:34.2390 Europe\/Moscow",
|
"T_TZ": "12:59:34 Europe\/Moscow",
|
||||||
"DF16": "1.128",
|
"DF16": "1.128",
|
||||||
"DF34": "1.128"
|
"DF34": "1.128"
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ echo "\ndone\n";
|
||||||
"I128": "12",
|
"I128": "12",
|
||||||
"N1": "12.34",
|
"N1": "12.34",
|
||||||
"N2": "12.34",
|
"N2": "12.34",
|
||||||
"TS_TZ": "%s 12:59:34.2390 Europe\/Moscow",
|
"TS_TZ": "2024-05-04 12:59:34 Europe\/Moscow",
|
||||||
"T_TZ": "12:59:00.0000 Europe\/Moscow",
|
"T_TZ": "12:59:00 Europe\/Moscow",
|
||||||
"DF16": "12.34",
|
"DF16": "12.34",
|
||||||
"DF34": "12.34"
|
"DF34": "12.34"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue