Firebird 2.5 C++ 客户端:DATE 数据类型错误
Firebird 2.5 C++ client: error with DATE data type
环境:Firebird 2.5.4-64 位,在 Windows 8.1.
我正在尝试使用 C 客户端 API(使用 VS2013)编写 C++ 客户端。我在包含 DATE 列的 table 上准备 SELECT 语句时收到此错误(调用 isc_dsql_prepare 函数时出错)
Dynamic SQL Error
-SQL error code = -804
-Data type unknown
-Client SQL dialect 1 does not support reference to DATE datatype
从 isql 工具,我确认数据库正在使用 SQL 方言 3:
SQL> 显示 sql 方言;
客户端 SQL 方言设置为:3,数据库 SQL 方言为:3
在客户端,我将 SQL 方言设置为 3(至少我在附加时没有错误):
uint32_t sqlDialect = 3;
const char* charset = "UTF8";
char dpbBuffer[256], *dpb, *p;
dpb = dpbBuffer;
*dpb++ = isc_dpb_version1;
*dpb++ = isc_dpb_user_name;
*dpb++ = user.size();
strcpy(dpb, user.c_str());
dpb += user.size();
*dpb++ = isc_dpb_password;
*dpb++ = pwd.size();
strcpy(dpb, pwd.c_str());
dpb += pwd.size();
*dpb++ = isc_dpb_lc_ctype;
*dpb++ = 4;
strcpy(dpb, charset);
dpb += 4;
*dpb++ = isc_dpb_sql_dialect;
memcpy(dpb, &sqlDialect, 4);
dpb += 4;
short dpbLength = dpb - dpbBuffer;
if (isc_attach_database(status, 0, url.c_str(), &_db, dpbLength, dpbBuffer))
{
isc_print_status(status);
}
我对 TIMESTAMP 列没有问题,因此我可以将所有 DATE 列设置为 TIMESTAMP 类型,但我希望有人能解释错误消息。
解决方案:
非常感谢 Mark Rotteveel 指出了确切的问题。
首先,详细了解我如何准备声明:
std::string sql = "SELECT * FROM truc";
out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(NbColumn));
out_sqlda->version = SQLDA_VERSION1;
out_sqlda->sqln = NbColumn;
isc_stmt_handle stmt;
isc_dsql_allocate_statement(status, &_db, &stmt);
isc_dsql_prepare(status, &(TransactHandle), &stmt, 0, sql.c_str(), 1, out_sqlda);
我被 Interbase API 指南 pdf 滥用了,它给出了以下内容:
isc_dsql_prepare(
status_vector,
&trans, /* Set by previous isc_start_transaction() call. */
&stmt, /* Statement handle set by this function call. */
0, /* Specifies statement string is null-terminated. */
str, /* Statement string. */
SQLDA_VERSION1, /* XSQLDA version number. */
out_sqlda /* XSQLDA for storing column data. */
);
但是第6个参数不是SQLDA版本,而是SQL方言!!!放 3 解决了这个问题。
查看 .Net 提供程序的代码也很有帮助。
如前所述,API 中的某些方法将 SQL 方言版本作为参数(isc_dsql_prepare
、isc_dsql_execute_immediate
和 isc_dsql_exec_immed2
)。如果您使用参数 1
而不是 3
调用它们,您的语句将被解析为方言 1 语句。
正如您在 Interbase 6 API 指南(第 122 页)中提到的一个示例所说,它是 SQLDA 版本。我的猜测是,在以前版本的 Interbase 中(方言在版本 6 中被引入)这个参数 是 SQLDA 版本(例如 isc_describe
需要da_version
参数在 XSQLDA
参数之前),并且他们重用了这个参数来保持方法参数类型和计数相同。这些方法中的一些方法根本需要 da_version
参数这一事实有点奇怪(sqlda 版本是 XSQLDA
的一部分)。
环境:Firebird 2.5.4-64 位,在 Windows 8.1.
我正在尝试使用 C 客户端 API(使用 VS2013)编写 C++ 客户端。我在包含 DATE 列的 table 上准备 SELECT 语句时收到此错误(调用 isc_dsql_prepare 函数时出错)
Dynamic SQL Error -SQL error code = -804 -Data type unknown -Client SQL dialect 1 does not support reference to DATE datatype
从 isql 工具,我确认数据库正在使用 SQL 方言 3: SQL> 显示 sql 方言; 客户端 SQL 方言设置为:3,数据库 SQL 方言为:3
在客户端,我将 SQL 方言设置为 3(至少我在附加时没有错误):
uint32_t sqlDialect = 3;
const char* charset = "UTF8";
char dpbBuffer[256], *dpb, *p;
dpb = dpbBuffer;
*dpb++ = isc_dpb_version1;
*dpb++ = isc_dpb_user_name;
*dpb++ = user.size();
strcpy(dpb, user.c_str());
dpb += user.size();
*dpb++ = isc_dpb_password;
*dpb++ = pwd.size();
strcpy(dpb, pwd.c_str());
dpb += pwd.size();
*dpb++ = isc_dpb_lc_ctype;
*dpb++ = 4;
strcpy(dpb, charset);
dpb += 4;
*dpb++ = isc_dpb_sql_dialect;
memcpy(dpb, &sqlDialect, 4);
dpb += 4;
short dpbLength = dpb - dpbBuffer;
if (isc_attach_database(status, 0, url.c_str(), &_db, dpbLength, dpbBuffer))
{
isc_print_status(status);
}
我对 TIMESTAMP 列没有问题,因此我可以将所有 DATE 列设置为 TIMESTAMP 类型,但我希望有人能解释错误消息。
解决方案: 非常感谢 Mark Rotteveel 指出了确切的问题。
首先,详细了解我如何准备声明:
std::string sql = "SELECT * FROM truc";
out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(NbColumn));
out_sqlda->version = SQLDA_VERSION1;
out_sqlda->sqln = NbColumn;
isc_stmt_handle stmt;
isc_dsql_allocate_statement(status, &_db, &stmt);
isc_dsql_prepare(status, &(TransactHandle), &stmt, 0, sql.c_str(), 1, out_sqlda);
我被 Interbase API 指南 pdf 滥用了,它给出了以下内容:
isc_dsql_prepare(
status_vector,
&trans, /* Set by previous isc_start_transaction() call. */
&stmt, /* Statement handle set by this function call. */
0, /* Specifies statement string is null-terminated. */
str, /* Statement string. */
SQLDA_VERSION1, /* XSQLDA version number. */
out_sqlda /* XSQLDA for storing column data. */
);
但是第6个参数不是SQLDA版本,而是SQL方言!!!放 3 解决了这个问题。 查看 .Net 提供程序的代码也很有帮助。
如前所述,API 中的某些方法将 SQL 方言版本作为参数(isc_dsql_prepare
、isc_dsql_execute_immediate
和 isc_dsql_exec_immed2
)。如果您使用参数 1
而不是 3
调用它们,您的语句将被解析为方言 1 语句。
正如您在 Interbase 6 API 指南(第 122 页)中提到的一个示例所说,它是 SQLDA 版本。我的猜测是,在以前版本的 Interbase 中(方言在版本 6 中被引入)这个参数 是 SQLDA 版本(例如 isc_describe
需要da_version
参数在 XSQLDA
参数之前),并且他们重用了这个参数来保持方法参数类型和计数相同。这些方法中的一些方法根本需要 da_version
参数这一事实有点奇怪(sqlda 版本是 XSQLDA
的一部分)。