Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in test suite on M1: Program type out of range #41

Open
soupi opened this issue Oct 27, 2021 · 4 comments
Open

Error in test suite on M1: Program type out of range #41

soupi opened this issue Oct 27, 2021 · 4 comments

Comments

@soupi
Copy link

soupi commented Oct 27, 2021

I am getting an error running the test suite on a macbook with the M1 chip.

Specifically, the Database.ODBC.Internal, Data retrieval, Basic santiy check test fails with
UnsuccessfulReturnCode "getSize" (-1) "[unixODBC][Driver Manager]Program type out of range[unixODBC][Driver Manager]Program type out of range"


Context

I'm on macOS, M1 chip, using brew install HOMEBREW_NO_ENV_FILTERING=1 ACCEPT_EULA=Y brew install msodbcsql17 mssql-tools unixodbc to install odbc drivers.

I'm using the mcr.microsoft.com/azure-sql-edge:latest docker image to run mssql server:

$ docker run --name odbc-test-21433 --platform linux/arm64 -e ACCEPT_EULA=1 -e MSSQL_SA_PASSWORD=hUntEr202 -p 127.0.0.1:21433:1433 -d mcr.microsoft.com/azure-sql-edge
1> select @@VERSION;
2> go

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Microsoft Azure SQL Edge Developer (RTM) - 15.0.2000.1559 (ARM64)
	Jun  8 2021 15:48:33
	Copyright (C) 2019 Microsoft Corporation
	Linux (Ubuntu 18.04.5 LTS aarch64) <ARM64>

but this issue also occurs when running SQL Server on a remote machine with x86_64:

> select @@VERSION;
[row 0]
: "Microsoft SQL Server 2019 (RTM-CU10) (KB5001090) - 15.0.4123.1 (X64) \n\tMar 22 2021 18:10:24 \n\tCopyright (C) 2019 Microsoft Corporation\n\tDeveloper Edition (64-bit) on Linux (Ubuntu 20.04.2 LTS) <X64>"

I've cloned the fpco/odbc repo and built with cabal and ghc-8.10.7, then ran the tests:

ODBC_TEST_CONNECTION_STRING='DRIVER={ODBC Driver 17 for SQL Server};SERVER=127.0.0.1,21433;Uid=sa;Pwd=hUntEr202;Encrypt=no' cabal v2-run tests

Result: 97 examples, 1 failure:

Failures:

  test/Main.hs:198:3:
  1) Database.ODBC.Internal, Data retrieval, Basic santiy check
       uncaught exception: ODBCException
       UnsuccessfulReturnCode "getSize" (-1) "[unixODBC][Driver Manager]Program type out of range[unixODBC][Driver Manager]Program type out of range"

I've tried to run this test repeatedly by changing the failing test in tests/Main.hs from:

  it "Basic santiy check"

to:

  forM_ [1..100] $ \i -> describe "Basic sanity check" $ it (show (i :: Int))

And ran it again:

ODBC_TEST_CONNECTION_STRING='DRIVER={ODBC Driver 17 for SQL Server};SERVER=127.0.0.1,21433;Uid=sa;Pwd=hUntEr202;Encrypt=no' cabal v2-run tests -- --match "Basic sanity"

And the failing test failed exactly 21 times and then started passing. This behaviour is consistent when running the test many times:

100 examples, 21 failures

I can replicate similar behaviour when running cabal v2-run odbc and running the test manually. If we are a bit persistent we can get the expected results:

% cabal v2-run odbc -- 'DRIVER={ODBC Driver 17 for SQL Server};SERVER=127.0.0.1,21433;Uid=sa;Pwd=hUntEr202;Encrypt=no'
> DROP TABLE IF EXISTS test;
Rows: 0
> CREATE TABLE test (int integer, text text, bool bit, nt ntext, fl float);
Rows: 0
> INSERT INTO test VALUES (123, 'abc', 1, 'wib', 2.415), (456, 'def', 0, 'wibble',0.9999999999999), (NULL, NULL, NULL, NULL, NULL);
Rows: 0
> SELECT * FROM test;
UnsuccessfulReturnCode "getSize" (-1) "[unixODBC][Driver Manager]Program type out of range[unixODBC][Driver Manager]Program type out of range["
> SELECT * FROM test;
UnsuccessfulReturnCode "getSize" (-1) "[unixODBC][Driver Manager]Program type out of range[unixODBC][Driver Manager]Program type out of range"
> SELECT * FROM test;
[row 0]
int: 123
text: "abc"
bool: True
nt: "wib"
fl: 2.415

[row 1]
int: 456
text: "def"
bool: False
nt: "wibble"
fl: 0.9999999999999

[row 2]
int: NULL
text: NULL
bool: NULL
nt: NULL
fl: NULL

Rows: 3
@soupi
Copy link
Author

soupi commented Nov 22, 2021

Interestingly, replacing this line:

with (traceShowId column) (and adding import Debug.Trace) makes the test suite pass on my machine...

I tried adding force -> column instead, and even (print column *> odbc_SQLGetData instead of:

(odbc_SQLGetData

but only (traceShowId column) seemed to worked 🤔

@soupi
Copy link
Author

soupi commented Nov 23, 2021

I've tried printing the input I get in this function:

odbc/cbits/odbc.c

Lines 222 to 232 in d5fb33a

RETCODE odbc_SQLGetData(EnvAndDbc *envAndDbc,
SQLHSTMT *hstmt,
SQLUSMALLINT col,
SQLSMALLINT targetType,
SQLPOINTER buffer,
SQLLEN bufferLen,
SQLLEN * resultLen){
RETCODE r = SQLGetData(*hstmt, col, targetType, buffer, bufferLen, resultLen);
if (r == SQL_ERROR) odbc_ProcessLogMessages(envAndDbc, SQL_HANDLE_STMT, *hstmt, "odbc_SQLGetData", FALSE);
return r;
}

I added printf("%d\n", targetType); before the SQLGetData call.

For some reason, when I try to select a text column (for which targetType is sql_binary = (-2)) for the first time when running select text from test the printed value is 65534 (which is the same representation as -2 but unsigned using Two's complement IIRC).
This might be related to the warning emitted by clang when compiling odbc:

/var/folders/4p/vsznhmbx6p15bndr9g1fwv3m0000gn/T/ghc3543_0/ghc_1.s:354:2: error:
     warning: instruction movi.2d with immediate #0 may not function correctly on this CPU, converting to equivalent movi.16b
            movi.2d v0, #0000000000000000
            ^
    |
354 |         movi.2d v0, #0000000000000000
    |  ^

What I tried doing is pass (ty - 1) instead of ty for calls to odbc_SQLGetData and then in the C code of odbc_SQLGetData add ty++; before calling SQLGetData. It seems to make the test-suite pass.

This might be a GHC bug, I'm not sure. But this workaround works for me for now.

@soupi
Copy link
Author

soupi commented Nov 24, 2021

Opened a ghc bug for this https://gitlab.haskell.org/ghc/ghc/-/issues/20735

@chrisdone
Copy link
Contributor

Very good sleuthing! Good catch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants