Delphi TadoQuery - Parameter type conversion - delphi

I send with Jquery and Ajax Parameters from the Webpage to my Delphi Webserver. Those Parameters will be used in the select, but as soon as i get to TADOQ.Open; i get a exception which contains the message bellow the code section.
I'm new to Delphi, so it's not easy for me to understand how to work with UnicodeString, AnsiString and String. Also i don't understand why it says double, when i don't use it anywhere.
Is there a simple way to fix the Problem? (Small Code and easy to unterstand)
EDIT: Added Process before calling SearchChosen();
KoyoWebSqlReader:=CKoyoWebSqlReader.Create;
KoyoWebSqlReader.OpenConnection;
Response.ContentType:='application/json';
Txt:=KoyoWebSqlReader.SearchChosen(
StrToInt(SplitString(Request.ContentFields[0], '=')[1]),
StrToDateTime(SplitString(Request.ContentFields[1], '=')[1])
).toJsonString;
Response.Content:=Txt;
KoyoWebSqlReader.CloseConnection;
// -----
function CKoyoWebSqlReader.SearchChosen(TicketNumber:Integer; Start:TDateTime):CKoyoMeasurement;
var Search:TADOQuery;
var Measurement:CKoyoMeasurement;
begin
Measurement:=CKoyoMeasurement.Create;
Search:=TADOQuery.Create(nil);
Search.Connection:=Connection;
Search.SQL.Clear;
Search.SQL.Text:=
'SELECT * FROM Measurements WHERE TicketNumber = :TicketNumber AND Start = :Start;';
Search.Parameters.ParamByName('TicketNumber').Value:=TicketNumber;
Search.Parameters.ParamByName('Start').Value:=Start;
try
Search.Open;
// Fill Measurement
except on EX:Exception do
begin
// Log Exception
end;
end;
Search.Close;
Result:=Measurement;
end;
Variant of Type (UnicodeString) could not be converted into (Double)

Related

Delphi 7 to XE8 assigning binary ADO parameter values

I'm converting a report that resides in a DLL to XE8 so that I can update our report control, which is problematic in Windows 10. In doing this, I've had to replace our ADO data access controls with the built-in ADO controls.
The issues is that our data uses binary keys, and I've run into an issue assigning values to query parameters. In our code, the keys are passed around as strings, and assigned to the parameters and converted by the control at runtime.
Previously, utilizing the old control, it utilized the Delphi DB unit which contains a method .AsBlob which was used in the assignment. See below...
Qry.Close;
Qry.ParamByName('#Id').AsBlob := IdStringValue;
Qry.Open;
In the control's implementation it handled setting the property, which called into SetAsBlob. See below...
Type TBlobData = string;
...
procedure TQryParameter.SetAsBlob(const Value: TBlobData);
begin
Self.DataType := ftVarBytes;
Self.Value := StringToVarArray(Value);
end;
Part of the issue is that Data.DB has changed TBlobData = string; to TBlobData = TArray<Byte>;.
I've tried assigning these values to the query parameters following the same method used in the previous implementation, but it doesn't work.
Qry.Close;
Qry.Parameters.ParamByName('#Id').DataType := ftVarBytes;
Qry.Parameters.ParamByName('#Id').Value := ADODB.StringToVarArray(IdStringValue);
Qry.Open;
I get a fairly generic MSSQL error due to the parameter mismatch, "Application uses a value of the wrong type for the current operation."
The ADO query parameter is defined as VarBytes and the stored procedure accepts BINARY(6) for its only parameter so everything appears to be correct.
I've tried casting IdStringValue from String to AnsiString prior to calling StringToVarArray but it makes no difference.
Anyone know of a way to deal with this? Thank you.
Convert the string value to array of bytes when assigning the parameter.
Qry.Parameters.ParamByName('#Id').AsBlob := TEncoding.Default.GetBytes(StringValue);

Debugging TValue containing a string

