I want to build a SELECT statement from the results of query within the Twicat3 PLC environment.
Query executes properly when variable is hard coded, but fails to execute when variable is passed from the results of another query. The defined datatypes are the same. Error in InformationLog View indicates "The given key was not present in the dictionary." when the query is executed using the results of the first query.
PROGRAM MAIN
VAR
conv_QueryDB : Query_tblConveyorQueue;
conv_queryRes : ARRAY [0..9] OF tblConveyorQueue;
conv_str_query : STRING(2000);
conv_query : WSTRING(2000);
conv_query1 : WSTRING(255) := "SELECT TOP 1 LEFT(AreaID,5) FROM ConveyorQueue WHERE CartonID = '";
conv_barcode : WSTRING(255) := "900981-1";
conv_query2 : WSTRING(255) := "' ORDER BY AreaID";
zone_QueryDB : Query_tblZoneMap;
zone_queryRes : ARRAY [0..18] OF tblZoneMap;
zone_str_query : STRING(2000);
zone_query : WSTRING(2000);
zone_query1 : WSTRING(255) := "SELECT transfer, zone, direction, neighborZone, deliveryLoc FROM tblZoneMap WHERE transfer = 1 AND zone = 0 AND deliveryLoc = '";
zone_dest : WSTRING(255);
zone_query2 : WSTRING(255) := "' ";
END_VAR
conv_query := WCONCAT(conv_query1, WCONCAT(conv_barcode, conv_query2));
conv_str_query := WSTRING_TO_STRING(conv_query);
conv_QueryDB(queryString := conv_str_query, dbConn := 2, bConnect := 1);
conv_queryRes := conv_QueryDB.queryResults;
zone_dest := STRING_TO_WSTRING(conv_queryRes[0].AreaID);
//zone_dest := "P1030"; //This works when uncommented??!!??
zone_query := WCONCAT(zone_query1, WCONCAT(zone_dest, zone_query2));
zone_str_query := WSTRING_TO_STRING(zone_query);
zone_QueryDB(queryString := zone_str_query, dbConn := 1, bConnect := 1);
zone_queryRes := zone_QueryDB.queryResults;
I would expect the zone_queryRes to be the same when executing zone_dest as a hard coded value vs. when it's extracted from the conv_queryRes array. I'm not sure if this is a datatype issue. When executed, the query strings appear to have the correct syntax.
--------------EDIT-----------------------------------------------------------------
Including SQL Function Block.
FUNCTION_BLOCK Query_tblZoneMap
VAR_INPUT
queryString : STRING(2000); //Select statement
dbConn : UDINT; //Int of connection configured in TF6420
bCONNECT : BOOL; //Rising trigger to connect to db. Need to make this re-fireable
END_VAR
VAR_OUTPUT
queryResults : ARRAY [0..18] OF tblZoneMap;
nError : INT;
END_VAR
VAR
fbSQLDatabase : FB_SQLDatabase(sNetID:='', tTimeout:=T#500MS);
fbSqlCommand : FB_SQLCommand(sNetID := '', tTimeout := T#500MS);
fbSQLResult : FB_SQLResult(sNetID:='', tTimeout:=T#500MS);
nState : INT;
R_TRIG1 : R_TRIG;
END_VAR
(*
Welcome to the QueryDB function block!
This function exists to query a database that is configured using the TF6420 Connectivity module.
When executed, it establishes a connection with the database, creates an instance of the FB_SQLCommand,
executes the instance of FB_SQLCommand, then reads the cached results using FB_SQLResult into the
queryResults array.
When results are received successfully, the database connection is closed.
*)
R_TRIG1(CLK:=bCONNECT);
IF R_TRIG1.Q AND nState = 0 THEN
nState := 1;
END_IF
CASE nState OF
0:(*Idle*)
IF bConnect THEN
bCONNECT := 0;
END_IF
1: // Connect to database
IF fbSqlDatabase.Connect(dbConn) THEN
IF fbSqlDatabase.bError THEN
nState := 255;
ELSE
nState := nState+1;
END_IF
END_IF
2: // Create a command reference
IF fbSqlDatabase.CreateCmd(ADR(fbSqlCommand)) THEN
IF fbSqlDatabase.bError THEN
nState := 255;
ELSE
nState := nState+1;
END_IF
END_IF
3://Execute SELECT Statement FB_SQLCommand.ExecuteDataReturn(pSQLCmd:= , cbSQLCmd:= , pSQLDBResult:= )
IF fbSQLCommand.ExecuteDataReturn(pSQLCmd:= ADR(queryString)
, cbSQLCmd:= SIZEOF(queryString)
, pSQLDBResult:= ADR(fbSqlResult)) THEN
IF fbSQLCommand.bError THEN
nState := 255;
ELSE
nState := nState + 1;
END_IF
END_IF
4://Read Results
IF fbSqlResult.Read(nStartIndex:= 0
,nRecordCount:= 19
,pData:= ADR(queryResults)
,cbData:= SIZEOF(queryResults)
,bWithVerifying:= FALSE
,bDataRelease:= FALSE) THEN
IF fbSqlResult.bError THEN
nState := 255;
ELSE
nState := nState+1;
END_IF
END_IF
5:// disconnect from database
IF fbSqlDatabase.Disconnect() THEN
IF fbSqlDatabase.bError THEN
nState := 255;
ELSE
nState := 0;
bConnect := 0;
END_IF
END_IF
255:
nError := 1; // If errored, check SQL logs.
bConnect := 0;
nState := 0;
END_CASE