cancel
Showing results for 
Search instead for 
Did you mean: 

Odbc driver issue with SQLA17

0 Kudos
2,287

Hi,

I have a client app using ODBC to connect to an SQLA17 database. The client calls a procedure that performs an INSERT on a table. There is one column on that table defined as UNIQUEIDENTIFIER. For that column, the client passes in a COALESCE('A NULL here', newid()) value.

The insert fails with an error: "Impossible to convert smallint to uniqueidentifier" However, the same call works in Interactive SQL.

This leads me to believe that in the ODBC driver (before getting to the INSERT) the Null that I pass is converted to a smallint with a default value, which causes the COALESCE('not a NULL anymore', newid()) to return a smallint value that is then converted to a uniqueidentifier, which explains the error.

Does this make sense? Is this a breaking change in the odbc driver for sa-17? (The same code works with sa-16)

Thanks


EDIT 1

So the client calls a procedure passing in a Null:

ALTER PROCEDURE PROC_NAME(
   ...
   IN _GLOBALID uniqueidentifier,
   ...etc...)
BEGIN
   INSERT INTO TABLE_NAME(...,GLOBALID_COL,...)
   VALUES(..., COALESCE(_GLOBALID,newid()),...)
END

The profiler says the client calls this proc with a Null. When the client calls it the exception is raised. When I call it from Interactive Sql, no exception.


EDIT 2

We are using SQL 19.0.9.4803

The error happens when the client calls the procedure (described previously).

When we comment the INSERT we still get the error:

ALTER PROCEDURE PROC_NAME(
   ...
   IN _GLOBALID uniqueidentifier,
   ...etc...)
BEGIN
--   INSERT INTO TABLE_NAME(...,GLOBALID_COL,...)
--   VALUES(..., COALESCE(_GLOBALID,newid()),...)
END

When we change the param type and keep the commented INSERT, we don't get the error:

ALTER PROCEDURE PROC_NAME(
    ...
    IN _GLOBALID unsigned smallint,
       ...etc...)
BEGIN
    --   INSERT INTO TABLE_NAME(...,GLOBALID_COL,...)
    --   VALUES(..., COALESCE(_GLOBALID,newid()),...)
END

When we uncomment the INSERT, we get the error:

ALTER PROCEDURE PROC_NAME(
   ...
   IN _GLOBALID unsigned smallint,
   ...etc...)
BEGIN
   INSERT INTO TABLE_NAME(...,GLOBALID_COL,...)
   VALUES(..., COALESCE(_GLOBALID,newid()),...)
END

EDIT 3

Below a trace from the client calling the procedure on a dbsrv16 with a DB supporting ver 16:

=,>,1,OPEN,131184 +6,<,1,PREPARE,call "INSERT_LIGNE_OFFRE"(:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?) =,>,1,PREPARE,458865 +7,<,1,EXEC,458865 =,H,1,,integer,25511
=,H,1,,integer,832773
=,H,1,,integer,832773
=,H,1,,varchar,'0'
=,H,1,,varchar,'1'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,any,<null>
=,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'1'
=,H,1,,varchar,'0'
=,H,1,,integer,130
=,H,1,,any,<null>
=,H,1,,integer,0
=,H,1,,varchar,'{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1036{\\fonttbl{\\f0\\fnil\\fcharset0 MS Shell Dlg;}} \\viewkind4\\uc1\\pard\\f0\\fs17 Composant\\par } '
=,H,1,,varchar,'<modele><pos>Composant</pos><easycom>6200</easycom><complement>0,00</complement><remplacement>0,00</remplacement></modele>'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
+1,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,varchar,'0'
=,H,1,,any,<null>
=,H,1,,varchar,'Sous-total'
=,H,1,,any,<null>
=,H,1,,any,<null>
=,H,1,,any,<null>
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,any,<null>
=,H,1,,integer,0
=,H,1,,integer,0
=,H,1,,integer,0
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,any,<null>
=,H,1,,varchar,''
=,H,1,,integer,4600
+79,>,1,EXEC =,<,1,COMMIT

You can see the parameter in question in bold. The type that is seen in the trace is ANY

Now for the same test using the same client but with a dbsrv17 and a DB supporting ver 17:

