Details
Description
Before upgrading to 0.9.9, we can create a virtual class in mapping to compose two and more real table. For example:
CALL SQL SELECT a.a1, a.a2, b.b1, b.b2 from tableA a left join tableB b on b.a = a.id AS model.Dummy
It throws the following exception for now on:
java.sql.SQLException: Column index out of range.
at org.exolab.castor.jdo.engine.SQLEngine$SQLQuery.fetchRaw(SQLEngine.java:2561)
at org.exolab.castor.jdo.engine.SQLEngine$SQLQuery.nextIdentity(SQLEngine.java:2249)
at org.exolab.castor.persist.QueryResults.nextIdentity(QueryResults.java:174)
at org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:581)
at org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:567)
When debugging, I'm surprised to find the SQLEngine use the nonexistent dummy table name in the query statment.
BTW, there is another bug I found before. The following mapping will make query fail:
<class identity="id" name="model.Item">
<map-to table="item"/>
<field name="id" type="integer">
<sql name="id" type="integer"/>
</field>
<field name="prop" type="model.Prop" collection="collection">
<sql many-key="item" />
</field>
<field name="name" type="string">
<sql name="name" type="varchar"/>
</field>
</class>
while, this doesn't:
<class identity="id" name="model.Item">
<map-to table="item"/>
<field name="id" type="integer">
<sql name="id" type="integer"/>
</field>
<field name="name" type="string">
<sql name="name" type="varchar"/>
</field>
<field name="prop" type="model.Prop" collection="collection">
<sql many-key="item" />
</field>
</class>
Someone also comment it out in line 2392, SQLEngine.java:
// TODO: wrong, as it could be that the first field is not part of the root class.
if (numberOfFields > 0) {
tableName = _engine._fields[0].tableName;
Testcase will be attached.
Activity
| Field | Original Value | New Value |
|---|---|---|
| Attachment | mapping.xml [ 17633 ] | |
| Attachment | Prop.java [ 17635 ] | |
| Attachment | Item.java [ 17634 ] |
| Attachment | Sum.java [ 17636 ] | |
| Attachment | TestTemplate.java [ 17637 ] |
| Attachment | patch.C1265.20051123.txt [ 17728 ] |
| Comment |
[ Just an idea .... ;-) Index: SQLEngine.java =================================================================== RCS file: /home/projects/castor/scm/castor/src/main/org/exolab/castor/jdo/engine/SQLEngine.java,v retrieving revision 1.38 diff -u -r1.38 SQLEngine.java --- SQLEngine.java 13 Oct 2005 07:40:54 -0000 1.38 +++ SQLEngine.java 23 Nov 2005 11:10:35 -0000 @@ -419,7 +419,7 @@ _log.debug( Messages.format( "jdo.createSql", sql ) ); } - return new SQLQuery( this, sql, types ); + return new SQLQuery( this, sql, types, false ); } @@ -441,7 +441,7 @@ _log.debug (Messages.format ("jdo.directSQL", sql)); } - return new SQLQuery( this, sql, types ); + return new SQLQuery( this, sql, types, true ); } if (_log.isDebugEnabled()) { @@ -2027,8 +2027,21 @@ private boolean _resultSetDone; private Object[] _fields; + + /** + * Indicates whether the SQL query executed is issued as part of a SQL + * CALL statement or not. + */ + private boolean _isCallSql = false; - SQLQuery( SQLEngine engine, String sql, Class[] types ) + /** + * Creates an instance of SQLQuery. + * @param engine SQLEngine instance + * @param sql The SQL statement to execute + * @param types Types of the class used. + * @param isCallSql true if the SQL is issued as part of a CALL SQL statement. + */ + SQLQuery(SQLEngine engine, String sql, Class[] types, boolean isCallSql) { _engine = engine; _requestedEngine = engine; @@ -2039,6 +2052,8 @@ for (int i = 0; i < _identSqlType.length; i++) { _identSqlType[i] = ((JDOFieldDescriptor) _engine._clsDesc.getIdentities()[i]).getSQLType()[0]; } + + _isCallSql = isCallSql; } @@ -2313,11 +2328,16 @@ String metaTableName = metaData.getTableName(count); String metaColumnName = metaData.getColumnName(count); if (fieldColumnName.equalsIgnoreCase(metaColumnName)) { + if (!_isCallSql) { if (fieldTableName.equalsIgnoreCase(metaTableName)) { - break; - } else if ("".equals(metaTableName)) { - break; - } + break; + } else if ("".equals(metaTableName)) { + break; + } + } else { + // if we are running as a result of a CALL SQL statement, let's relax our checks. + break; + } } else if (fieldName.equalsIgnoreCase(metaColumnName)) { break; } Let me know what you think. Werner ] |
| Assignee | Werner Guttmann [ wguttmn ] |
| Fix Version/s | 1.0 [ 11700 ] | |
| Original Estimate | 1 hour [ 3600 ] | |
| Remaining Estimate | 1 hour [ 3600 ] |
| Status | Open [ 1 ] | Resolved [ 5 ] |
| Resolution | Fixed [ 1 ] |
| Fix Version/s | 1.0 [ 11700 ] | |
| Fix Version/s | 1.0 M1 [ 12121 ] |
| Status | Resolved [ 5 ] | Closed [ 6 ] |
Sean, is there any way you could join me on IRC ? Either connect to irc://irc.codehaus.org:6665/castor, or if you cannot connect due to security restrictions, pleae use http://irc.codehaus.org, and join the castor channel.