I'm trying to implement a Guice module that to lets Guacamole use SQLite as a backend. The Guacamole project has a generic JDBC base module. This lets you implement modules for specific datastores with less code. Most of the lines of code end up being in mapper XML files. The project provides PostgreSQL and MySQL implementations.
I based this SQLite module off of the MySQL module. For the mapper XML files, SQLite and MySQL are similar enough that I didn't have to make any changes. However, when I try to use the SQLite module, I get this error:
### Error querying database. Cause: java.lang.ArrayIndexOutOfBoundsException: 2
### The error may exist in org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT guacamole_connection_group.connection_group_id, connection_group_name, parent_id, type, max_connections, max_connections_per_user, enable_session_affinity FROM guacamole_connection_group JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id WHERE guacamole_connection_group.connection_group_id IN ( ? ) AND user_id = ? AND permission = 'READ'; SELECT parent_id, guacamole_connection_group.connection_group_id FROM guacamole_connection_group JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id WHERE parent_id IN ( ? ) AND user_id = ? AND permission = 'READ'; SELECT parent_id, guacamole_connection.connection_id FROM guacamole_connection JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id WHERE parent_id IN ( ? ) AND user_id = ? AND permission = 'READ';
### Cause: java.lang.ArrayIndexOutOfBoundsException: 2
It looks like the problem is that two parameters are passed to the query, but each is repeated three times. When MyBatis generates the PreparedStatement, it acts as if there are six parameters that needed to be passed in.
Here's the query it has a problem with:
<!-- Select multiple connection groups by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections">
SELECT
guacamole_connection_group.connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM guacamole_connection_group
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
WHERE guacamole_connection_group.connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, guacamole_connection_group.connection_group_id
FROM guacamole_connection_group
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, guacamole_connection.connection_id
FROM guacamole_connection
JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
</select>
If I manually populate the parameters, I can execute this against the SQLite database. Also, the MySQL version works fine.
What the heck is going on? What can I do to debug this? Is it a MyBatis problem or something with the JDBC connector?
If it helps, you can see the code for the module here.
Here's the method for the parameter the mapper related to this query. The full mapper classes for ConnectionGroup are here and here. The full mapper XML for my SQLite module is here.
Collection<ModelType> selectReadable(@Param("user") UserModel user,
@Param("identifiers") Collection<String> identifiers);
This is what the ConnectionGroupResultMap
looks like:
<resultMap id="ConnectionGroupResultMap" type="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel" >
<!-- Connection group properties -->
<id column="connection_group_id" property="objectID" jdbcType="INTEGER"/>
<result column="connection_group_name" property="name" jdbcType="VARCHAR"/>
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
<result column="type" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.ConnectionGroup$Type"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="enable_session_affinity" property="sessionAffinityEnabled" jdbcType="BOOLEAN"/>
<!-- Child connection groups -->
<collection property="connectionGroupIdentifiers" resultSet="childConnectionGroups" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_group_id"/>
</collection>
<!-- Child connections -->
<collection property="connectionIdentifiers" resultSet="childConnections" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_id"/>
</collection>
</resultMap>