Sybase ASE 到 HSQLDB JUnit java.sql.SQLSyntaxErrorException: 找不到类型或用户缺少权限
Sybase ASE to HSQLDB JUnit java.sql.SQLSyntaxErrorException: type not found or user lacks privilege
在我继承的一个项目中,有一个prepared statement定义为:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
FROM FILES_TABLE
WHERE file_id = #{id}
</select>
此 SQL 语句在 运行 时使用 Sybase ASE
数据库运行良好。
但是执行它的 JUnit(作为构建的一部分)一直失败
java.sql.SQLSyntaxErrorException: type not found or user lacks privilege: FILE_DATA_SHORT
我将此错误跟踪到 CASE THEN 转换语句:
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
也就是说,以下准备好的语句不会产生上述错误:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
file_data_short fileData
FROM FILES_TABLE
WHERE file_id = #{id}
</select>
怀疑这可能与 convert
有关,我发现 这表明 运行 HSQLDB 与非 HSQLDB 方言必须首先在 HSQLDB 上启用该语法兼容模式。
在 this SO answer 中发现了类似的提示。
这样我就可以在 the hsqldb.org doc:
中找到特定于 Sybase 的指令
"Use SET DATABASE SQL SYNTAX MSS TRUE or the equivalent URL property sql.syntax_mss=true to enable support for the CONVERT(<type definition>, <expression)
function with switched order of arguments"
好吧,我就是这样做的,将 sql.syntax_mss=true
添加到项目的 HSDLDB 属性中:
HSQLDB(org.hsqldb.jdbc.JDBCDriver.class, org.hsqldb.jdbc.JDBCDataSource.class, "jdbc:hsqldb:mem:mymemdb;sql.syntax_mss=true", new TestMapperHsqlDB(), true)
但这并没有帮助:当 运行 进行 JUnit 测试时,我仍然遇到那个可怕的异常(只有那时。那个查询 运行 在 运行 时间或来自 DBeaver)。
想知道我在尝试使这项工作同时适用于 运行time (Sybase/ASE) 和 JUnit (HSDLDB) 时还可能遗漏什么吗?
回答我自己的问题,以造福于可能因类似遭遇而感到困惑的其他人:
在尝试使用 syntax/dialect 修饰符(参见 OP)后,我发现 this list of HSQLDB built it in functions,其中 'image' 不是 HSQLDB 支持的类型,因此 convert
没有机会成功...
这促使我寻找 solution/workaround,其中 SQL 本身会根据其所在的数据库略有不同 运行:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
<if test="_databaseId == 'SYBASE'">
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
</if>
<if test="_databaseId == 'HSQLDB'">
CASE WHEN FFT.file_data_long is null THEN FFT.file_data_short ELSE FFT.file_data_long END AS fileData
</if>
FROM FILES_TABLE FFT
WHERE file_id = #{id}
</select>
这 -- 很有魅力。
在我继承的一个项目中,有一个prepared statement定义为:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
FROM FILES_TABLE
WHERE file_id = #{id}
</select>
此 SQL 语句在 运行 时使用 Sybase ASE
数据库运行良好。
但是执行它的 JUnit(作为构建的一部分)一直失败
java.sql.SQLSyntaxErrorException: type not found or user lacks privilege: FILE_DATA_SHORT
我将此错误跟踪到 CASE THEN 转换语句:
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
也就是说,以下准备好的语句不会产生上述错误:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
file_data_short fileData
FROM FILES_TABLE
WHERE file_id = #{id}
</select>
怀疑这可能与 convert
有关,我发现
在 this SO answer 中发现了类似的提示。
这样我就可以在 the hsqldb.org doc:
中找到特定于 Sybase 的指令"Use SET DATABASE SQL SYNTAX MSS TRUE or the equivalent URL property sql.syntax_mss=true to enable support for the CONVERT(<type definition>, <expression)
function with switched order of arguments"
好吧,我就是这样做的,将 sql.syntax_mss=true
添加到项目的 HSDLDB 属性中:
HSQLDB(org.hsqldb.jdbc.JDBCDriver.class, org.hsqldb.jdbc.JDBCDataSource.class, "jdbc:hsqldb:mem:mymemdb;sql.syntax_mss=true", new TestMapperHsqlDB(), true)
但这并没有帮助:当 运行 进行 JUnit 测试时,我仍然遇到那个可怕的异常(只有那时。那个查询 运行 在 运行 时间或来自 DBeaver)。
想知道我在尝试使这项工作同时适用于 运行time (Sybase/ASE) 和 JUnit (HSDLDB) 时还可能遗漏什么吗?
回答我自己的问题,以造福于可能因类似遭遇而感到困惑的其他人:
在尝试使用 syntax/dialect 修饰符(参见 OP)后,我发现 this list of HSQLDB built it in functions,其中 'image' 不是 HSQLDB 支持的类型,因此 convert
没有机会成功...
这促使我寻找 solution/workaround,其中 SQL 本身会根据其所在的数据库略有不同 运行:
<select id="GET_FILE_BY_FILE_ID" parameterType="long" resultType="com.employer.my.File" statementType="PREPARED">
SELECT
file_id fileId,
file_name name,
file_type type,
<if test="_databaseId == 'SYBASE'">
CASE WHEN file_data_long is null THEN convert (image, file_data_short) ELSE file_data_long END AS fileData
</if>
<if test="_databaseId == 'HSQLDB'">
CASE WHEN FFT.file_data_long is null THEN FFT.file_data_short ELSE FFT.file_data_long END AS fileData
</if>
FROM FILES_TABLE FFT
WHERE file_id = #{id}
</select>
这 -- 很有魅力。