I'm having trouble to inspect the string value of a TValue variable while debugging. The hover menu doesn't show the string value and even adding it to the watch list seems tricky.
Given a very basic sample console application, like
program Project1;
uses
System.SysUtils, System.Rtti;
var
Value: TValue;
begin
Value := 'Hello';
WriteLn(Value.AsType<string>);
ReadLn;
end.
Adding a breakpoint to the WriteLn line, I can hover over the Value variable and see the value type, but there isn't really any information on the string value, see
Next thing I tried was adding it to the watch list, using .AsType<string> - however watchlist errors - Internal Error in the sample application, E2531 (method requires explicit type arguments) in my real application. It made no difference to check/uncheck the option to allow side effects and functions
.
What finally worked was creating a function for the conversion, e.g.
function ValueToString(const Value: TValue): string;
begin
Result := Value.AsType<string>;
end;
and using this in the watchlist. I had to use this function in aplication code though (e.g. in the WriteLn call in the sample) to avoid it being removed by the linker. This also means that I'll have to add this funtion or a unit containing this function to every unit I want to debug.
Is there a better solution?
Using TValue's built-in Value.ToString works in a watch. Value.AsString also evaluates.
You can use Value.AsVariant, as well.

COM Exception "Bad Variable Type" Error in Delphi Call of Domino GetDocumentByKey Method

I have a legacy Delphi 2 application that I need to convert from communicating with Notes via OLE Automation to communicating via COM early binding. I am using Delphi 7 since the code base is large and I want to avoid the work of dealing with the Unicode support in the more current versions of Delphi.
The basics are working: the program opens the database then the view and searches for a particular document using the NotesView.GetDocumentByKey method. The GetDocumentByKey call works when the first parameter is a single string cast to an OleVariant as shown below (opening of DB and view not shown).
var
Key: OleVariant;
const ExactMatch: WordBool = True;
begin
Key := 'AKeyValue';
Doc := View.GetDocumentByKey(Key, ExactMatch);
The bad variable type error occurs when the first parameter is a variant array as required when it is desired to search the view based on multiple columns as shown below.
var
TwoKeysV: OleVariant;
const ExactMatch: WordBool = True;
begin
TwoKeysV := VarArrayCreate([0, 1], varOleStr);
TwoKeysV[0]:= WideString('Key1');
TwoKeysV[1]:= WideString('Key2');
Doc := View.GetDocumentByKey(TwoKeysV, ExactMatch);
I have tried several variations on the two key assignment statements with no success. For example, just assigning the key string without a cast still produces the bad variable type, and using the StringToOleString function is rejected by the compiler as an invalid assignment (PWideChar to Variant).
I can't test this, so I'm not sure this works.
HELP: If this method is used under COM, with a keyArray parameter of an array, it must be defined as an array of type Variant
So you need to pass: an array of type Variant
Based on How to use variant arrays in Delphi.
Note: Code edited by Keeloid to match code that worked by casting key string to WideString.
var
TwoKeysV: OleVariant;
const ExactMatch: WordBool = True;
begin
TwoKeysV := VarArrayCreate([0, 1], varVariant);
TwoKeysV[0]:= WideString('Key1'); {WideString = varOleStr}
TwoKeysV[1]:= WideString('Key2');
Doc := View.GetDocumentByKey(TwoKeysV, ExactMatch);

Why are certain Delphi SOAP RTL OpConvert.pas methods deprecated if they use a String instead of a Stream as their XML document type?

