gmslSamples
- Mark Juras
Owned by Mark Juras
Sample Applications of gmSL
This section contains samples of gmSL applications.Migration of VB6 RDO code to ADO.NET
The original request from the user was "Our VB6 code is in the following pretty standard pattern:"Dim SQL As String Dim SP As rdoQuery Dim Results As rdoResultset SQL = "select * from departments where category_id = ?" Set SP = MainForm.EnablerRDOCN.CreateQuery("QueryDept", SQL) SP.rdoParameters(0).value = CategoryID; Set Results = SP.OpenResultset(rdOpenForwardOnly) While Not Results.EOF DeptID = Results.rdoColumns("department_id").value Results.MoveNext Wend SP.Close
string SQL = "select * from departments order by department_id"; DbCommand SP = DatabaseConnection().CreateCommand(); SP.CommandText = SQL; SP.Parameters[0].Value = CategoryID; using (DbDataReader Results = SP.ExecuteReader()) { while(Results.Read()) { DeptID = Convert.ToInt32(Results["department_id"]); } }
An example code was created
An example VB6 code was created that uses the external library "MSRDO20.DLL#Microsoft Remote Data Object 2.0". Some time was spent to make it a real working example using the .NET class "System.Data.SqlClient", that could passed on to show how gmBasic is able to perform these types of code transformations. The two specific VB6 methods to be transformed are as follows.Public Sub connectDB() Set conn = New rdoConnection Dim dbs As String _ dbs = _ "UID=stocks_login;PWD=password;Database=stocks;" _ & "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" _ & "DSN='';" conn.Connect = dbs conn.EstablishConnection End Sub Public Sub execQuery() Dim SQL As String Dim SP As rdoQuery Dim Results As rdoResultset Dim f As String SQL = "select * from accounts where accountID < ? and FirstName like ?" Set SP = conn.CreateQuery("QueryAcct", SQL) SP.rdoParameters(0).Value = "5005" SP.rdoParameters(1).Value = "Test%" Set Results = SP.OpenResultset(rdOpenForwardOnly) While Not Results.EOF f = Results.rdoColumns("FirstName").Value writeLog f f = Results.rdoColumns("eMail").Value writeLog f Results.MoveNext Wend SP.Close End Sub
public static void connectDB() { conn = new System.Data.SqlClient.SqlConnection(); string dbs = ""; dbs = "UID=stocks_login;PWD=password;Database=stocks;Server=GMI-CS-01.gmi.local;"; conn.ConnectionString = dbs; conn.Open(); } public static void execQuery() { string SQL = ""; System.Data.SqlClient.SqlCommand SP = null; string f = ""; SQL = "select * from accounts where accountID < @0 and FirstName like @1"; (SP = conn.CreateCommand()).CommandText = SQL; SP.Parameters.Add(new System.Data.SqlClient.SqlParameter("@0", null)).Value = "5005"; SP.Parameters.Add(new System.Data.SqlClient.SqlParameter("@1", null)).Value = "Test%"; using (System.Data.SqlClient.SqlDataReader Results = SP.ExecuteReader()) { while (Results.Read()) { f = Results["FirstName"].ToStr(); writeLog(f); f = Results["eMail"].ToStr(); writeLog(f); } } }
The unmigrated translation
Using the reference script for MSRDO20.Dll exactly as produced by the gmBasic IDL translator and the following very simple gmSL based translation script<gmBasic> <gmSL> Execute.Storage Action:="Create", Identifier:="\gmManual\Samples\RDOtoNet\csh\RDOToNet_std" Select.DevEnv = "VS2013" Select.Dialect = Dialects.csh Select.BuildFile = BuildFileStatus.On Select.System = "\gmManual\Samples\FromIdl" Select.Target = "\gmManual\Samples\FromIdl" Select.DeployLocation = "\Temp" Execute.Compile Project:="\gmManual\Samples\RDOtoNet\src\RDOToNET.vbp" Execute.Analyse Execute.Output Status:="New", Filename:="\gmManual\Samples\RDOtoNet\csh\RDOToNet_std.bnd" Execute.Author Execute.Storage Action:="Close" </gmSL> </gmBasic>
public static void connectDB() { conn = new RDO.rdoConnection(); string dbs = ""; dbs = "UID=stocks_login;PWD=password;Database=stocks;" + "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" + "DSN='';"; conn.Connect = dbs; conn.EstablishConnection(null,null,null); } public static void execQuery() { string SQL = ""; RDO.rdoQuery SP = null; RDO.rdoResultset Results = null; string f = ""; SQL = "select * from accounts where accountID < ? and FirstName like ?"; SP = conn.CreateQuery("QueryAcct",SQL); SP.rdoParameters[0].Value = "5005"; SP.rdoParameters[1].Value = "Test%"; Results = SP.OpenResultset(RDO.ResultsetTypeConstants.rdOpenForwardOnly,null,null); while (!Results.EOF) { f = Results.rdoColumns["FirstName"].Value.ToStr(); writeLog(f); f = Results.rdoColumns["eMail"].Value.ToStr(); writeLog(f); Results.MoveNext(); } SP.Close(); }
Adding a few migration names
The first step in any migration is to add migration names, using gmPL, to reflect any simple name changes that need to be done. The reader is assumed to be familiar with the gmPL component refactoring attributes -- in this case migName and migPattern. Doing this takes a lot of noise out of the differences between the migrated and unmigrated translations. In this case, they are as summarized here.<library id="MSRDO20.DLL" name="RDO" migName="System.Data.SqlClient" .. > <class id="_rdoConnection" ..> <property id="Connect" type="String" status="InOut" migName="ConnectionString" /> <method id="EstablishConnection" type="Void" migPattern="%1d.Open()\c"> <method id="CreateQuery" type="rdoQuery" migName="CreateCommand"> ... <class id="rdoPreparedStatement" <property id="rdoParameters" type="rdoParameters" status="Out" migName="Parameters" /> <method id="OpenResultset" type="rdoResultset" migPattern="%1d.ExecuteReader()" > ... <coclass id="rdoConnection" migName="SqlConnection"> <coclass id="rdoResultset" creatable="off" migName="SqlDataReader"> <coclass id="rdoQuery" migName="SqlCommand">
public static void connectDB() { conn = new System.Data.SqlClient.SqlConnection(); string dbs = ""; dbs = "UID=stocks_login;PWD=password;Database=stocks;" + "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" + "DSN='';"; conn.ConnectionString = dbs; conn.Open(); } public static void execQuery() { string SQL = ""; System.Data.SqlClient.SqlCommand SP = null; System.Data.SqlClient.SqlDataReader Results = null; string f = ""; SQL = "select * from accounts where accountID < ? and FirstName like ?"; SP = conn.CreateCommand("QueryAcct",SQL); SP.Parameters[0].Value = "5005"; SP.Parameters[1].Value = "Test%"; Results = SP.ExecuteReader(); while (!Results.EOF) { f = Results.rdoColumns["FirstName"].Value.ToStr(); writeLog(f); f = Results.rdoColumns["eMail"].Value.ToStr(); writeLog(f); Results.MoveNext(); } SP.Close(); }
Starting the transformation process
The first difference between the current translation and the target translation is in the method connectDB.Current: dbs = "UID=stocks_login;PWD=password;Database=stocks;" + "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" + "DSN='';"; Target : dbs = "UID=stocks_login;PWD=password;Database=stocks;Server=GMI-CS-01.gmi.local;";
conn.ConnectionString = dbs;
72 | | | | NEW | 43 conn.Connect = dbs 75 | | | | LEV | Nest0 77 | 1.77 | 1.77 | String | LDA | Variable:dbs:88066 82 | 1.77 | | | ARG | String 84 | 2.84 | 1.84 | RDO.rdoConnection | LDA | Variable:conn:87690 89 | 3.89 | 1.84 | String | LLP | Component:Connect:50673 94 | 2.84 | 1.84 | String | MEM | Child 96 | | | | STR | AssignValue
| 50673 | 39973 | Lib_Property | RDO._rdoConnection.Connect
Introducing a component transform method
The gmSL transform methods are introduced within library description file Refactor statement sections using the gmSL statement. In this case this is as follows.<Refactor id="RDO" event="rdoHandlers" > <gmSL NameSpace="rdoHandlers" Class="Transform" Source="msrdo20Transform.gmsl" /> </Refactor>
int __rdoConnection_Connect(int subRoot,int iStart,int iRefer) { System.LogMessage("RDO#01: sub<" + Symbol.FullName(subRoot,-1) + "> iStart=" + iStart + " iRefer=" + iRefer); return 0; }
Loading reference:[Language.std] \gmIDF\Language.std.xml Reprocessing file: Transform.cls Reprocessing file: Transform.cls Processing file: \gmManual\Samples\RDOtoNet\src\RDOToNET.vbp Loading reference:[stdole2.tlb] \gmIDF\stdole2.tlb.xml Loading reference:[MSRDO20.DLL] \gmManual\Samples\FromIdl\MSRDO20.DLL.xml Reprocessing file: \gmManual\Samples\RDOtoNet\src\modRDOToNET.bas Reprocessing file: \gmManual\Samples\RDOtoNet\src\modRDOToNET.bas RDO#01: sub<RDOToNET.connectDB> iStart=77 iRefer=89
2 | 85026 | 81920 | ClassFile | Transform.cls 3 | 85249 | 85026 | Subprogram | rdoHandlers.Transform.__rdoConnection_Connect 4 | 85337 | 85249 | Variable | rdoHandlers.Transform.__rdoConnection_Connect.subRoot 4 | 85418 | 85249 | Variable | rdoHandlers.Transform.__rdoConnection_Connect.iStart 4 | 85463 | 85249 | Variable | rdoHandlers.Transform.__rdoConnection_Connect.iRefer 2 | 85128 | 81920 | Vb_Name.85026 | rdoHandlers.Transform
Text Associated with Scanned Code: RecNo | Rai | nRec | Content ----- | --- | ---- | ------- 1 | 0 | 65 | int __rdoConnection_Connect(int subRoot,int iStart,int iRefer){ 2 | 0 | 110 | System.LogMessage("RDO#01: sub<" + Symbol.FullName(subRoot,-1) + "> iStart=" + iStart + " iRefer=" + iRefer) 3 | 0 | 10 | return 0 4 | 0 | 3 | }
Actual C# Codeblock Associated with __rdoConnection_Connect: Offset | Sl.Start | Ql.Start | Quantity type | Opcode | Operation support information ------ | -------- | -------- | ------------- | ------ | ----------------------------- 0 | | | | LEV | Nest0 2 | 1.2 | 1.2 | String | LSC | 12:RDO#01: sub< 7 | 1.2 | 1.2 | String | LEV | Nest1 9 | 2.9 | 2.9 | Integer | LDA | Variable:subRoot:85337 ... 59 | 2.9 | | | SCM | System_LogMessage 61 | 2.9 | | | LEV | Nest0 63 | 3.63 | 1.63 | Integer | LIC | 0 66 | 3.63 | | | ARG | Integer 68 | | | | EXI | Function
Detailed Description of Lib_Property RDO._rdoConnection.ConnectionString with root address 50673: Property | Content -------- | ------- Migrate Status | Referenced Migrate Flags | HasCodeHandler Transformation | 85249 BinaryType | String:8
The RDO._rdoConnection.Connect transform Code
The actual code used to ultimately change the content of the dbs connection string works through references to the RDO._rdoConnection.Connect component. It is as follows. It begins with the same underlined converted method identifier, with the same standard parameters, and then the declarations of the local variables. Reading about, writing about, and understanding code whose purpose is to manage other code can get confusing quickly, so keep in mind that there are two coding levels.int __rdoConnection_Connect(int subRoot,int iStart,int iRefer) { tCodeBlock codptr; int nCode; int opcd; int subcd; int icode; int iEnd; int localVar; int iAssign; string connect; int iPos; int semi; int nDelete; int addr;
codptr = Opcode.GetCode(); nCode = Opcode.GetLength(); opcd = Opcode.GetOperation(codptr,iStart,localVar); if(opcd != OPC.LDA) return 0; icode = iRefer + sizeof(OPC.LLP); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.MEM) return 0; icode = icode + sizeof(OPC.MEM); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.STR) return 0;
89 | 3.89 | 1.84 | String | LLP | Component:Connect:50673 94 | 2.84 | 1.84 | String | MEM | Child 96 | | | | STR | AssignValue
iAssign = RefactorCode_FindAssign(localVar,iStart); if(iAssign == 0) return 0;
iEnd = Opcode.FindArgumentEnd(codptr,iAssign,nCode); connect = Opcode.GetString(iAssign,iEnd); if(!connect) return 0;
37 | | | | LEV | Nest0 39 | 1.39 | 1.39 | String | LSC | 46:UID=stocks_login;PWD=password;Database=stocks; 44 | 2.44 | 2.44 | String | LSC | 47:Server=GMI-CS-01.gmi.local;Driver={SQL Server}; 49 | 1.39 | 1.39 | String | CAT | String 51 | 2.51 | 2.51 | String | LSC | 7:DSN=''; 56 | 1.39 | 1.39 | String | CAT | String 58 | 1.39 | | | ARG | String
iPos = Character.FindFirst(connect,0,"Driver="); if(iPos) { iPos = iPos - 1; semi = Character.FindFirst(connect,iPos,";"); if(semi) { connect = Character.Remove(connect,iPos,semi); } } iPos = Character.FindFirst(connect,0,"DSN="); if(iPos) { iPos = iPos - 1; semi = Character.FindFirst(connect,iPos,";"); if(semi) { connect = Character.Remove(connect,iPos,semi); } }
nDelete = RefactorCode_ReplaceAssign(iAssign,connect); iRefer = iRefer - nDelete; return iRefer; }
int RefactorCode_FindAssign(int varRoot,int iEnd) { tCodeBlock codptr; int lastLev0; int icode; int addr; int opcd; int subcd; codptr = Opcode.GetCode(); lastLev0 = 0; for(icode = 0; icode >= 0; icode = Opcode.GetNext(codptr,icode,iEnd)) { opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd == OPC.LEV && subcd == 0) lastLev0 = icode; else if(opcd == OPC.LDA && subcd == varRoot) { opcd = Opcode.GetOperation(codptr,icode+sizeof(OPC.LDA),subcd); if(opcd == OPC.STR) return lastLev0; } } return 0; }
int RefactorCode_ReplaceAssign(int iAssign, string replacement) { tCodeBlock codptr; int nCode; int iEnd; int nDelete; int addr; codptr = Opcode.GetCode(); nCode = Opcode.GetLength(); iEnd = Opcode.FindArgumentEnd(codptr,iAssign,nCode); iAssign = iAssign + sizeof(OPC.LEV); nDelete = iEnd - iAssign - sizeof(OPC.LSC) - sizeof(OPC.ARG); if(nDelete > 0) { nCode = Opcode.DeleteCode(iAssign,nCode,nDelete); Opcode.SetLength(nCode); } addr = Store.String(replacement); Opcode.SetOperation(codptr,iAssign,OPC.LSC,addr); return nDelete; }
Comparing files rdotran.bnd and RDOTRAN.SAV ***** rdotran.bnd dbs = "UID=stocks_login;PWD=password;Database=stocks;Server=GMI-CS-01.gmi.local;"; ***** RDOTRAN.SAV dbs = "UID=stocks_login;PWD=password;Database=stocks;" + "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" + "DSN='';"; *****
The RDO._rdoConnection.CreateQuery transform Code
The next difference between the unmigrated and migrated code is in execQuery in the string assigned to the variable SQL.Current: SQL = "select * from accounts where accountID < ? and FirstName like ?"; Target : SQL = "select * from accounts where accountID < @0 and FirstName like @1";
Set SP = conn.CreateQuery("QueryAcct", SQL)
int __rdoConnection_CreateQuery(int subRoot,int iStart,int iRefer) { tCodeBlock codptr; int nCode; int opcd; int subcd; int icode; int sqlString; int sqlVar; string query; int iAssign; int index; int iPos; int lPos; int nDelete; int createCommand; int iEnd;
codptr = Opcode.GetCode(); nCode = Opcode.GetLength(); icode = iRefer; opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.LLP) return 0; icode = icode + sizeof(OPC.LLP); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.MEM) return 0; icode = icode + sizeof(OPC.MEM); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.LEV) return 0; sqlString = Opcode.FindArgumentEnd(codptr,icode,nCode); opcd = Opcode.GetOperation(codptr,sqlString,subcd); if(opcd != OPC.LEV) return 0; sqlString = sqlString + sizeof(OPC.LEV); opcd = Opcode.GetOperation(codptr,sqlString,sqlVar); if(opcd != OPC.LDA) return 0; sqlString = sqlString+sizeof(OPC.LDA); opcd = Opcode.GetOperation(codptr,sqlString,subcd); if(opcd != OPC.ARG) return 0; sqlString = sqlString+sizeof(OPC.ARG);
iAssign = RefactorCode_FindAssign(sqlVar,iRefer); if(iAssign == 0) return 0;
iEnd = Opcode.FindArgumentEnd(codptr,iAssign,nCode); query = Opcode.GetString(iAssign,iEnd); if(!query) return 0;
if(iAssign) { iPos = 0; for(index = 0; index < 10; index = index + 1) { lPos = Character.FindFirst(query,iPos,"?"); if(!lPos) break; iPos = iPos + lPos - 1; query = Character.Remove(query,iPos,1); query = Character.Insert(query,iPos,"@" + index); } if(iPos != 0) { nDelete = RefactorCode_ReplaceAssign(iAssign,query); iRefer = iRefer - nDelete; sqlString = sqlString - nDelete; } } return iRefer; }
Comparing files rdotran.bnd and RDOTRAN.SAV ***** rdotran.bnd SQL = "select * from accounts where accountID < @0 and FirstName like @1"; ***** RDOTRAN.SAV SQL = "select * from accounts where accountID < ? and FirstName like ?"; *****
Current: SP = conn.CreateCommand("QueryAcct",SQL); Target : (SP = conn.CreateCommand()).CommandText = SQL;
<migclass id="DotNet"> <method id="CreateCommand" type="void" migPattern="(%1d = %2d()).CommandText = %4d\c"> <argument id="conn" type="Object" status="ByVal" /> <argument id="Name" type="String" status="ByVal"/> <argument id="SqlString" type="Variant" status="ByVal"/> </method> </migClass>
iEnd = sqlString; opcd = Opcode.GetOperation(codptr,iEnd,subcd); if(opcd != OPC.CUF) return 0; iEnd = iEnd + sizeof(OPC.CUF); opcd = Opcode.GetOperation(codptr,iEnd,subcd); if(opcd != OPC.REF) return 0; iEnd = iEnd + sizeof(OPC.REF); opcd = Opcode.GetOperation(codptr,iEnd,subcd); if(opcd != OPC.ARG) return 0; iEnd = iEnd + sizeof(OPC.ARG); opcd = Opcode.GetOperation(codptr,iEnd,subcd); if(opcd != OPC.CMD) return 0; iEnd = iEnd + sizeof(OPC.CMD); nDelete = iEnd - sqlString - sizeof(OPC.PAT); createCommand = Symbol.FindIdentifier("RDO.DotNet.CreateCommand"); nCode = Opcode.DeleteCode(sqlString,nCode,nDelete); Opcode.SetLength(nCode); Opcode.SetOperation(codptr,sqlString,OPC.PAT,createCommand);
***** rdotran.bnd (SP = conn.CreateCommand()).CommandText = SQL; ***** RDOTRAN.SAV SP = conn.CreateCommand("QueryAcct",SQL); *****
The RDO.rdoPreparedStatement.rdoParameters transform Code
The next difference between the unmigrated and migrated code is as follows. This particular difference occurs twice.Current: SP.Parameters[0].Value = "5005"; Target : SP.Parameters.Add(new System.Data.SqlClient.SqlParameter("@0", null)).Value = "5005";
<Method id="Parameters" type="object" migPattern="%1d.Add(new System.Data.SqlClient.SqlParameter(\S@%2d\S, null))" > <argument id="index" type="Integer" status="ByVal" /> </Method>
int rdoPreparedStatement_rdoParameters(int subRoot,int icode,int iRefer) { int nCode; tCodeBlock codptr; int iEnd; int opcd; int subc; int parameters; nCode = Opcode.GetLength(); codptr = Opcode.GetCode(); iEnd = Opcode.FindArgumentEnd(codptr,iRefer+7,nCode); opcd = Opcode.GetOperation(codptr,iEnd,subc); if(opcd != OPC.COL || subc != OPC.COL.Item) return 0; parameters = Symbol.FindIdentifier("RDO.DotNet.Parameters"); nCode = Opcode.ExpandCode(iEnd,nCode,sizeof(OPC.PAT) - sizeof(OPC.COL)); Opcode.SetLength(nCode); Opcode.SetOperation(codptr,iEnd,OPC.PAT,parameters); return iRefer; }
Comparing files rdotran.bnd and RDOTRAN.SAV ***** rdotran.bnd SP.Parameters.Add(new System.Data.SqlClient.SqlParameter("@0", null)).Value = "5005"; SP.Parameters.Add(new System.Data.SqlClient.SqlParameter("@1", null)).Value = "Test%"; ***** RDOTRAN.SAV SP.Parameters[0].Value = "5005"; SP.Parameters[1].Value = "Test%"; *****
The RDO.rdoPreparedStatement.OpenResultset transform code
An important difference in the migrated code has to do with the SqlDataReader variable Results. In the unmigrated version, it is declared as a method level local variable and is then opened in the code.System.Data.SqlClient.SqlDataReader Results = null; ... Results = SP.ExecuteReader();
using (System.Data.SqlClient.SqlDataReader Results = SP.ExecuteReader()) {
int rdoPreparedStatement_OpenResultset(int subRoot,int iStart,int iRefer) { tCodeBlock codptr; int nCode; int opcd; int subcd; int icode; int varRoot; tVariable varInfo;
codptr = Opcode.GetCode(); nCode = Opcode.GetLength(); icode = iRefer; opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.REF) return 0; icode = icode + sizeof(OPC.REF); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.ARG) return 0; icode = icode + sizeof(OPC.ARG); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.CMD) return 0; opcd = Opcode.GetOperation(codptr,iStart,varRoot); if(opcd != OPC.LDA) return 0;
varInfo = Store.DeltaVector(varRoot); varInfo.DeadCode = True;
Opcode.SetOperation(codptr,icode,OPC.IFS,OPC.IFS.Using); nCode = Opcode.ExpandCode(icode,nCode,sizeof(OPC.TYV)); Opcode.SetLength(nCode); Opcode.SetOperation(codptr,icode,OPC.TYV,varRoot); return iRefer; }
Comparing files rdotran.bnd and RDOTRAN.SAV ***** rdotran.bnd using (System.Data.SqlClient.SqlDataReader Results = SP.ExecuteReader()) { while (!Results.EOF) .... ***** RDOTRAN.SAV Results = SP.ExecuteReader(); while (!Results.EOF) .. *****
AUTHOR WARNING#02: Indentation level not balanced old = 3 current = 4 in <RDOToNET.execQuery>
The RDO.rdoPreparedStatement.Close transform code
Within the unmigrated code the Openresultset method has a corresponding Close method. In the migrated approach this method call is replaced by an IFS.EndUsing operation. The transform code is as follows.int rdoPreparedStatement_Close(int subRoot,int icode,int iRefer) { int nCode; tCodeBlock codptr; iRefer = Opcode.CommentOut(iRefer,OPC.CMT.Delete); iRefer = iRefer + sizeof(OPC.CMT); nCode = Opcode.GetLength(); codptr = Opcode.GetCode(); nCode = Opcode.ExpandCode(iRefer,nCode,sizeof(OPC.IFS)); Opcode.SetLength(nCode); Opcode.SetOperation(codptr,iRefer,OPC.IFS,OPC.IFS.EndUsing); return iRefer; }
***** rdotran.bnd } ***** RDOTRAN.SAV SP.Close(); *****
The RDO._rdoResultset.EOF transform code
The next difference is in the while loop that reads the records from the result set.Current: while (!Results.EOF) Target : while (Results.Read())
<property id="EOF" type="Boolean" status="Out" migName="Read()"/>
266 | 2.266 | 1.261 | Boolean | LLP | Component:EOF:59440 271 | 1.261 | 1.261 | Boolean | MEM | Child 273 | 1.261 | 1.261 | Boolean | NOT | Arithmetic
int __rdoResultset_EOF(int subRoot,int iStart,int iRefer) { int nCode; tCodeBlock codptr; int opcd; int subcd; int icode; nCode = Opcode.GetLength(); codptr = Opcode.GetCode(); icode = iRefer + sizeof(OPC.LLP); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.MEM) return 0; icode = icode + sizeof(OPC.MEM); opcd = Opcode.GetOperation(codptr,icode,subcd); if(opcd != OPC.NOT) return 0; nCode = Opcode.DeleteCode(icode,nCode,sizeof(OPC.NOT)); Opcode.SetLength(nCode); return iRefer; }
***** rdotran.bnd while (Results.Read()) ***** RDOTRAN.SAV while (!Results.EOF) *****
The RDO._rdoColumn.Value and RDO._rdoResultset.rdoColumns transform code
The next difference is in the while loop that reads the records from the result set.Current: f = Results.rdoColumns["FirstName"].ToStr(); Target : f = Results["FirstName"].ToStr();
280 | | | | LEV | Nest0 282 | 1.282 | 1.282 | RDO.rdoResultset | LDA | Variable:Results:106065 287 | 2.287 | 1.282 | RDO.rdoColumns | LLP | Component:rdoColumns:57254 292 | 1.282 | 1.282 | RDO.rdoColumns | MEM | Child 294 | 1.282 | 1.282 | RDO.rdoColumns | LEV | Nest1 296 | 2.296 | 2.296 | String | LSC | 9:FirstName 301 | 2.296 | 1.282 | RDO.rdoColumns | ARG | String 303 | 1.282 | 1.282 | RDO.rdoColumn | COL | Item 305 | 2.305 | 1.282 | Variant | LLP | Component:Value:54311 310 | 1.282 | 1.282 | Variant | MEM | Child
int __rdoColumn_Value(int subRoot,int icode,int iRefer) { int nCode; tCodeBlock codptr; nCode = Opcode.GetLength(); codptr = Opcode.GetCode(); nCode = Opcode.DeleteCode(iRefer,nCode,sizeof(OPC.LLP) + sizeof(OPC.MEM)); Opcode.SetLength(nCode); return iRefer; } int __rdoResultset_rdoColumns(int subRoot,int icode,int iRefer) { int nCode; tCodeBlock codptr; nCode = Opcode.GetLength(); codptr = Opcode.GetCode(); nCode = Opcode.DeleteCode(iRefer,nCode,sizeof(OPC.LLP) + sizeof(OPC.MEM)); Opcode.SetLength(nCode); return iRefer; }
Comparing files rdotran.bnd and RDOTRAN.SAV ***** rdotran.bnd f = Results["FirstName"].ToStr(); writeLog(f); f = Results["eMail"].ToStr(); ***** RDOTRAN.SAV f = Results.rdoColumns["FirstName"].Value.ToStr(); writeLog(f); f = Results.rdoColumns["eMail"].Value.ToStr(); *****
The RDO._rdoResultset_MoveNext code
The final difference between the two translations is that the MoveNext call is no longer needed. The migrated code already does the read in the while loop. The transform method can simply comment out the unwanted statement.int __rdoResultset_MoveNext(int subRoot,int icode,int iRefer) { iRefer = Opcode.CommentOut(iRefer,OPC.CMT.Delete); return iRefer; }
Table of Contents