XML-DBMS: Known Bugs
This list is incomplete. For specific problems, search the mailing list archives or ask a question on the mailing list.
Version 1.x Bugs
- Reuse of prepared SELECT statements with JDBC-ODBC bridge and Access doesn't work
- KeyGeneratorImpl doesn't work with Microsoft Access
- Namespace prefix "lost" if more than one prefix defined for same namespace
- Order not supported when foreign key in parent
- Root table assumed to have a key
- Columns with markup not expanded
- Markup characters not serialized correctly
- Duplicate keys not handled correctly?
- Empty elements-as-classes inserted as row of all NULLs
- SubsetToDTD ignores encoding declarations
1. Reuse of prepared SELECT statements with JDBC-ODBC bridge and Access doesn't work
Either the JDBC-ODBC bridge or the MS Access driver does not correctly support the reuse of prepared SELECT statements. As a consequence, the code to reuse these statements has been commented out. If your driver does correctly support prepared SELECT statements, see the comments in Map.checkInSelectStmt for how to increase performance.
2. KeyGeneratorImpl doesn't work with Microsoft Access
KeyGeneratorImpl doesn't work with Microsoft Access. The problem is that the transaction that updates the XMLDBMSKey table is never committed, in spite of a call to do this. As a workaround, comment out the line of code that sets auto-commit to false. Presumably, this means there is a possibility two users could receive the same high key value. Note that it is not clear whether the problem is with Microsoft Access itself or the ODBC driver supplied by Microsoft.
3. Namespace prefix "lost" if more than one prefix defined for same namespace
If more than one prefix is declared in SubsetToDTD.convertDocument or SubsetToDTD.convertExternalSubset, then the prefix actually used is the first one encountered in the DTD.
4. Order not supported when foreign key in parent
When the foreign key in a parent/child relationship between two element types-as-classes is in the table of the parent element type, order information can be saved for the child element type but not retrieved. For example, consider the following:
<SalesOrder> <Number>123</Number> <Customer> <Name>ABC Industries</Name> <Address>123 Main St., Chicago</Address> </Customer> </SalesOrder>
If the foreign key used to join the sales order and customer tables is in the sales order table, then no information about the order in which the Customer element appears in the SalesOrder element can be retrieved from the database. The problem here is that the code to construct SELECT statements and the code to access data in result sets assumes that SELECTs are done over a single table. In this case, the order column for the Customer element is stored in the Sales table, so a join to the Sales table needs to be done when retrieving customer data. Fixing this is likely to require some rethinking in the way in which the statement-generation code in Map and data retrieval code in Row (as well as elsewhere) works.
5. Root table assumed to have a key
If the root table does not have a candidate key, then the DocumentInfo object returned by DOMToDBMS.storeDocument() cannot be used to retrieve the data. It is also quite likely that some code will fail, although this has not been tested.
6. Columns with markup not expanded
When a column containing markup is retrieved from the database, it is not expanded into the corresponding DOM nodes. Instead, it remains as marked up text.
7. Markup characters not serialized correctly
The code that serializes the contents of a DOM node needs to know how to serialize markup characters that are not true markup. For example, if an element contains "a<b", how should the < character be serialized? If it is serialized as a < character, it will generate an error when it is retrieved from the database, as the code will try to parse it as markup. If it is serialized as the entity <, the data in the database cannot be searched for the expected text, but must instead be searched for the < entity usage. Which route to follow should be left as a choice for the user -- probably designated on a per-element-type basis in the mapping document.
8. Duplicate keys not handled correctly?
If the code encounters a duplicate key value when inserting data into the database, it returns an error. Although this makes sense in some cases -- for example, it is clearly an error to insert the same sales order twice -- it does not make sense in others. For example, suppose part information is sent with each sales order. Because multiple sales orders can refer to the same part, all sales orders after the first that refer to a given part will fail because they get a duplicate key error inserting the part information. One possible solution to this is to ignore duplicate key errors when the foreign key in the parent/child relationship is in the table of the parent element; in such a situation, the contents of the child and all its children would presumably be ignored. However, because it is not clear what to do in this case, the best solution for the moment is to simply throw the duplicate key error and find out how people are using the software and what they expect.
9. Empty elements-as-classes inserted as row of all NULLs
If an element-as-class is empty and has no attributes, the code (probably) inserts in a row with all NULLs into the database, which will often cause an INSERT error. It is not clear whether this is the correct behavior.
10. SubsetToDTD ignores encoding declarations
SubsetToDTD ignores encoding declarations, instead depending on the native abilities of Java to decode the bytes. This will most likely be encountered while using MapFactory_DTD.
Version 2.0 Bugs
- Values are placed in the wrong elements / attributes when retrieving data from a result set in version 2.0
- Ordering at the root level is not supported by DBMSToDOM.
- The All element in the action language is not supported.
- The Extends element in the mapping language is not supported.
- The CREATE TABLE statements generated by DDLGenerator may include duplicate constraint names, which are illegal.
- Update and update-or-insert capabilities do not support updating order columns. That is, order columns are guaranteed to be correct only when inserting data.
1. Values are placed in the wrong elements / attributes when retrieving data from a result set in version 2.0.
The version of Transfer in the alpha 3 release (incorrectly) does not call org.xmlmiddleware.xmldbms.maps.utils.MetadataInitializer, which is used to match result set columns to mapping information. To fix this, you need to make the changes to org.xmlmiddleware.xmldbms.tools.Transfer listed below.
Add the following import:
import org.xmlmiddleware.xmldbms.maps.utils.*;
Modify the method private Document retrieveDocumentInternal(Properties configProps, String mapFilename, Properties selects, String filterFilename, Hashtable params) so that it calls initTableMetadata:
private Document retrieveDocumentInternal(Properties configProps, String mapFilename, Properties selects, String filterFilename, Hashtable params) throws XMLMiddlewareException, SQLException { ... resultSets = createResultSets(selects); transferInfo = createTransferInfo(map); filterSet = createFilterSet(map, filterFilename, (validate.indexOf(XMLDBMSProps.FILTERTOKEN) != -1)); // New line of code: initTableMetadata(map, resultSets, filterSet); // Configure the DBMSToDOM object ... }
Add the following method:
private void initTableMetadata(XMLDBMSMap map, Hashtable resultSets, FilterSet filterSet) throws XMLMiddlewareException { MetadataInitializer initializer; Vector filters; Object o; ResultSetFilter rsFilter; String rsName; ResultSet rs; Table table; // Get a new MetadataInitializer. initializer = new MetadataInitializer(map); // Get the Vector of RootFilters and ResultSetFilters. Loop through the // filters and, for each ResultSetFilter that is found, use the result set // metadata to initialize the corresponding table metadata. Note that // ResultSetFilters associate result set names with table names. filters = filterSet.getFilters(); for (int i = 0; i < filters.size(); i++) { // Get the next object and process it if it is a ResultSetFilter. o = filters.elementAt(i); if (o instanceof ResultSetFilter) { rsFilter = (ResultSetFilter)o; // Get the name of the result set specified in the filter and // get the corresponding ResultSet object. rsName = rsFilter.getResultSetName(); rs = (ResultSet)resultSets.get(rsName); if (rs == null) throw new XMLMiddlewareException("Filter document specifies a " + "result set with the name " + rsName + ". No result set with " + "this name was specified in the properties passed to Transfer."); // Get the name of the table specified in the filter; this is the // name of the table in the map that maps the result set. Get the // corresponding Table object. table = map.getTable(rsFilter.getDatabaseName(), rsFilter.getCatalogName(), rsFilter.getSchemaName(), rsFilter.getTableName()); if (table == null) throw new XMLMiddlewareException("Table specified in " + "filter document but not found in map: " + Table.getUniversalName(rsFilter.getDatabaseName(), rsFilter.getCatalogName(), rsFilter.getSchemaName(), rsFilter.getTableName())); // Initialize the metadata for the columns in the table from // the result set metadata. initializer.initializeMetadata(table, rs); } } }
2. Ordering at the root level is not supported by DBMSToDOM.
There is no workaround for this problem.
3. The All element in the action language is not supported.
As a workaround, individually specify the names of the element types whose corresponding columns should be updated.
4. The Extends element in the mapping language is not supported.
If you want data from an element type to be stored in a base table (corresponding to the properties in the superclass) and an extension table (corresponding to the properties found only in the subclass), you must do this by hand. For example, suppose element type A contains properties A1, A2, and A3 and element type B (a subclass of element type A) contains properties A1, A2, A3, B1, and B2. You must construct your XML document so it contains element type A (with properties A1, A2, and A3) and element type B (with properties B1 and B2), where element B is a child of element A. You must then map element types A and B separately.
5. The CREATE TABLE statements generated by DDLGenerator may include duplicate constraint names, which are illegal.
As a workaround, generate the CREATE TABLE statements, then check for and rename any duplicate constraint names.
6. Update and update-or-insert capabilities do not support updating order columns. That is, order columns are guaranteed to be correct only when inserting data.
There is no workaround for this problem.
Version 1.x and 2.0 Bugs
1. DBMSToDOM does not work with SQL Server
DBMSToDOM generally requires more than one result set to be open at any given time. Specifically, it opens as many result sets as its current depth in the hierarchy of tables. Because a Map object contains a single JDBC Connection, this is a problem for databases like SQL Server (Microsoft and Sybase) which allow a single open JDBC Statement per Connection. The eventual solution to this problem is to pass a JDBC 2.0 DataSource to Map and let it create more Connections as it needs them. In the mean time, DBMSToDOM can only retrieve data from a single table when used with SQL Server. (Note that the opposite problem -- transferring data from XML to the database with DOMToDBMS -- does not exist.)