=,>,1,OPEN,65546 +7,<,1,PREPARE,call "INSERT_LIGNE_OFFRE"(:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?,:?) =,>,1,PREPARE,131083 +4,<,1,EXEC,131083 +2,H,1,,integer,85911
=,H,1,,integer,525129
=,H,1,,integer,525129
=,H,1,,varchar,'0'
+1,H,1,,varchar,'1'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,smallint,<null>
=,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'1'
=,H,1,,varchar,'0'
=,H,1,,integer,130
=,H,1,,smallint,<null>
=,H,1,,integer,0
=,H,1,,varchar,'{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1036{\\fonttbl{\\f0\\fnil\\fcharset0 MS Shell Dlg;}} \\viewkind4\\uc1\\pard\\f0\\fs17 Poste\\par } '
=,H,1,,varchar,'<modele><pos>Poste</pos><easycom>6200</easycom><complement>0,00</complement><remplacement>0,00</remplacement></modele>'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
+1,H,1,,varchar,'0'
=,H,1,,integer,0
=,H,1,,varchar,'0'
=,H,1,,smallint,<null>
=,H,1,,varchar,'Sous-Total Poste'
=,H,1,,smallint,<null>
=,H,1,,smallint,<null>
=,H,1,,smallint,<null>
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,smallint,<null>
=,H,1,,integer,0
=,H,1,,integer,0
=,H,1,,integer,0
+1,H,1,,varchar,'0'
=,H,1,,varchar,'0'
=,H,1,,smallint,<null>
=,H,1,,varchar,''
=,H,1,,integer,4600
=,E,1,-157,Impossible de convertir smallint en uniqueidentifier =,>,1,EXEC +4,<,1,ROLLBACK

This time, the type that is seen in the trace is SMALLINT


EDIT 4

Below the source code:

SELF:Fill({
oLd:IDDOCUMENT,
oLd:IDLIGNE,
oLd:ORDRE,
oLd:TAUX_REMISE,
oLd:QUANTITE,
oLd:PRIX_VENTE,
oLd:ALTERNATIVE,
oLd:IDPOSTE,
AsNull(oLd:DLIVRAISON),
oLd:SAUT_PAGE,
oLd:BLANK_NB,;
oLd:LENTETE,
oLd:LPIED,
oLd:LIMAGE,
oLd:LDETAIL,
oLd:ECOTAXE_MONTANT,
oLd:TYPELIGNE,
AsNull(oLd:IdFournisseur),
oLd:IDTVA,
oLd:DESIGNATION,
oLd:MODELE_INFO,
oLd:PRIX_CATALOGUE,;
oLd:PRIX_UNITAIRE,
oLd:ACHAT,
oLd:NEGO,
oLd:IDUNITE,
oLd:PRIX_CATALOGUE_DEVISE,
AsNull(oLd:IDMONNAIE),
AsNull(oLd:TRANSMISSION),
AsNull(oLd:LIVRAISON),
AsNull(oLd:FACTURATION),;
AsNull(oLd:CODE_ACCORD),
oLd:TAUX_REMISE_ACHAT,
oLd:LAUTOPRICING,
oLd:lEXPRESS,
oLd:POIDS,
oLd:VOLUME,
oLd:POIDS_LOGISTIQUE,
oLd:VOLUME_LOGISTIQUE,
AsNull(oLd:CODE_SH),;
oLd:IDGRILLE,
oLd:IDCATEGORIE,
oLd:IDFONCTION,
oLd:ECOTAXE_TAUX,
oLd:ECO_CONCEPTION,

AsNull(oLd:GLOBALID),

oLd:EXTERNALID,
iif(!Empty(oLd:TYPE_ARTICLE),oLd:TYPE_ARTICLE,ARTICLE_NON_DEF)})

The relevant part above in bold.

Notice how the oLd:GLOBALID value is passed to the AsNull method, defined below:

FUNCTION AsNull(uParam AS USUAL) AS USUAL PASCAL 
RETURN IIF(Empty(uParam),NIL,uParam)

This method checks if the input param is empty and returns either NIL, or the data passed in. In this case, we get a USUAL Nil, which is the VB Variant equivalent of Visual Objects.

So, as per EDIT 3, we can now see that the USUAL Nil is translated to any when run on a dbsrv16 and to smallint when run on a dbsrv17. Why do you think this happens?

Accepted Solutions (0)

Answers (0)