Many databases have a hidden primary key column. MySQL implements this as _rowid. In MySQL’s case it is really a pointer to a previously defined primary key column. However in other databases (in my case, Informix), this column is independent of a deliberately defined primary key. The database which I’m coding for was designed mostly under the practice of depending on the Informix hidden column, ROWID instead of defining a primary key. I’m connecting to Informix from JRuby on Rails using the Informix JDBC driver. All is good except that I cannot figure out a way to make the hidden rowid column show up as an ActiveRecord property. All of the other fields are there, just not rowid. If I query a model using Whatever.find_by_sql(“SELECT rowid,* FROM whatevertable”) it returns an array of “Whatever” objects but the rowid column is not there.
I’ve investigated tweaking the JDBC driver, ActiveRecord or the database; nothing has borne fruit.
Any guidance would be appreciated.
First, note that if your table is fragmented, it won’t have a ROWID – unless you created it using the WITH ROWIDS clause, in which case the ROWID becomes an indexed physical column instead of a virtual column.
Second, why don’t you just use the declared primary key for the table instead of delving behind the scenes – especially when the delving behind the scenes version is not working.
I’m not clear why the explicit notation you are using is not doing as you request; that could be the JDBC driver poking its nose in where its nose does not belong. How many columns do you get back in the result set? If it isn’t the number you select (the number of columns in the table plus one), then something is very fishy.
If I needed to see what the JDBC driver is sending to the server, I would enable SQLI debug tracing – either at the client side or, if the client side does not cooperate, on the server side. In normal (C-based) APIs, enabling SQLI debug is a matter of setting an environment variable:
This will create a file with a name starting ‘
sqli_‘ in the current directory of the process running the C API (ESQL/C, ODBC, etc). I assume that the same mechanism should work with the JDBC driver.If SQLIDEBUG does not work with JDBC, then you have a much harder job – you need to enable SQLI debug on the server side.
Assuming you trap the SQLI (SQL Interface) output, you can then print it using ‘
sqliprint‘. You’d look for the SQL sent to IDS. If it does not contain the ROWID, then you can be fairly sure the JDBC driver is playing silly games with you. However, it is not clear what you’d do to work around that. Maybe try a table alias (such as ‘t’) and:If it turns out that JDBC is tweaking ROWID, we could try aliassing that too:
(The AS is optional after the table name.)
Please keep us posted if you discover anything interesting or useful.
OK; that is a design decision that should be reviewed at your next main upgrade if any of your customers have large enough volumes of data that fragmentation might be beneficial. Remember, fragmented tables do not have a virtual ROWID column; you can create them with a physical ROWID column by using the WITH ROWIDS clause in the CREATE TABLE or ALTER FRAGMENT statements.
Well done on getting the information. Offhand, my knowledge of what the JDBC driver might be doing starts to run out – this might be something to take to IBM/Informix Technical Support. Various questions arise in my mind – and I’m not even sure whether the problem is in the JDBC driver, the JDBC design overall, or something sitting above JDBC; I am not by any stretch of my imagination an expert in the area. (I can spell Java – C; is that right?)
Have you tried fiddling the ROWID into the last column in the statement?
What about aliassing that?
If the JDBC driver sees through both those, then it is working far too hard and doing everyone a disservice. Indeed, I’m not even sure I know how it works with views.
I have a table of elements:
I was able to create a view on that table including the ROWID and then query it:
The two queries produced disjoint sets of data. You may be able to finagle your system to exploit this. If necessary, you’d rename the base tables (e.g. ‘WhateverTable’ becomes ‘Base_Whatever’) and then create the view ‘WhateverTable’ to select the data from Base_Whatever, along with the ROWID. I haven’t formally tried this with a JDBC program, but it ‘ought’ to work (but since the original query also ‘ought’ to work, I am not sure how much reliance I would place on the ‘ought to work’ assertion).