RexxSQL on PASE broken
Brought to you by:
rexx
Jesse Gorzinski of IBM i Rochester has successfully built Regina on the IBM i PASE environment.
I have build rexxsql
which runs, but does not seem to produce correct result sets.
For instance, given the following script:
Call RXFuncAdd 'SqlLoadFuncs','REXXSQL','SqlLoadFuncs' Call SqlLoadFuncs say "result of sqlconnect is" sqlconnect("opensrc",'jwoehr','********','mysystem') query1 = "select MSGNUM,SENDER,TIMESENT,MSGTEXT from UBLUTEST.XAMPL" say "The result of query is" sqlcommand("Q1", query1) say "Q1.MSGNUM.0 is stem variable supposed to contain number of rows" say "Number of rows is" Q1.MSGNUM.0 /* DO i = 1 to Q1.MSGNUM.0 */ DO i = 1 to 2 say q1.MSGNUM.i q1.SENDER.i q1.TIMESENT.i q1.MSGTEXT.i end
and a table UBLUTEST.XAMPL which contains two rows:
1 Fred W. Foobar 12345678 this is a silly message 2 Florian Gheorgiu 56789012 Please don't talk about me when I'm gone
execution proceeds as follows (one blank row then the names of the stem vars:
$ rexxsql mytest.rex result of sqlconnect is 0 The result of query is 1 Q1.MSGNUM.0 is stem variable supposed to contain number of rows Number of rows is Q1.MSGNUM.0 Q1.MSGNUM.2 Q1.SENDER.2 Q1.TIMESENT.2 Q1.MSGTEXT.2
Any tips, please?
I suggest you run rexxsql with full debugging flags:
rexxsql -Dvd mytest.rex
This will provide lots of infromation including setting error variables that may hint as the problem.
Hi Mark, long time, no chat. Good to hear from you.
The suspicious stuff is here:
Hi Jack. Yes been a while. I did some Googling. Have a look at this text I found, hopefully it will work for you.
The iSeries ODBC driver obviously looks at your environment and decides
that if you have UTF-8 set it will encode data returned from the
database in UTF-8. Denis had UTF-8 set and his data contained some
accented characters. Also, Denis' data was held in char(30) columns so
trailing spaces are returned. When DBD::ODBC queries the driver about
the column it is told it is of size 30 and binds the buffer at size 31
allowing for the trailing NULL. When the data is returned it requires
more than 31 bytes now because UTF-8 encoding has increased the size in
bytes of some chrs. Now you are I know that the iSeries driver meant
that 30 to be 30 characters but ODBC defines it as bytes and even if
ODBC did not say this there are other places where returning UTF-8
encoded data in ODBC is not possible (e.g., SQLGetData provides a buffer
for the returned data and each subsequent call returns more of a columns
data SO LONG as the buffer on the previous call was filled. If you UTF-8
encode the data it may not be possible to put a full chr in it).
In Denis' case we can work around it to a point because he can rtrim the
column to take the spaces off and leave room for the encoding but this
only works because his dataset only contains a few accented chrs and
plenty of trailing spaces. Anyone doing this also needs to know the data
is UTF-8 encoded and decode it. The other alternative is to do what
Denis did and take UTF-8 out of your environment.
Aha!
Will test ...
Hmmm ...
But still the same result. I wonder if it's getting some system-wide setting for the ODBC driver itself.
Which is what you said, of course, per Denis
Thanks for the help, we'll test this on a test system.
Since Jack's data set does not have expanding chars, I'm not sure the root cause is the same.
I'd recommend some next steps.
1) try this query:
select TRIM(MSGNUM) as MSG, TRIM(SENDER) as SND,TRIM(TIMESENT) as TSENT,TRIM(MSGTEXT) as TEXT from UBLUTEST.XAMPL
I'm not sure what your column data types are, but this would maybe alleviate boundary conditions if you have a non-varchar string field. Maybe.
In any event, please share the column types in use.
2) Gather a CWBTRC, like so:
CWBTRC /DT:1
[recreate problem]
CWBTRC /DT:0
[send in logs, by default in
~/.iSeriesAccess
Ran the query as show above with the TRIM()s. Trace attached.
Jack, to be clear, are you still seeing the same behavior withthe TRIM()s?
Yes, that which I uploaded was with the TRIM()s.
Ahh yes... I see this now in the raw trace data (my analysis tool wasn't showing me the CWB0111, sorry!)
Some interesting tidbits in the repeated (at a glance, seemingly every row, every column) data.
It looks like we're trying to convert to 819, so UTF8 isn't the root cause.
This line is interesting:
s*=0x18012237A sl=1 t*=0x180111C60 tl=0
Those fields are src ptr, src len, tgt ptr, tgt len.
RexxSQL is passing a zero-length target buffer to the ODBC driver.
So, I propose three hypotheses:
1) a flat-out bug in RexxSQL
2) An endianness issue of some sort (I'm thinking unlikely)
3) (my #1 bet) An issue related to legacy 64bit mode and ODBC
BUILD_LEGACY_64_BIT_MODE
I'd suggest checking that:
- the build is picking up the sql.h and sqltypes.h from unixODBC-devel (
/QOpenSys/pkgs/include/*
), and not, for instance the sqlcli-devel ones- the build does not have
BUILD_LEGACY_64_BIT_MODE
defined.Also, one could check the RexxSQL code to see what data type is used for the buffer size.
Glancing through rexxsql's
cli-odbc\rexxcli.c
, I see common use of types such asSWORD
andSDWORD
, which I think is troublesome when dealing with a 64bit ODBC drivers that aren't built withBUILD_LEGACY_64_BIT_MODE
I suspect it's related to this issue: https://sourceforge.net/p/rexxsql/support-requests/28/
and maybe this one https://sourceforge.net/p/rexxsql/support-requests/31/
I tried adding these two lines to the build file:
with no change in the outcome.
Thanks both for looking into this further. I haven't done much with RexxSQL, or the ODBC port for a long time. I presume you are building Rexx/SQL against unixodbc ? I've looked into the unixodbc headers and am not 100% sure how to fix the problem. My best guess at the moment would be to use the SQLINTEGER, SQLLEN etc typedefs (these are new since I wrote the ODBC port) instead of SDWORD, SWORD etc. Does these seem like it would solve the problems not only with using unixodbc, but hopefully also on 64bit windows? I have no access to a big-endian machine to be able to test if the changes work.
@rexx, that's correct. Jack has built against unixODBC. 64-bit support in ODBC has a tumultuous history, as you may know. We've seen a lot of people run into crashes, missing data (as this issue), or overall unpredictable behavior because of the churn in the data types. There's a pretty good writeup at https://www.easysoft.com/developer/interfaces/odbc/64-bit.html#unixodbc-2-2-12 and
https://www.easysoft.com/developer/interfaces/odbc/64-bit.html#unixodbc-2-2-13
In net... I can't confidently say that using the
SQL*
types would fix this problem, but in my experience it could. And if it does, it is likely to fix 64bit Windows problems also.If you are interested in pursuing, we can surely procure an IBM i system and/or help test any changes.
Thanks!
Thanks Jesse. I've made the changes on 64bit Windows to use SQLLEN and friends and to remove lots of warnings regarding loss of precision; mainly by adding casts :-) Runs fine via 64bit driver to SQLite3. not a perfect test, but the best I've got on that machine. I'm in the process of bringing the changes over to Linux and adding a configure check to see if SQLLEN is typedefed. Once I get that built on 64bit Linux with unixODBC I'll make a source zip file available.
Access to a big-endian sysem would be very helpful, not only for Rexx/SQL, but for all my open source software!
Mark, I can probably arrange access for this purpose. Please pm me and I'll set you up.
Everything good, @rexx? I know we had some confusion over one of your email addrs bouncing.