String Truncation on Transfer to ClientDataset - delphi

I'm using Firebird 2.1, DBExpress Driver from DevArt and Delphi 2010. Some of my reports that used to work with Delphi 2006 stopped working and produced an error message indicating that "arithmetic exception, numeric overflow, or string truncation" had occurred. The error occurred at this point in my code:
cds.Data := dsProvider.Data;
I found the place in my SQL statement that caused the error:
iif(ytd.hPayType <> -1,t.sCode, 'NET') sPayType
T.sCode is a Varchar(10) field. My conclusion is that the query returns data to the dsProvider and that when the dsProvider.Data is passed to the cds.Data, the cds component sets the field width based on the first value it receives. I get the same error message if I change the "iif" to a CASE statement. I managed to work around the issue by doing this:
CAST(iif(ytd.hPayType <> -1,t.sCode, 'NET') AS varchar(10)) sPayType
Since this used to work in Delphi 2006 without the CAST, I assume that the new behavior is due to an update to the TClientDataset. It would be nice to have the old, more forgiving behavior. Is there a way to configure the ClientDataset to accept this without a complaint or do I need to just tell my users to CAST on string results based on iif and CASE statements?

I used to work a lot with firebird in my last job, this error happens when you already have a large (length) varchar field value stored in the db and you are trying to "get" the string in delphi, try updating the value in the db to a smaller (length) varchar. I'm not sure if will work for you but give it a try.

Well, with a little more experience, it looks like I am seeing this truncation error show up consistently with the Delphi 2010 version of ClientDatasets. If I find a resolution that does not involve having to use CAST in the query, I will post it here. But for now, I am going to close this posting.

Related

Firedac Empty Result Set

I am sure that I'm overlooking some simple thing here.
With a FireDac connection, if I use a SQL query with a WHERE clause that, due to the content of the search parameter, would normally return an empty result set, the OPEN command returns an error instead "Cannot open / define command, which does not return result sets". Is this by design ? Every other Delphi DB connection tool I have used simply returns an empty result set with a record count of 0.
******************************* April 16
I believe Victoria is on the right track. I had never used Firedac before so assumed it was the behaviour as designed. However if I communicate with the same RDBMS using the MS SQL driver, I do not see this happen, so I suspect it is on the Datasnap end.

How do I return a result parameter from a Sybase 16 database using FireDAC?

I'm updating an ancient codebase written in Delphi 7 using ODBC Express for database connectivity to Delphi Seattle 10 using FireDAC. Currently, ODBC Express OEDataset components are pointed at stored procs and defined with params at design-time, including an #Result param populated from the "Return" function of the Sybase SPs.
If I attempt a simple swap (with minimal adjustment) for FireDAC's TFDStoredProc component (defining params at design-time), I get an "invalid parameter type" error when I include the #Result parameter (DataType=ftInteger, ParamType=ptResult). Without the #Result parameter, the stored procedure executes fine, but then I can't access the "Return" value.
I've mucked about with ResourceOptions.UnifyParams, FetchItems.Items := [fiMeta], ExecFunc instead of ExecProc, leaving out the #Result param, etc etc.
I'm sure I'm missing something very obvious, but I've been banging my head on my desk for a day trying to figure this out. Does anybody have any advice?
As weird as it seems, the issue is simply that the ptResult parameter was added as the last parameter in the list (which is how it was done using ODBC Express). Moving the #Result param to the first position, and only the first position, fixes the issue. Now I'm going to have to scour the documentation to see where I missed that little tidbit...

SSRS is assuming the wrong column datatype

I have an SSRS report that's being built from a stored procedure given 2 variables. The error I'm receiving is
An error has occurred during report processing. (rsProcessingAborted)
Cannot read the next data row for the dataset Sheet2. (rsErrorReadingNextDataRow)
Conversion failed when converting the varchar value '.5' to data type int.
This doesn't make any sense. The variable in question is being stored as a varchar. I don't do any typecasting in the stored procedure. Executing the stored proc in sql server studio works fine. In the query designer I replaced the stored procedure call with just the code for the stored procedure and it works fine as well. Switching it back to call the stored procedure throws the same error.
Why is SSRS trying to convert a varchar to an int? It should be a double if anything or just leave it alone and not try typecasting it at all.
I looked into the technical details when I ran it in the query designer and found the error was originating from the stored procedure and not involving SSRS at all. When I tested the stored proc the first time I tested the production version and not the development version. The development stored proc I use to test reports in VS and the database that houses this stored proc is the development database. The dev server obviously also uses the dev database version as well.
For some reason this line of code breaks it
CASE WHEN TN_UNPLATED_BLANK.CN_ZZ_ANGLE_TOL_MINUTES = '-32767' THEN -999999
ELSE TN_UNPLATED_BLANK.CN_ZZ_ANGLE_TOL_MINUTES END AS CN_ZZ_ANGLE_TOL_MINUTES,
Changing it to this fixes it
CASE WHEN TN_UNPLATED_BLANK.CN_ZZ_ANGLE_TOL_MINUTES = '-32767' THEN NULL
ELSE TN_UNPLATED_BLANK.CN_ZZ_ANGLE_TOL_MINUTES END AS CN_ZZ_ANGLE_TOL_MINUTES,
It's as if the return type of the else portion forced the string '-32767' to convert to an int and then forcing the .5 to typecast to an int causing the error to be thrown.

