on 2018 Sep 05 7:00 AM
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?
User | Count |
---|---|
69 | |
11 | |
10 | |
10 | |
9 | |
7 | |
7 | |
7 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.