I have a warning in my code that I can't figure out how to remove. The method is a utility method that is invoking THTTPRIO's FConverter field's IOPConvert.ProcessResponse method.
There are several overloaded versions of ProcessResponse in IOPConvert, and the one that is declared with parameter type InvString as the first parameter is the deprecated one.
Throughout the Delphi SOAP RTL, the trend has been away from String types and towards stream types, since Delphi 7, up to now (Delphi XE/XE2).
The question is WHY? In this case I can't even figure out how to convert my helper code unless I add an ugly string-stream wrapper:
TRIOHelper = class helper for THTTPRIO
public
function HelperMethod(aMethName: String; aSoapString: String) : TRemotable;
end;
function TRIOHelper.HelperMethod(aMethName, aSoapString: String): TRemotable;
var
tmpString:String;
begin
//FConverter is a field in THTTPRIO
tmpStr := GrievousXmlHackery(aSoapString);
FConverter.ProcessResponse(InvString(tmpStr), IntfMD, MethMD, FContext);
...
end;
The code above the deprecated call is tweaking an XML document (the SOAP response) and removing some problematic elements from the incoming stream. Yes, a hack. How should I change it,and why are strings bad in OpConvert?
I guess I need to make a String Stream or Memory Stream wrapper for tmpString? Note that in my case, the GrievousXmlHackery function removes the <encoding> tag when present, from the SOAP for evil reasons that remain unimportant here.
Unless there is something actually technically WRONG with the old methods and the string based apis, I'm going to put up with the warning. But if (like many places in the VCL), the deprecated warning also means "here be dragons", I'd like to know about it.
I'm not familiar with Delphi's SOAP implementation, but why can't you just use a TStringStream instead?
function TRIOHelper.HelperMethod(aMethName, aSoapString: String): TRemotable;
var
Strm: TStringStream;
begin
//FConverter is a field in THTTPRIO
Strm := TStringStream.Create(GrievousXmlHackery(aSoapString));
// or
// Strm := TStringStream.Create('');
// Strm.DataString := GreviousXmlHackery(aSoapString);
FConverter.ProcessResponse(Strm, IntfMD, MethMD, FContext);
// Not sure if you or THTTPRIO is responsible for releasing the stream
...
end;

getting "E2197 Constant object cannot be passed as var parameter" when passing var parameter

this code works fine:
procedure TForm2.Timer1Timer(Sender: TObject);
var
Text: string;
begin SetLength (Text,555);
GetWindowText (getforegroundwindow, PChar (Text),555);
Form2.gtListBox1.Items.Add (
IntToStr (getforegroundwindow) + ': ' + Text);
end;
but when i put
var
Text: string;
from Timer1Timer event handler to
units implementation section or ''text : string'' in the units var section i get error : E2197 Constant object cannot be passed as var parameter
according to documentation :
This error message appears when you
try to send a constant as a var or out
parameter for a function or procedure.
but i didnt declared text as constant then why am i getting this error?
Edit:#mason wheeler: i do not understand than why does this work:
implementation
{$R *.dfm}
var
char :integer;//first of all why does delphi let me declare variable that is also a type name
procedure TForm2.Button1Click(Sender: TObject);
begin
char:=11;
showmessage(IntToStr(char));
end;
my first code was not working because i declared text as string ,you say : ''the compiler might think it's a reference to the type and not to the variable'' than why doesnt the compiler think its a reference to the type and not to the variable in this case? i am confused
Edit2: i now understand what was wrong but still have 1 confusion i did'nt use a with statement then why delphi is treating as if i am using:
with
form1 do
text := 'blahblahblah';
this is wrong on the delphi part i mean delphi should not let us do text := 'blah' but form1.text := blah; or with form1 do text := 'blah'; do i need to turn on/off some compiler setting(s) i am using delphi 2010 without any ide experts
Actually if you declare Text in implementation section and use it in Timer1Timer(Sender: TObject), compiler will consider Text as Form1.Text.
Change the name of text as sText and it will work.
Edit 1:
Because there is no property/Field for form like Form1.Char.
It's probably a name confusion. "Text" is a type name as well, a legacy textfile type. So if you declare the variable in a different scope, the compiler might think it's a reference to the type and not to the variable. Try naming it something else and it should work.
With regard to your Edit #2:
That's a standard convention of object-oriented programming. When you're writing a method for an object, the code is implicitly interpreted as being in the scope of the object. In other words, every object method can be considered as being inside a hidden with self do block.

Resources