Complex T-SQL script executed via TADOQuery is firing "Multiple-step OLE DB operation generated errors."

I have a very large block of SQL that I am trying to execute inside of Delphi, against a Microsoft SQL Database. I am getting this:
Multiple-step OLE DB operation generated errors.
Check each OLE DB status value, if available. No work was done.
The script has multiple sql IF statements followed by BEGIN and END blocks with invocations of stored procedures, declaration of variables, and EXEC inside that. Finally it returns some of the variable values by SELECT #Variable1 AsName1,#Variable2 AsName2....
The above multi-step error is coming in as an OLEException from ADO, not from the Delphi code, and happens after all the SQL exec-stored-procedure have occurred, and therefore I suspect it's firing this OLE exception when it reaches the final stage which SELECT #Variable1 AsName1,... to get back a few variable values for my program to see them.
I know about this retired/deprecated MS KB article, and this is unfortunately not my actual issue:
http://support.microsoft.com/kb/269495
In short that KB article says to fix a registry key and remove "Persist Security Info" from the connection string. That's not my problem. I'm asking this question because I found the answer already and I think that someone else who gets stuck here might not want to waste several hours finding potential issues when there are several that I have found after searching for solutions for several hours. Anyone who wants to add another answer with different options, is fine, and I'll select yours if it's reproducible, and if necessary I'll turn this one into a Community Wiki because there could be a dozen obscure causes for this "ADO recordset is in a bad mood and is unhappy with your T-SQL" exception.
I have found several potential causes that are listed in various sources of documentation. The original KB article in the question suggests removing the 'Persist Security Info' from my ADO connection string, however in a standalone test in an application with just a TADOConnection and a single TADOQuery, the presence or absence of Persist Security Info had no effect, nor did explicitly setting it True or False.
What DID fix it was removing this CursorType declaration:
CursorType=ctKeyset
What I have learned is that bidirectional ADO datasets are fine for SELECT * FROM TABLE in ADO but are not so fine for complex SQL scripts.
Potential source of this error is updating char field with large value.
Example: Form has edit box with max length property set to 20 characters and Oracle database table has field defined as char(10).
Updating with 10 characters (or less) will work fine while updating with more then 10 characters will cause 'Multiple step...' error on ADOQuerry.UpdateBatch().
You also have to know that CHAR will allways have 20 characters. Consider Trimming value in edit box. CHAR behaves different than VARCHAR2 type.
If you have a query with parameter ,check the number of parameters in the query is matched with script...!

Missing Field Errors In TClientDataSet when external dll called from Delphi 7

I have a DLL created in Delphi XE2 that is using DB Express and TClientDataSet to display the results of a join in a DB Grid. There is a simple function to launch/show the form that is exported for use in other applications. The query is executed, and the grid populated, on FormActivate.
When I call the function to show the form from a separate Delphi XE2 application, everything runs fine - no issues that I can find.
However, when I call the same function from a separate Delphi 7 application, I get an error that that TClientDataSet can't find fields from the join.
For Example, data is returned like this:
[dbxds == TSQLDataSet
cds == TClientDataSet]
dbxds.commandtext='select s.sfield1, s.sfield2, t.tfield1, t.tfield2 from s left join t on s.sfield1 = t.tfield1';
cds.Open;
cds.fieldByName(sfield2).visible:=false;//to hide from a dbgrid
cds.fieldByName(tfield2).visible:=false;//to hide from a dbgrid
When called from XE2, no issues.
When called from Delphi 7, the last line (used to hide that field from the db grid) gives an error that:
cds: Field 'tfield2' not found
Though the first line is fine - if I switch the order of the query so that that 't' fields are retrieved first ('from t left join s'), then I get the error on the 's' field instead.
Any thoughts on what could be causing the incompatibility?
Thanks!
OK so, I noticed something odd and that put me on the path to getting the answer to this.
It just happened that, in either table, the field I was trying to access to hide was of type 'tinyint(1)'. If I tried to hide a field of type int/varchar etc, no error was thrown.
I swapped my 'tinyint(1)' fields for 'int(1)' and it works fine.
No idea why this was happening, but I'm glad I caught it and, if any one else runs into this issue, I hope that this answers their question for them too.

Resources