open-insight/LSL2/STPROC/SQL_SERVICES.txt
2024-10-24 16:37:24 -07:00

3644 lines
201 KiB
Plaintext

Function SQL_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc..
Name : SQL_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
History : (Date, Initials, Notes)
10/19/17 dmb v1.0.0 - Original programmer.
05/06/20 dmb v2.0.0 - Added GetDatabases, GetSchemas, and GetTables services.
05/09/20 dmb v2.0.0 - Changed GetSQLServer service to GetMappedSQLServer to use the same naming
convention as other similar services.
05/09/20 dmb v2.0.0 - Decprecate the GetTableNames service. Use GetTables instead.
05/09/20 dmb v2.0.0 - Update GetTableColumns service to support Database and Schema arguments. Add logic
to check the Table argument for other SQL objects.
05/09/20 dmb v2.0.0 - Remove all case conversions for SQL table names in all services.
05/11/20 dmb v2.0.0 - Update the GetMappedSQLColumnValues and GetMappedOIColumnValues services to support
additional SQL data types and to use SRP_Date/SRP_DateTime/SRP_Time functions
instead of Iconv/Oconv.
05/11/20 dmb v2.0.0 - Update GetSQLUpdateStatements service so secondary tables use the correct SQL
syntax.
05/12/20 djs v2.0.0 - Update GetServers service to use new SERVERS table. Add CreateNewConnection,
EditConnection, DeleteConnection, and SetConnectionDesc services.
05/12/20 dmb v2.0.0 - More updates to the GetSQLInsertStatements and GetSQLUpdateStatements services to
improve handling of AMV mapping.
05/12/20 dmb v2.0.0 - Move transaction control out of the WriteDataRowToSQL and DeleteDataRowFromSQL
services into the ExecuteQueries service so error trapping can determine if a
COMMIT or ROLLBACK should be made.
05/13/20 dmb v2.0.0 - Update GetConnectionString service to use the SERVERS table.
05/13/20 dmb v2.0.0 - Remove deprecated LogConnectionActivity service.
05/14/20 dmb v2.0.0 - Update the ExecuteQueries service to ignore query statements that are empty. This
will allow other query statements to be executed in the event of an accidental
empty entry.
05/14/20 dmb v2.0.0 - Update the GetMappedSQLColumnValues service return the OI Key value correctly when
working with AMV values greater than 1.
05/14/20 dmb v2.0.0 - Update the GetSQLUpdateStatements service to DELETE all secondary SQL table rows
first and then INSERT rows as needed. This is necessary to keep the data in sync
since AMV columns likely will not have a column that can be used as a secondary Key
ID within the secondary SQL table.
06/03/20 dmb v2.0.0 - Update the GetSQLInsertStatements and GetSQLUpdateStatements services so that AMV
master columns with actual data (rather than empty values) will generate a SQL
statement. This fixes a problem where NULLs were attempted to be stored in a
primary key column.
06/04/20 dmb v2.0.0 - Update the GetStaticSQLColumnNames and GetStaticSQLColumnValues services to support
the new JSON structure.
06/05/20 dmb v2.0.0 - Update the GetDatabases service so system schemas are excluded.
06/06/20 dmb v2.0.0 - Improve error handling in the GetAllQueryDataRows service.
06/06/20 dmb v2.0.0 - Update the GetAllQueryDataRows service to check the EOF property of the RecordSet
object before calling the GetString method.
06/06/20 dmb v2.0.0 - Update the GetSchemas service to see if the error returned from the ExecuteQuery
service reports a permissions error. If so, ignore and clear the error.
06/08/20 dmb v2.0.0 - Change all references to information_schema to all caps to avoid case sensitivity
issues.
06/08/20 dmb v2.0.0 - Update the GetDatabases service to see if the response from the ExecuteQuery
service is "0". If so, then clear the response and set an error.
06/10/20 dmb v2.0.1 - Update the GetJoinedOIColumns service to assign to the ValuesReturned passed by
reference argument whether an associated column should return its column data
(default) or its index position.
06/10/20 dmb v2.0.1 - Update the GetMappedOIColumnNames to use the ValuesReturned argument that is
assigned by the GetJoinedOIColumns service. This service will also assigned its own
ValuesReturned passed by preference argument.
06/10/20 dmb v2.0.1 - Update the GetMappedSQLColumnValues to use the ValuesReturned argument that is
assigned by the GetMappedOIColumnNames service.
06/10/20 dmb v2.0.1 - Change the Errors argument to ErrorList in the AddConnectionErrors service to avoid
suspected VNAV warnings.
06/10/20 dmb v2.0.1 - Change the Desc argument to Description in the SetConnectionDesc service to avoid
suspected VNAV warnings.
06/10/20 dmb v2.0.1 - Update the GetMappedSQLColumnNames service to better exclude SQL columns that are
not mapped.
06/10/20 dmb v2.0.1 - Update the GetMappedOIColumnNames service to better exclude OI columns that are not
mapped.
06/12/20 dmb v2.0.1 - Update the GetAMVMaster service to locate the AMV Master using the attributes of
the join clause rather than the dedicated key/value pair.
06/12/20 dmb v2.0.1 - Update the GetSQLInsertStatements and GetSQLUpdateStatements services to use the
updated GetAMVMaster service.
06/14/20 dmb v2.0.1 - Update the GetSQLInsertStatements and GetSQLUpdateStatements services to verify if
any columns used in the join clause are not defined in the map. If so, then include
these columns and their corresponding values in the Insert or Update statements.
06/14/20 dmb v2.0.1 - Fix bug in the GetMappedSQLColumnValues service to properly return the AMV index
position if the value returned requested it.
06/14/20 dmb v2.0.1 - Added the GetJoinedSQLColumns service.
06/15/20 dmb v2.0.1 - Update the GetMappedSQLColumnValues service to support the bit SQL data type.
06/15/20 dmb v2.0.1 - Update the GetTableColumns service to use a SQL statement that also returns PK and
Null constraints.
06/22/20 dmb v2.0.1 - Update the GetTableColumns service so the results are sorted by PK and then
alphabetically.
06/22/20 dmb v2.0.1 - Update the GetTableColumns service to make a USE <database> query if the database
is known.
06/23/20 dmb v2.0.1 - Rename the GetJoinedSQLColumns service to GetMappedJoinedSQLColumns and update all
calls to this service.
06/23/20 dmb v2.0.1 - Rename the GetJoinedSQLColumns service to GetMappedJoinedSQLColumnNames and update
all calls to this service.
06/23/20 dmb v2.0.1 - Rename the GetJoinedOIColumns service to GetMappedJoinedOIColumnNames and update
all calls to this service.
06/23/20 dmb v2.0.1 - Added the GetMappedJoinedSQLColumnValues service.
06/23/20 dmb v2.0.1 - Added the GetMappedJoinedOperators service.
06/23/20 dmb v2.0.1 - Major refactoring of all services that create SQL statements to better handle edge
cases and joined columns.
06/24/20 dmb v2.0.1 - Fix memory leak in the GetMappedOIColumnNames service by releasing the MapObj
object.
06/29/20 dmb v2.0.1 - Update the GetMappedSQLColumnValues service so that all errors are cleared once
the column value is being calculated because any errors that are created must have
come from a calculated column. This will avoid returning a number of values that
differs from the number of column names.
07/10/20 dmb v2.0.1 - Update the GetMappedSQLColumnValues service to support the uniqueidentifier SQL
data type.
07/10/20 dmb v2.0.1 - Udpate the GetMappedOIColumnNames and GetMappedSQLColumnNames services to support
a ExcludeJoinedColumns flag rather than assume joined columns should always be
excluded.
07/10/20 dmb v2.0.1 - Update the GetMappedOIColumnValues and GetMappedSQLColumnValues services to pass
the ExcludeJoinedColumns flag to the GetMappedOIColumnNames and
GetMappedSQLColumnNames services.
07/20/20 dmb v2.0.1 - Fix bug in the GetMappedJoinedSQLColumnValues service that attempted to convert
an index value based on the data type.
07/20/20 dmb v2.0.1 - Fix bug in the WriteDataRowToSQL service to avoid VNAV error with the
TransactionQueries variable.
07/31/20 dmb v2.0.2 - Fix bug in the GetSQLInsertStatements and GetSQLUpdateStatements services where
maps to tables with no data columns would attempt to insert/update empty values
in empty columns.
07/31/20 dmb v2.0.2 - Update the GetSQLUpdateStatements service to avoid creating an update state for
primary tables that only have a join but no column maps.
08/13/20 djs v2.0.3 - Replaced CreateNewConnection service with CreateNewConnectionString and
SaveConnectionString services. These new services allow multiple connections to
the same SQL server (i.e. same SQL source, different user credentials and/or base
catalog) to be stored under user defined Server ID key IDs.
08/14/20 djs - Created a new copy of SQL_Services (LSL2) from SQL_Services (SYSPROG).
Added PostSQLRequest and ProcessSQLRequests services back into SQL_Services (LSL2),
which are services that only exist in Infineon's copy of SQL_Services. These
services add the ability to query SQL servers outside of the originating server's
domain. Created SERVERS entries for all SQL Server connections currently in the
APP_INFO table.
08/17/20 djs - Replaced all calls to SQL_Services_DJS (a temporary stored procedure that
was utilized during the SQL_Services (SYSPROG) upgrade) throughout the LSL2
application with calls to SQL_Services.
08/17/20 dmb v2.0.7 - Update the GetMappedJoinedSQLColumnValues and GetMappedSQLColumnValues services
to safety check integer and floating point numbers for empty and non-numeric
values and convert to something other than an empty or unquoted string.
09/18/20 dmb v2.0.8 - Update the GetTables service to sort the results rather than rely upon SQL to
return sorted results.
06/28/21 dmb v2.0.9 - Update the GetMappedSQLColumnNames and GetMappedSQLColumnValues services to compare
the passed in SQL Table against the mapped SQL table in the JSON definition before
accepting the current SQL Column. This resolves issues where one OI table with only
MultiValue columns is mapped to two SQL tables.
02/12/2024 djm v2.0.10- Move Free_Class.Net(DotNetObj) in ExecuteQuery to avoid memory leak.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert SERVERS_EQUATES
$insert MICROSOFT_ADO_EQUATES
$insert DICT_EQUATES
$insert SQL_REQUESTS_EQUATES
$insert RLIST_EQUATES
$insert REVDOTNETEQUATES
Equ CRLF$ to \0D0A\
Equ COMMA$ to ','
Common /SQLServices/ ConnectionObjects@, Unused2@, Unused3@, Unused4@, Unused5@, Unused6@, Unused7@, Unused8@
Declare function Memory_Services, SQL_Services, Database_Services, SRP_JSON, SRP_Array, SRP_Hash, SRP_COM, SRP_Encode
Declare function SRP_Date, SRP_DateTime, SRP_Time, Utility, Unicode_UTF8, Str_Unicode, GetTickCount, SRP_Decode
Declare function SRP_List, Environment_Services, Logging_Services, Active_Directory_Services
Declare subroutine Memory_Services, SQL_Services, Database_Services, SRP_JSON, SRP_Stopwatch, SRP_COM, SRP_List
Declare subroutine GetTempPath, GetTempFileName, Sleepery, WinYield, Yield, RList, Set_Status, Logging_Services
Declare subroutine Update_Index, obj_Notes
UseRevDotNet = Database_Services('ReadDataRow', 'APP_INFO', 'USE_REVDOTNET')
If UseRevDotNet EQ '' then UseRevDotNet = False$
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\SQL_Services'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' SQL Services Log.csv'
Headers = 'Logging DTM' : @FM : 'Error'
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\Replication'
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Null Record Log.csv'
Headers = 'Logging DTM' : @FM : 'Error'
objNullLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
If ConnectionObjects@ EQ '' then ConnectionObjects@ = SRP_List('Create')
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// WriteDataRowToSQL
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table being written to. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being written to SQL. - [Required]
// OIRow - The OpenInsight row being written to SQL. - [Required]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to SQL. If empty,
// all columns that have a map defintion will be used. - [Optional]
//
// High level services that writes OpenInsight data into a designated SQL table. This services calls other lower
// level services as needed and assumes an OpenInsight to SQL map has already been created.
//----------------------------------------------------------------------------------------------------------------------
Service WriteDataRowToSQL(OITableName, OIKeyID, OIRow, OIColumns)
If (OITableName NE '') AND (OIKeyID NE '') AND (OIRow NE '') then
// Create a new or get an existing Connection Object.
SQLServer = SQL_Services('GetMappedSQLServer', OITableName)
objConnection = SQL_Services('GetConnectionObject', SQLServer, 2)
TransactionQueries = ''
If Error_Services('NoError') then
// Confirm if row already exists. This will determine if an INSERT or UPDATE should be made.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
TransactionQueries = SQL_Services('GetSQLMergeStatements', OITableName, OIKeyID, OIRow, OIColumns)
end
If Error_Services('NoError') AND (TransactionQueries NE '') then
// Process the tranaction queries.
SQL_Services('ExecuteQueries', objConnection, TransactionQueries, True$, OITableName, OIKeyID)
If Error_Services('HasError') then
ErrorMessage = Error_Services('GetMessage')
Error_Services('Clear')
InsertError = IndexC(ErrorMessage, 'FOREIGN', 1)
If InsertError then
// Record may have been inserted in between the time this routine began and by the time the SQL
// statement executed. Try an UPDATE statement instead.
TransactionQueries = SQL_Services('GetSQLUpdateStatements', OITableName, OIKeyID, OIRow, OIColumns)
If Error_Services('NoError') AND (TransactionQueries NE '') then
SQL_Services('ExecuteQueries', objConnection, TransactionQueries, True$, OITableName, OIKeyID)
end
end else
Error_Services('Add', ErrorMessage)
end
end
end
end else
Error_Services('Add', 'The OITableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// DeleteDataRowFromSQL
//
// High level services that deletes data from a designated SQL table. This services calls other lower level services as
// needed and assumes an OpenInsight to SQL map has already been created.
//----------------------------------------------------------------------------------------------------------------------
Service DeleteDataRowFromSQL(OITableName, OIKeyID)
If (OITableName NE '') AND (OIKeyID NE '') then
// Create a new or get an existing Connection Object.
SQLServer = SQL_Services('GetMappedSQLServer', OITableName)
objConnection = SQL_Services('GetConnectionObject', SQLServer, 2)
TransactionQueries = ''
If Error_Services('NoError') then
// Confirm if row already exists. This will determine if an INSERT or UPDATE should be made.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
JoinClause = SQL_Services('GetJoinClause', OITableName, PrimarySQLTableName, OIKeyID, OIRow)
SQLStatement = 'SELECT TOP 1 * FROM ' : PrimarySQLTablename : ' WHERE ' : JoinClause
RowData = SQL_Services('ExecuteQuery', objConnection, SQLStatement, True$)
If RowData NE '' then
// Create the DELETE statements so the data in SQL is cleared out first.
TransactionQueries = SQL_Services('GetSQLDeleteStatements', OITableName, OIKeyID)
end
end
If Error_Services('NoError') AND (TransactionQueries NE '') then
// Process the tranaction queries.
SQL_Services('ExecuteQueries', objConnection, TransactionQueries, True$)
end
end else
Error_Services('Add', 'The OITableName or OIKeyID argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ReadDataRowFromSQL
//
// High level services that reads data from a designated SQL table. This services calls other lower level services as
// needed and assumes an OpenInsight to SQL map has already been created.
//----------------------------------------------------------------------------------------------------------------------
Service ReadDataRowFromSQL(OITableName, OIKeyID)
OIRow = ''
If (OITableName NE '') AND (OIKeyID NE '') then
// Create a new or get an existing Connection Object.
SQLServer = SQL_Services('GetMappedSQLServer', OITableName)
objConnection = SQL_Services('GetConnectionObject', SQLServer, 2)
If Error_Services('NoError') then
// Select the SQL data for the primary SQL table associated to the OpenInsight table.
SQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
SQLSelectStatement = SQL_Services('GetSQLSelectStatement', OITableName, SQLTableName, OIKeyID)
SQLData = SQL_Services('ExecuteQuery', objConnection, SQLSelectStatement, True$)
If (SQLData NE '') AND (Error_Services('NoError')) then
OIRow = SQL_Services('GetMappedOIColumnValues', OITableName, SQLTableName, SQLData)
end
end
If Error_Services('NoError') then
// Select the SQL data for all secondary SQL tables associated to the OpenInsight table.
SQLTableNames = SQL_Services('GetSecondarySQLTables', OITableName)
If SQLTableNames NE '' then
For Each SQLTableName in SQLTableNames using @FM
SQLSelectStatement = SQL_Services('GetSQLSelectStatement', OITableName, SQLTableName, OIKeyID)
// Create a new or get an existing Connection Object.
SQLServer = SQL_Services('GetMappedSQLServer', OITableName)
objConnection = SQL_Services('GetConnectionObject', SQLServer, 2)
If Error_Services('NoError') AND (SQLSelectStatement NE '') then
SQLData = SQL_Services('ExecuteQuery', objConnection, SQLSelectStatement, True$)
If (SQLData NE '') AND (Error_Services('NoError')) then
OIRow = SQL_Services('GetMappedOIColumnValues', OITableName, SQLTableName, SQLData, OIRow)
end
end
While (Error_Services('NoError'))
Next SQLTable
end
end
end else
Error_Services('Add', 'The OITableName or OIKeyID argument was missing in the ' : Service : ' service.')
end
Response = OIRow
end service
//----------------------------------------------------------------------------------------------------------------------
// GetRowCount
//
// Server - Name of the server the connection object is bound to. This should be the same name that will be used in
// the Data Source connection string.
// Table - SQL table whose row count is being requested.
//
// High level services that counts the number of rows in the designated table. This services calls other lower level
// services.
//----------------------------------------------------------------------------------------------------------------------
Service GetRowCount(Server, TableName)
RowCount = ''
If (Server NE '') AND (TableName NE '') then
// Create a new or get an existing Connection Object.
objConnection = SQL_Services('GetConnectionObject', Server, 2)
If Error_Services('NoError') then
// Select the SQL data for the primary SQL table associated to the OpenInsight table.
ErrorMessage = ''
SQLCountStatement = 'SELECT COUNT(*) FROM ' : TableName
RowCount = SQL_Services('ExecuteQuery', objConnection, SQLCountStatement, True$)
If Error_Services('HasError') then
ErrorMessage = Error_Services('GetMessage')
end
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
end
end else
Error_Services('Add', 'The Server or TableName argument was missing in the ' : Service : ' service.')
end
Response = RowCount
end service
//----------------------------------------------------------------------------------------------------------------------
// GetDataRows
//
// Server - Name of the server the connection object is bound to. This should be the same name that
// will be used in the Data Source connection string.
// QueryStatement - Query command. This should be a properly syntaxed SQL statement.
//
// High level service that gets database rows from the indicated database using the indicated query statement. This
// service will automatically get the connection and query object needed to perform the query statement.
//----------------------------------------------------------------------------------------------------------------------
Service GetDataRows(Server, QueryStatement, AttemptsBeforeFailure)
If AttemptsBeforeFailure EQ '' then AttemptsBeforeFailure = 1
DataRows = ''
If ( (Server NE '') AND (QueryStatement NE '') ) then
ErrorMessage = ''
objConnection = SQL_Services('GetConnectionObject', Server, 2)
If Error_Services('NoError') then
If Error_Services('NoError') then
DataRows = SQL_Services('ExecuteQuery', objConnection, QueryStatement, True$, AttemptsBeforeFailure)
end
// Get any errors from the GetConnectionObject service or the ExecuteQuery service.
ErrorMessage = Error_Services('GetMessage')
end
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage then Error_Services('Set', ErrorMessage)
end else
Error_Services('Add', 'Server or QueryStatement argument was missing in the ' : Service : 'service.')
end
Response = DataRows
end service
//----------------------------------------------------------------------------------------------------------------------
// GetConnectionObject
//
// Server - Name of the server the connection object is bound to. This should be the same name that
// will be used in the Data Source connection string.
// AttemptsBeforeFailure - Number of attempts to make the connect before erroring out. Default is 1.
//
// Returns a Connection Object based on the server. A returned Connection Object means that the server has been
// successfully connected to with the provided credentials. This service uses caching, so until an existing Connection
// Object has been destroyed (see the DestroyConnectionObject service), it will continue to use the one already in
// existence.
//----------------------------------------------------------------------------------------------------------------------
Service GetConnectionObject(Server, AttemptsBeforeFailure)
If UseRevDotNet EQ False$ then
If AttemptsBeforeFailure EQ '' then AttemptsBeforeFailure = 1
objConnection = ''
// Check to see if the Connection Object already exists.
ServiceKeyID := '*' : Server
objConnection = Memory_Services('GetValue', ServiceKeyID)
If objConnection EQ '' then
If Server NE '' then
Attempts = 0
Error = ''
Loop
If SRP_COM(objConnection, 'CREATE', 'ADODB.Connection') then
Memory_Services('SetValue', objConnection : '*Server', Server)
If SRP_COM('', 'ERROR') then
Error = SRP_COM('', 'ERROR')
SQL_Services('DestroyConnectionObject', objConnection)
objConnection = ''
end else
ConnectionString = SQL_Services('GetConnectionString', Server)
If Error_Services('NoError') then
SRP_COM(objConnection, 'CALL', 'Open', ConnectionString)
If SRP_COM('', 'ERROR') then
Error = SRP_COM('', 'ERROR')
SQL_Services('DestroyConnectionObject', objConnection)
objConnection = ''
end
end else
objConnection = ''
end
end
end
Attempts += 1
Until (objConnection NE '') OR (Attempts GE AttemptsBeforeFailure)
Repeat
If objConnection then
Memory_Services('SetValue', ServiceKeyID, objConnection)
end else
If Error_Services('NoError') then
// If no error message has been set then create a generic one.
Error_Services('Add', 'Unable to create the connection object to ' : Server : ' in the ' : Service : ' service: ' : Error)
end
end
end else
Error_Services('Add', 'Server argument was missing from the ' : Service : ' service.')
end
end
Response = objConnection
end else
If AttemptsBeforeFailure EQ '' then AttemptsBeforeFailure = 1
objConnection = ''
// Check to see if the Connection Object already exists.
ServiceKeyID := '*' : Server : '*objConnection'
objConnection = Memory_Services('GetValue', ServiceKeyID)
If objConnection EQ '' then
If Server NE '' then
Attempts = 0
Error = ''
Loop
// Define the .NET version
DotNetHandle = StartDotNet("","4.0")
DotNetDir = CheckDotNet('4.0'):'\'
SqlClientDLLPath = DotNetDir:'System.Data.dll'
ConnectionString = Sql_Services('GetConnectionString', Server)
// Specify the DLL
rv = Set_Property.NET(DotNetHandle, "AssemblyName", SqlClientDLLPath)
// Define the classes
objConnection = Create_Class.NET(DotNetHandle, "System.Data.SqlClient.SqlConnection", 0, ConnectionString, 'System.String')
If Not(Get_Status(errCode)) then
rv = Set_Property.NET(objConnection, 'Pooling', 'False')
If Not(Get_Status(errCode)) then
rv = Send_Message.Net(objConnection, "Open")
If Not(Get_Status(errCode)) then
ConnectionState = Get_Property.Net(objConnection, "State")
If ConnectionState EQ 'Open' then
ClientConnectionID = Get_Property.NET(objConnection, 'ClientConnectionId', False$)
Memory_Services('SetValue', ClientConnectionID : '*Server', Server)
end else
Sql_Services('DestroyConnectionObject', objConnection)
objConnection = ''
end
end else
Sql_Services('DestroyConnectionObject', objConnection)
objConnection = ''
end
end else
Sql_Services('DestroyConnectionObject', objConnection)
objConnection = ''
end
end
Attempts += 1
Until (objConnection NE '') OR (Attempts GE AttemptsBeforeFailure)
Repeat
If objConnection and Error_Services('NoError') then
Memory_Services('SetValue', ServiceKeyID, objConnection)
ConnObjIndex = SRP_List('Add', ConnectionObjects@, objConnection)
end else
If Assigned(objConnection) then Free_Class.Net(objConnection)
If Error_Services('NoError') then
// If no error message has been set then create a generic one.
Error_Services('Add', 'Unable to create the connection object to ' : Server : ' in the ' : Service : ' service: ' : Error)
end
end
end else
Error_Services('Add', 'Server argument was missing from the ' : Service : ' service.')
end
end
Response = objConnection
end
end service
//----------------------------------------------------------------------------------------------------------------------
// DestroyConnectionObject
//
// objConnection - Connection Object (see GetConnectionObject service.)
//
// Destroys the Connection Object. This returns True$ if successful, False$ if not.
//----------------------------------------------------------------------------------------------------------------------
Service DestroyConnectionObject(objConnection)
Destroyed = False$ ; // Assume object is not destroyed for now.
If UseRevDotNet EQ False$ then
If objConnection NE '' then
Error = ''
// Close the connection object, but don't worry about errors. It might have already been closed.
SRP_COM(objConnection, 'CALL', 'Close')
SRP_COM(objConnection, 'RELEASE')
If SRP_COM('', 'ERROR') then
Error = SRP_COM('', 'ERROR')
end else
Destroyed = True$
end
If Destroyed then
SQL_Services('ClearConnectionErrors', objConnection)
Server = Memory_Services('GetValue', objConnection : '*Server')
Memory_Services('SetValue', ServiceModule : '*GetConnectionObject*' : Server, '')
end else
SQL_Services('AddConnectionErrors', objConnection, Error)
Error_Services('Add', 'Service : ' : Service : ', Error : ' : Error)
end
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
end else
If objConnection NE '' then
ConnObjIndex = SRP_List('Locate', ConnectionObjects@, objConnection)
If ConnObjIndex GT 0 then
Error = ''
ClientConnectionID = Get_Property.NET(objConnection, 'ClientConnectionId', False$)
// Close the connection object, but don't worry about errors. It might have already been closed.
Set_Status(0)
Sql_Services('ClearConnectionErrors', objConnection)
rv = Send_Message.Net(objConnection, 'Close')
errCode = ''
If Not(Get_Status(errCode)) then
Server = Memory_Services('GetValue', ClientConnectionID : '*Server')
MemKey = ServiceModule : '*GetConnectionObject*' : Server : '*objConnection'
Memory_Services('SetValue', MemKey, '')
SRP_List('RemoveAt', ConnectionObjects@, ConnObjIndex)
Free_Class.Net(objConnection)
end else
Error = 'Error in service ':Service:'. Failed to close SQL connection. Error code: ':errCode
Sql_Services('AddConnectionErrors', objConnection, Error)
Error_Services('Add', 'Service : ' : Service : ', Error : ' : Error)
end
end
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
end
Response = Destroyed
end service
//----------------------------------------------------------------------------------------------------------------------
// AddConnectionErrors
//
// objConnection - Connection Object (see GetConnectionObject service.)
// ErrorList - @FM delimited list of errors.
//
// Adds a list of errors to the indicated Connection Object so the GetConnectionErrors service can retrieve them at
// will. This list will accumulate until the ClearConnectionErrors service is called.
//----------------------------------------------------------------------------------------------------------------------
Service AddConnectionErrors(objConnection, ErrorList)
If UseRevDotNet EQ False$ then
objConnection = objConnection[1, '*']
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : objConnection
ConnectionErrors = Memory_Services('GetValue', ServiceKeyID)
If (objConnection NE '') AND (ErrorList NE '') then
If ConnectionErrors NE '' then
ConnectionErrors := @FM : ErrorList
end else
ConnectionErrors = ErrorList
end
Memory_Services('SetValue', ServiceKeyID, ConnectionErrors)
end else
Error_Services('Add', 'The objConnection or ErrorList argument was missing in the ' : Service : ' service.')
end
end else
objConnection = objConnection[1, '*']
ClientConnectionID = Get_Property.NET(objConnection, 'ClientConnectionId', False$)
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : ClientConnectionID
ConnectionErrors = Memory_Services('GetValue', ServiceKeyID)
If (objConnection NE '') AND (ErrorList NE '') then
If ConnectionErrors NE '' then
ConnectionErrors := @FM : ErrorList
end else
ConnectionErrors = ErrorList
end
Memory_Services('SetValue', ServiceKeyID, ConnectionErrors)
end else
Error_Services('Add', 'The objConnection or ErrorList argument was missing in the ' : Service : ' service.')
end
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetConnectionErrors
//
// objConnection - Connection Object (see GetConnectionObject service.)
//
// Returns an @FM list of all connection errors associated with the indicated Connection Object.
//----------------------------------------------------------------------------------------------------------------------
Service GetConnectionErrors(objConnection)
If UseRevDotNet EQ False$ then
objConnection = objConnection[1, '*']
ConnectionErrors = ''
If objConnection NE '' then
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : objConnection
ConnectionErrors = Memory_Services('GetValue', ServiceKeyID)
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
Response = ConnectionErrors
end else
objConnection = objConnection[1, '*']
ConnectionErrors = ''
If objConnection NE '' then
ClientConnectionID = Get_Property.NET(objConnection, 'ClientConnectionId', False$)
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : ClientConnectionID
ConnectionErrors = Memory_Services('GetValue', ServiceKeyID)
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
Response = ConnectionErrors
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ClearConnectionErrors
//
// objConnection - Connection Object (see GetConnectionObject service.)
//
// Clears all connection errors associated with the indicated Connection Object.
//----------------------------------------------------------------------------------------------------------------------
Service ClearConnectionErrors(objConnection)
If UseRevDotNet EQ False$ then
objConnection = objConnection[1, '*']
If objConnection NE '' then
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : objConnection
Memory_Services('SetValue', ServiceKeyID, '')
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
end else
objConnection = objConnection[1, '*']
If objConnection NE '' then
ClientConnectionID = Get_Property.NET(objConnection, 'ClientConnectionId', False$)
ServiceKeyID = ServiceModule : '*' : 'GetConnectionErrors' : '*' : ClientConnectionID
Memory_Services('SetValue', ServiceKeyID, '')
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
end
end service
//----------------------------------------------------------------------------------------------------------------------
// HasConnectionErrors
//
// objConnection - Connection Object (see GetConnectionObject service.)
//
// Returns a Boolean flag indicating of the Connection Object has any connection errors.
//----------------------------------------------------------------------------------------------------------------------
Service HasConnectionErrors(objConnection)
objConnection = objConnection[1, '*']
HasErrors = False$ ; // Assume no errors for now.
If objConnection NE '' then
ConnectionErrors = SQL_Services('GetConnectionErrors', objConnection)
If ConnectionErrors NE '' then
HasErrors = True$
end else
HasErrors = False$
end
end else
Error_Services('Add', 'The objConnection argument was missing in the ' : Service : ' service.')
end
Response = HasErrors
end service
//----------------------------------------------------------------------------------------------------------------------
// GetConnectionString
//
// Returns a well formed Connection String for the current server. This is used for ADO connections.
//----------------------------------------------------------------------------------------------------------------------
Service GetConnectionString(Server)
If UseRevDotNet EQ False$ then
ServiceKeyID := '*' : Server
ConnectionString = Memory_Services('GetValue', ServiceKeyID)
If ConnectionString EQ '' then
If (Server NE '') then
ConnectionInfo = Database_Services('ReadDataRow', 'SERVERS', Server)
If ConnectionInfo NE '' then
Swap \0D0A\ with @FM in ConnectionInfo
ConnectionString = ConnectionInfo<3>
ConnectionString := ';'
Memory_Services('SetValue', ServiceKeyID, ConnectionString)
end else
Error_Services('Add', Server : ' is not a valid server. [' : Service : ']')
end
end else
Error_Services('Add', 'The Server argument was missing in the ' : Service : ' service.')
end
end
Response = ConnectionString
end else
If (Server NE '') then
// Prod Stealth
ConnectionString = Database_Services('ReadDataRow', 'SERVERS', Server)
If ConnectionString NE '' then
ConnectionString = Delete(ConnectionString, 2, 0, 0)
ProviderIdx = IndexC(ConnectionString, 'Provider', 1)
If ProviderIdx then
ConnectionString = ConnectionString[(ProviderIdx), 999]
ProviderEndIdx = Index(ConnectionString, ';', 1)
ConnectionString = ConnectionString[(ProviderEndIdx + 1), 999]
end
InitialIdx = IndexC(ConnectionString, 'Initial File Name', 1)
If InitialIdx then
InitialLen = Len(ConnectionString[InitialIdx, 'F;'])
ConnectionString[InitialIdx, InitialLen + 1] = ''
end
DataSourceIdx = IndexC(ConnectionString, 'Data Source', 1)
If DataSourceIdx then
ConnectionString[DataSourceIdx + 12, 0] = 'tcp:'
end
TrustIdx = IndexC(ConnectionString, 'Trust Server Certificate', 1)
If TrustIdx then
TrustLen = Len(ConnectionString[TrustIdx, 'F;'])
ConnectionString[TrustIdx, TrustLen + 1] = ''
end
AccessIdx = IndexC(ConnectionString, 'Access Token', 1)
If AccessIdx then
AccessLen = Len(ConnectionString[AccessIdx, 'F;'])
ConnectionString[AccessIdx, AccessLen + 1] = ''
end
AuthIdx = IndexC(ConnectionString, 'Authentication', 1)
If AuthIdx then
AuthLen = Len(ConnectionString[AuthIdx, 'F;'])
ConnectionString[AuthIdx, AuthLen + 1] = ''
end
SpnIdx = IndexC(ConnectionString, 'Server SPN', 1)
If SpnIdx then
SpnLen = Len(ConnectionString[SpnIdx, 'F;'])
ConnectionString[SpnIdx, SpnLen + 1] = ''
end
If ConnectionString[-1, 1] EQ ';' then ConnectionString[-1, 1] = ''
end else
Error_Services('Add', Server : ' is not a valid server. [' : Service : ']')
end
end else
Error_Services('Add', 'The Server argument was missing in the ' : Service : ' service.')
end
Response = ConnectionString
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ExecuteQuery
//
// objConnection - Connection Object (see GetConnectionObject service.)
// QueryStatement - Query command. This should be a properly syntaxed SQL statement.
// ReturnDataRows - Boolean flag to determine if all data rows resulting from the query should automatically be
// returned. This is the same as if the caller used the GetAllQueryDataRows service, but this allows
// everything to be done in one service rather than two. Default is False$
//
// Executes the query against the Connection Object. If the ReturnDataRows argument is False$, then this returns True$
// if there are results, False$ if there are no results or if there is a problem running the services. Otherwise, the
// datarows from the query will be returned unless there is an error.
//----------------------------------------------------------------------------------------------------------------------
Service ExecuteQuery(objConnection, QueryStatement, ReturnDataRows=BOOLEAN, AttemptsBeforeFailure)
If AttemptsBeforeFailure EQ '' then AttemptsBeforeFailure = 1
Results = False$ ; // Assume no results from this query for now.
If ReturnDataRows NE True$ then ReturnDataRows = False$
ErrorMessage = ''
If UseRevDotNet EQ False$ then
If (objConnection NE '') AND (QueryStatement NE '') then
Attempts = 0
ErrorMessage = ''
Loop
objRecordSet = SRP_COM(objConnection, 'CALL', 'Execute', QueryStatement)
If SRP_COM('', 'ERROR') OR (objRecordSet EQ 0) then
ErrorMessage = 'ADO error in the ' : Service : ' service: ' : SRP_COM('', 'ERROR')
Results = '' ; // Since there is an error, no result should be returned.
end else
If ReturnDataRows then
Results = SQL_Services('GetAllQueryDataRows', objRecordSet)
end else
Results = True$
end
SRP_COM(objRecordSet, 'CALL', 'Cancel')
SRP_COM(objRecordSet, 'RELEASE')
end
Attempts += 1
Until ( (ErrorMessage EQ '') OR (Attempts GE AttemptsBeforeFailure) )
Repeat
end else
Error_Services('Add', 'The objConnection or QueryStatement argument was missing in the ' : Service : ' service.')
end
end else
If (objConnection NE '') AND (QueryStatement NE '') then
Attempts = 0
ConnObjIndex = SRP_List('Locate', ConnectionObjects@, objConnection)
If ConnObjIndex GT 0 then
Loop
objCommand = Send_Message.Net(objConnection, 'CreateCommand', '', '', 1)
If Not(Get_Status(errCode)) then
rv = Set_Property.NET(objCommand, 'CommandText', QueryStatement)
If Not(Get_Status(errCode)) then
If ReturnDataRows then
objReader = Send_Message.Net(objCommand, 'ExecuteReader', '', '', 1)
If Not(Get_Status(errCode)) then
Reading = ''
RowIndex = 0
Loop
RowData = ''
RowIndex += 1
Reading = Send_Message.Net(objReader, 'Read')
Until ( (Reading EQ 'False') or (ErrorMessage NE '') )
If Not(Get_Status(errCode)) then
NumCols = Get_Property.Net(objReader, 'FieldCount')
If Not(Get_Status(errCode)) then
For Col = 1 to NumCols
DotNetObj = Send_Message.Net(objReader, 'GetValue', (Col - 1), 'System.Int32', 1)
If Not(Get_Status(errCode)) then
Result = Send_Message.Net(DotNetObj, 'ToString')
If (Result EQ 'True' or Result EQ 'False') then
DotNetObjType = Send_Message.Net(DotNetObj, 'GetType')
If DotNetObjType EQ 'System.Boolean' then
Swap 'True' with 1 in Result
Swap 'False' with 0 in Result
end
end
RowData<0, Col> = Result
If Get_Status(errCode) then
ErrorMessage = 'Error calling ToString method in the Object object in the ' : Service : ' service.' : errCode
end
end else
ErrorMessage = 'Error calling GetValue method in the SqlDataReader object in the ' : Service : ' service.' : errCode
end
If Assigned(DotNetObj) then Free_Class.NET(DotNetObj)
Until Error EQ True$
Next Col
end else
ErrorMessage = 'Error getting FieldCount property of the SqlDataReader in the ' : Service : ' service.' : errCode
end
end else
ErrorMessage = 'Error calling Read method in the SqlDataReader object in the ' : Service : ' service.' : errCode
end
Results<RowIndex> = RowData
Repeat
If Reading EQ 'False' and RowIndex EQ 1 then Results = '' ; // No results
end else
AccessError = (IndexC(errCode, 'not able to access the database', 1) GT 0)
If Not(AccessError) then ErrorMessage = 'Error creating SqlDataReader object in the ' : Service : ' service.' : errCode
end
Swap @FM with @RM in Results
Swap @VM with @FM in Results
If Assigned(objReader) and (objReader NE '') then
rv = Send_Message.Net(objReader, 'Close')
Free_Class.NET(objReader)
end
end else
objTransaction = Send_Message.Net(objConnection, 'BeginTransaction', '', '', 1)
If Not(Get_Status(errCode)) then
rv = Set_Property.NET(objCommand, 'Transaction', objTransaction)
If Not(Get_Status(errCode)) then
Results = Send_Message.Net(objCommand, "ExecuteScalar")
If Not(Get_Status(errCode)) then
rv = Send_Message.Net(objTransaction, 'Commit')
If Get_Status(errCode) then
AllAccepted = False$
ErrorMessage = 'Error committing transaction in the ' : Service : ' service.' : errCode
end else
Results = True$
end
end else
ErrorMessage = 'Failed to execute SQL command in the ' :Service : 'service.' : errCode
end
end else
ErrorMessage = 'Unable to set Transaction property of the SqlCommand object in the ' : Service : ' service: ' : errCode
end
end else
ErrorMessage = 'Unable to create the SQLTransaction object in the ' : Service : ' service: ' : errCode
end
end
end else
ErrorMessage = 'Unable to set CommandText property of the SQLCommand object in the ' : Service : ' service: ' : errCode
end
If Assigned(objTransaction) then Free_Class.NET(objTransaction)
If Assigned(objCommand) then Free_Class.NET(objCommand)
end else
ErrorMessage = 'Unable to create the SQLCommand object in the ' : Service : ' service: ' : errCode
end
Attempts += 1
Until ( (ErrorMessage EQ '') or (Attempts GE AttemptsBeforeFailure) )
Repeat
end else
ErrorMessage = 'objCommand could not be found in the ' : Service : ' service.'
end
end else
ErrorMessage = 'The objConnection or QueryStatement argument was missing in the ' : Service : ' service.'
end
If ErrorMessage NE '' then
Results = ''
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = QueryStatement
LogData<3> = ErrorMessage
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Swap @FM with @VM in ErrorMessage
Error_Services('Add', ErrorMessage)
end
end
Response = Results
end service
//----------------------------------------------------------------------------------------------------------------------
// ExecuteQueries
//
// objConnection - Connection Object (see GetConnectionObject service.)
// QueryStatements - @FM delimited list of Query commands. These should be a properly syntaxed SQL statement.
//
// Executes one or more queries against the Connection Object. This returns True$ if all queries processed without any
// errors, False$ if there is a problem running any of the queries.
//----------------------------------------------------------------------------------------------------------------------
Service ExecuteQueries(objConnection, QueryStatements, UseTransactionControl=BOOLEAN, OITableName, OIKeyID)
If UseTransactionControl NE True$ then UseTransactionControl = False$
AllAccepted = True$ ; // Assume all queries were accepted for now unless otherwise proven.
ErrorMessage = ''
If UseRevDotNet EQ False$ then
If (objConnection NE '') AND (QueryStatements NE '') then
*Message = '1. Begin transaction processing.' ; GoSub WriteLog
If UseTransactionControl EQ True$ then
// Begin transaction processing.
objRecordSet = SRP_COM(objConnection, 'CALL', 'Execute', 'BEGIN TRANSACTION')
*Message = '2. Begin transaction processing.' ; GoSub WriteLog
If SRP_COM('', 'ERROR') OR (objRecordSet EQ 0) then
*Message = '3a. Begin transaction processing.' ; GoSub WriteLog
Error_Services('Add', 'ADO error in the ' : Service : ' service: ' : SRP_COM('', 'ERROR'))
end else
*Message = '3b. Begin transaction processing.' ; GoSub WriteLog
SRP_COM(objRecordSet, 'RELEASE')
end
end
*Message = '4. Begin transaction processing.' ; GoSub WriteLog
If Error_Services('NoError') then
*Message = '5. Begin execute call.' ; GoSub WriteLog
For Each QueryStatement in QueryStatements using @FM
If QueryStatement NE '' then
*Message = '6. Begin execute call.' ; GoSub WriteLog
objRecordSet = SRP_COM(objConnection, 'CALL', 'Execute', QueryStatement)
If SRP_COM('', 'ERROR') OR (objRecordSet EQ 0) then
*Message = '7a. Begin execute call.' ; GoSub WriteLog
Error_Services('Add', 'ADO error in the ' : Service : ' service: ' : SRP_COM('', 'ERROR'))
AllAccepted = False$
end else
*Message = '7b. Begin execute call.' ; GoSub WriteLog
SRP_COM(objRecordSet, 'RELEASE')
end
end
Until Error_Services('HasError')
Next QueryStatement
end
*Message = '8. Begin execute call.' ; GoSub WriteLog
If UseTransactionControl EQ True$ then
// COMMIT or ROLLBACK the transaction.
*Message = '9. Begin execute call.' ; GoSub WriteLog
If Error_Services('NoError') then
*Message = '10a. Begin execute call.' ; GoSub WriteLog
objRecordSet = SRP_COM(objConnection, 'CALL', 'Execute', 'COMMIT TRANSACTION')
end else
*Message = '10b. Begin execute call.' ; GoSub WriteLog
AllAccepted = False$
objRecordSet = SRP_COM(objConnection, 'CALL', 'Execute', 'ROLLBACK TRANSACTION')
SRP_COM(objRecordSet, 'RELEASE')
end
*Message = '11. Begin execute call.' ; GoSub WriteLog
SRP_COM(objRecordSet, 'RELEASE')
end
end else
*Message = '12. All accepted not true.' ; GoSub WriteLog
AllAccepted = False$
Error_Services('Add', 'The objConnection or QueryStatement argument was missing in the ' : Service : ' service.')
end
end else
If (objConnection NE '') AND (QueryStatements NE '') then
ConnObjIndex = SRP_List('Locate', ConnectionObjects@, objConnection)
If ConnObjIndex GT 0 then
objCommand = Send_Message.Net(objConnection, 'CreateCommand', '', '', 1)
If Not(Get_Status(errCode)) then
objTransaction = Send_Message.Net(objConnection, 'BeginTransaction', 'Test', 'System.String', 1)
If Not(Get_Status(errCode)) then
rv = Set_Property.NET(objCommand, 'Transaction', objTransaction)
If Not(Get_Status(errCode)) then
For Each QueryStatement in QueryStatements using @FM
If QueryStatement NE '' then
rv = Set_Property.Net(objCommand, 'CommandText', QueryStatement)
If Not(Get_Status(errCode)) then
rv = Send_Message.Net(objCommand, 'ExecuteNonQuery')
If Get_Status(errCode) then
ErrorMessage = 'Error executing command ':Quote(QueryStatement):' in the ' : Service : ' service.' : errCode
end
end else
ErrorMessage = 'Error setting CommandText property of the SqlCommand object in the ' : Service : ' service.' : errCode
end
end
Until ErrorMessage NE ''
Next QueryStatement
end else
ErrorMessage = 'Unable to set Transaction property of the SqlCommand object in the ' : Service : ' service. ' : errCode
end
end else
ErrorMessage = 'Unable to create the SQLTransaction object in the ' : Service : ' service. ' : errCode
end
end else
ErrorMessage = 'Unable to create the SQLCommand object in the ' : Service : ' service. ' : errCode
end
If UseTransactionControl EQ True$ then
// COMMIT or ROLLBACK the transaction.
If ErrorMessage EQ '' then
rv = Send_Message.Net(objTransaction, 'Commit')
If Get_Status(errCode) then
AllAccepted = False$
ErrorMessage = 'Error committing transaction in the ' : Service : ' service.' : errCode
end
end else
AllAccepted = False$
rv = Send_Message.Net(objTransaction, 'Rollback')
end
end
If Assigned(objTransaction) then Free_Class.NET(objTransaction)
If Assigned(objCommand) then Free_Class.NET(objCommand)
end
end else
AllAccepted = False$
ErrorMessage = 'The objConnection or QueryStatement argument was missing in the ' : Service : ' service.'
end
If ErrorMessage NE '' then
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = OITableName
LogData<3> = OIKeyID
LogData<4> = ErrorMessage
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Swap @FM with ',' in ErrorMessage
Error_Services('Add', ErrorMessage)
end
end
Response = AllAccepted
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAllQueryDataRows
//
// objRecordSet - RecordSet Object (see ExecuteQuery service.)
//
// Gets all of the data rows from the RecordSet Object. This returns an @RM array of data rows.
//----------------------------------------------------------------------------------------------------------------------
Service GetAllQueryDataRows(objRecordSet)
DataRows = ''
If Len(objRecordSet) then
BOF = SRP_COM(objRecordSet, 'GET', 'BOF')
EOF = SRP_COM(objRecordSet, 'GET', 'EOF')
If (EOF EQ False$) then
DataRows = SRP_COM(objRecordSet, 'CALL', 'GetString', 2, -1, @FM, @RM)
If SRP_COM('', 'ERROR') then
Error = SRP_COM('', 'ERROR')
Error_Services('Add', 'ADO error in the ' : Service : ' service: ' : SRP_COM('', 'ERROR'))
end
If Error_Services('NoError') then
If DataRows[-1, 1] EQ @RM then DataRows[-1, 1] = ''
If DataRows EQ objRecordSet then
DataRows = ''
Error_Services('Add', 'Unknown ADO error in the ' : Service : ' service.')
end else
If SRP_COM('', 'ERROR') then
Error = SRP_COM('', 'ERROR')
If IndexC(Error, 'current record has been deleted', 1) then
DataRows = ''
end else
Error_Services('Add', 'ADO error in the ' : Service : ' service: ' : SRP_COM('', 'ERROR'))
end
end
end
end
end
end else
Error_Services('Add', 'The objRecordSet argument was missing in the ' : Service : ' service.')
end
Response = DataRows
end service
//----------------------------------------------------------------------------------------------------------------------
// GetServers
//
// Returns an @FM list of database servers.
//----------------------------------------------------------------------------------------------------------------------
Service GetServers()
Servers = ''
hServers = Database_Services('GetTableHandle', 'SERVERS')
If Error_Services('NoError') then
Select hServers
EOF = False$
Loop
Readnext ServerID else EOF = True$
Until EOF
Servers := ServerID : @FM
Repeat
Servers[-1, 1] = ''
Servers = SRP_Array('SortRows', Servers, 'AL1', 'LIST', @FM, @VM)
end
Response = Servers
end service
//----------------------------------------------------------------------------------------------------------------------
// SaveConnectionString
//
// ServerID - Key ID to a row in the SERVERS database table.
// ConnectionString - SQL server connection string
//
// If a row in the SERVERS table with the key ServerID exists, updates the connection string, otherwise a new row
// within the SERVERS database table containing ConnectionString.
//----------------------------------------------------------------------------------------------------------------------
Service SaveConnectionString(ServerName, ConnectionString)
If ServerName NE '' then
ServerRec = Database_Services('ReadDataRow', 'SERVERS', ServerName)
ServerRec<SERVERS.CONNECTION_STRING$> = ConnectionString
Database_Services('WriteDataRow', 'SERVERS', ServerName, ServerRec, True$, False$, True$)
end else
ErrorMsg = 'Error saving connection. Null server name passed in to the ' : Service : ' service.'
Error_Services('Add', ErrorMsg)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// CreateNewConnectionString
//
// Utilizes the Windows Data Link Properties utility to create a new connection string.
// Returns a field mark delimited array containing a suggested server name (the data source) and the connection string
// generated by the Windows Data Link Properties utility.
//----------------------------------------------------------------------------------------------------------------------
Service CreateNewConnectionString()
Response = ''
ServerName = ''
ConnectionString = ''
OleDBString = ''
Filename = 'temp.udl'
TempPath = Str(\00\, 1024)
GetTempPath(Len(TempPath), TempPath)
Convert \00\ to '' in TempPath
TempFilename = Str(\00\, 1024)
GetTempFileName(TempPath, \00\, 0, TempFilename)
OSWrite OleDBString to TempFilename
UDLFile = 'C:\Windows\syswow64\rundll32.exe "C:\Program Files (x86)\Common Files\System\Ole DB\oledb32.dll",OpenDSLFile ' : TempFilename
Mode = '-1' ;* modal
rv = Utility('RUNWIN', UDLFile, Mode)
OSRead ConnectionString from TempFilename then
If ConnectionString NE '' then
Convert \FFFE\ to '' in ConnectionString
ConnectionString = Unicode_UTF8(ConnectionString)
DataSourcePos = Index(ConnectionString, 'Data Source', 1)
ServerPos = Index(ConnectionString, 'Server', 1)
Begin Case
Case DataSourcePos
ServerName = ConnectionString[(DataSourcePos + Len('Data Source') + 1), 'F;']
Case ServerPos
ServerName = ConnectionString[(ServerPos + Len('Server') + 1), 'F;']
End Case
end
end
Response = ServerName : @FM : ConnectionString
end service
//----------------------------------------------------------------------------------------------------------------------
// EditConnection
//
// ServerID - Key ID for the SERVERS database table.
//
// Utilizes the Windows Data Link Properties utility to edit the connection string found in the SERVERS record
// associated with the ServerID key.
//----------------------------------------------------------------------------------------------------------------------
Service EditConnection(ServerID)
If ServerID NE '' then
ServerRec = Database_Services('ReadDataRow', 'SERVERS', ServerID)
If Error_Services('NoError') then
ConnectionString = ServerRec<SERVERS.CONNECTION_STRING$>
TempPath = Str(\00\, 1024)
GetTempPath(Len(TempPath), TempPath)
TempFilename = Str(\00\, 1024)
GetTempFileName(TempPath, \00\, 0, TempFilename)
If ConnectionString NE '' then
UnicodeString = \FFFE\ : Str_Unicode(ConnectionString)
OSWrite UnicodeString To TempFilename
end else
OSWrite '' to TempFileName
end
Program = 'C:\Windows\syswow64\rundll32.exe "C:\Program Files (x86)\Common Files\System\Ole DB\oledb32.dll",OpenDSLFile ':TempFilename
Mode = '-1' ;* modal
rv = Utility("RUNWIN", Program, Mode)
NewFile = ''
OSRead NewConnectionString from TempFilename then
Convert \FFFE\ to '' in NewConnectionString
NewConnectionString = Unicode_UTF8(NewConnectionString)
ServerRec<SERVERS.CONNECTION_STRING$> = NewConnectionString
Database_Services('WriteDataRow', 'SERVERS', ServerID, ServerRec, True$, False$, True$)
end
end
end
end service
//----------------------------------------------------------------------------------------------------------------------
// DeleteConnection
//
// ServerID - Key ID for the SERVERS database table.
//
// Deletes the SERVERS record associated with the ServerID key.
//----------------------------------------------------------------------------------------------------------------------
Service DeleteConnection(ServerID)
If ServerID NE '' then
Database_Services('DeleteDataRow', 'SERVERS', ServerID, True$)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetConnectionDesc
//
// ServerID - Key ID for the SERVERS database table.
// Description - Description of the server connection
//
// Sets the DESCRIPTION column of the SERVERS record associated with the ServerID key.
//----------------------------------------------------------------------------------------------------------------------
Service SetConnectionDesc(ServerID, Description)
If ServerID NE '' then
ServerRec = Database_Services('ReadDataRow', 'SERVERS', ServerID)
ServerRec<SERVERS.DESCRIPTION$> = Description
Database_Services('WriteDataRow', 'SERVERS', ServerID, ServerRec)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetOITableToSQLMap
//
// TableName - OpenInsight table being mapped. - [Required]
// SQLMap - JSON object containing the OI Table to SQL Map information. - [Required]
//
// Updates the stored JSON object that defines the mapping between the indicated OpenInsight table and the SQL table.
//----------------------------------------------------------------------------------------------------------------------
Service SetOITableToSQLMap(TableName, SQLMap)
Convert @Lower_Case to @Upper_Case in TableName
ServiceKeyID = ServiceModule : '*' : 'GetOITableToSQLMap' : '*' : TableName
If (TableName NE '') AND (SQLMap NE '') then
Convert \0D0A\ to @FM in SQLMap ; // Makes it easier to inspect. The GetOITableToSQLMap service removes the @FMs.
Database_Services('WriteDataRow', 'DICT.' : TableName, '%SQLMap%', SQLMap, True$)
If Error_Services('NoError') then
Convert @FM to '' in SQLMap
Memory_Services('SetValue', ServiceKeyID, SQLMap)
end
end else
Error_Services('Add', 'The TableName or SQLMap argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetOITableToSQLMap
//
// TableName - OpenInsight table being mapped. - [Required]
//
// Returns JSON object that defines the mapping between the indicated OpenInsight table and the SQL table.
//----------------------------------------------------------------------------------------------------------------------
Service GetOITableToSQLMap(TableName)
Convert @Lower_Case to @Upper_Case in TableName
ServiceKeyID := '*' : TableName
OITableToSQLMap = Memory_Services('GetValue', ServiceKeyID)
If OITableToSQLMap EQ '' then
If TableName NE '' then
OITableToSQLMap = Database_Services('ReadDataRow', 'DICT.' : TableName, '%SQLMap%')
Convert @FM to '' in OITableToSQLMap
If OITableToSQLMap NE '' then
Memory_Services('SetValue', ServiceKeyID, OITableToSQLMap)
end
end else
Error_Services('Add', 'The TableName argument was missing in the ' : Service : ' service.')
end
end
Response = OITableToSQLMap
end service
//----------------------------------------------------------------------------------------------------------------------
// SetOIColumnToSQLMap
//
// TableName - OpenInsight table being mapped. - [Required]
// ColumnName - Database column from the OpenInsight table. - [Required]
// SQLMap - JSON object containing the OI Column to SQL Map information. - [Required]
//
// Updates the stored JSON object that defines the mapping between the indicated OpenInsight column and the SQL table.
//----------------------------------------------------------------------------------------------------------------------
Service SetOIColumnToSQLMap(TableName, ColumnName, SQLMap)
Convert @Lower_Case to @Upper_Case in TableName
Convert @Lower_Case to @Upper_Case in ColumnName
ServiceKeyID = ServiceModule : '*' : 'GetOIColumnToSQLMap' : '*' : TableName : '*' : ColumnName
If (TableName NE '') AND (ColumnName NE '') AND (SQLMap NE '') then
Convert @FM to '' in SQLMap
Convert \0D0A\ to '' in SQLMap
ColumnData = Database_Services('ReadDataRow', 'DICT.' : TableName, ColumnName)
ColumnData<DICT_USER1$> = SQLMap
Database_Services('WriteDataRow', 'DICT.' : TableName, ColumnName, ColumnData, True$)
If Error_Services('NoError') then
Memory_Services('SetValue', ServiceKeyID, SQLMap)
end
end else
Error_Services('Add', 'The TableName, ColumnName, or SQLMap argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAllOIColumnToSQLMaps
//
// TableName - OpenInsight table being mapped. - [Required]
//
// Returns an @FM/@VM delimited array of all JSON objects that define the mapping being the table columns and their
// respective SQL table columns. Columns with no maps will return an empty string for the JSON object.
//----------------------------------------------------------------------------------------------------------------------
Service GetAllOIColumnToSQLMaps(TableName)
Convert @Lower_Case to @Upper_Case in TableName
ColumnSQLMaps = ''
If TableName NE '' then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : TableName, '%FIELDS%')
ColumnNames = FieldArray<FIELDS_NAME$>
For Each ColumnName in ColumnNames using @VM
SQLMap = SQL_Services('GetOIColumnToSQLMap', TableName, ColumnName)
ColumnSQLMaps := ColumnName : @VM
If SQLMap NE '' then
ColumnSQLMaps := SQLMap
end
ColumnSQLMaps := @FM
Next ColumnName
ColumnSQLMaps[-1, 1] = ''
end else
Error_Services('Add', 'The TableName argument was missing in the ' : Service : ' service.')
end
Response = ColumnSQLMaps
end service
//----------------------------------------------------------------------------------------------------------------------
// GetOIColumnToSQLMap
//
// TableName - OpenInsight table being mapped. - [Required]
// ColumnName - Database column from the OpenInsight table. - [Required]
//
// Returns JSON object that defines the mapping between the indicated OpenInsight table column and the SQL table column.
//----------------------------------------------------------------------------------------------------------------------
Service GetOIColumnToSQLMap(TableName, ColumnName)
Convert @Lower_Case to @Upper_Case in TableName
Convert @Lower_Case to @Upper_Case in ColumnName
ServiceKeyID := '*' : TableName : '*' : ColumnName
OIColumnToSQLMap = Memory_Services('GetValue', ServiceKeyID)
If OIColumnToSQLMap EQ '' then
If (TableName NE '') AND (ColumnName NE '') then
ColumnData = Database_Services('ReadDataRow', 'DICT.' : TableName, ColumnName)
OIColumnToSQLMap = ColumnData<DICT_USER1$>
If OIColumnToSQLMap NE '' then
Memory_Services('SetValue', ServiceKeyID, OIColumnToSQLMap)
end
end else
Error_Services('Add', 'The TableName or ColumnName argument was missing in the ' : Service : ' service.')
end
end
Response = OIColumnToSQLMap
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedSQLServer
//
// Returns the name of the SQL Server that the indicated OpenInsight table is mapped to.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedSQLServer(OITableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName
SQLServer = Memory_Services('GetValue', ServiceKeyID)
If SQLServer EQ '' then
If OITableName NE '' then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
SQLServer = SRP_JSON(MapObj, 'GETVALUE', 'SQLServer.Name')
SRP_JSON(MapObj, 'RELEASE')
end
If SQLServer NE '' then Memory_Services('SetValue', ServiceKeyID, SQLServer)
end else
Error_Services('Add', 'OITableName argument was missing in the ' : Service : ' service.')
end
end
Response = SQLServer
end service
//----------------------------------------------------------------------------------------------------------------------
// GetDatabases
//
// objConnection - Connection Object (see GetConnectionObject service.) - [Optional, but Server is then Required]
// Server - Name of a defined server. - [Optional, but objConnection is then Required]
//
// Returns an @FM list of databases available through the indicated connection object. If the connection object is
// empty, then a new one will be created (and then subsequently destroyed) for the indicated server.
//----------------------------------------------------------------------------------------------------------------------
Service GetDatabases(objConnection, Server)
Databases = ''
If (objConnection NE '') OR (Server NE '') then
If objConnection EQ '' then
objConnection = SQL_Services('GetConnectionObject', Server, 3)
NewObject = True$
end else
NewObject = False$
end
If Error_Services('NoError') then
SQLQuery = "SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb')"
Databases = SQL_Services('ExecuteQuery', objConnection, SQLQuery, True$)
If Databases EQ 0 then
Databases = ''
Error_Services('Add', 'Unknown error in the ' : Service : ' service for server ' : Server : '.')
end else
Convert @RM to @FM in Databases
end
end
If NewObject EQ True$ then
SQL_Services('DestroyConnectionObject', objConnection)
end
end else
Error_Services('Add', 'objConnection and Server arguments were both missing in the ' : Service : ' service.')
end
Response = Databases
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSchemas
//
// objConnection - Connection Object (see GetConnectionObject service.) - [Optional, but Server is then Required]
// Server - Name of a defined server. - [Optional, but objConnection is then Required]
// Database - Name of a specific database to use. If empty, then all databases will be used. - [Required]
//
// Returns an @FM list of schemas available for the indicated database. If the connection object is empty, then a new
// one will be created (and then subsequently destroyed) for the indicated server.
//----------------------------------------------------------------------------------------------------------------------
Service GetSchemas(objConnection, Server, Database)
Schemas = ''
If Database NE '' then
If (objConnection NE '') OR (Server NE '') then
If objConnection EQ '' then
objConnection = SQL_Services('GetConnectionObject', Server, 3)
NewObject = True$
end else
NewObject = False$
end
If Error_Services('NoError') then
SQLQuery = "SELECT DISTINCT TABLE_SCHEMA FROM [" : Database : "].INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
Schemas = SQL_Services('ExecuteQuery', objConnection, SQLQuery, True$)
If Error_Services('NoError') then
Convert @RM to @FM in Schemas
end else
Message = Error_Services('GetMessage')
If IndexC(Message, 'not able to access the database', 1) AND IndexC(Message, 'under the current security context', 1) then
// Users does not have permission. Clear the error rather than report it.
Error_Services('Clear')
end
end
end
If NewObject EQ True$ then
ErrorMessage = Error_Services('GetMessage')
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
end
end else
Error_Services('Add', 'objConnection and Server arguments were both missing in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'Database argument was missing in the ' : Service : ' service.')
end
Response = Schemas
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTables
//
// objConnection - Connection Object (see GetConnectionObject service.) - [Optional, but Server is then Required]
// Server - Name of a defined server. - [Optional, but objConnection is then Required]
// Databases - @FM delimited list of databases to use. If empty, then all databases will be used.
// - [Optional]
// Schemas - @FM delimited list of schemas to use. If empty, then all schemas will be used. If Databases is
// empty, then Schemas will be ignored. - [Optional]
// ReturnFullObjects - Boolean flag to indicate if full object notation (e.g., Server.Database.Schema.Table) should
// be returned or just the tables. Default is False$ - [Optional]
// BracketObjects - Boolean flag to indicate if the objects being returned should be bracketed in case some of the
// object names are reserved words. Default is False$ - [Optional]
//
// Returns an @FM list of tables using full object name formatting (i.e., Database.Schema.Table) available for the
// indicated connection object (or server). If the connection object is empty, then a new one will be created (and then
// subsequently destroyed) for the indicated server.
//----------------------------------------------------------------------------------------------------------------------
Service GetTables(objConnection, Server, Databases, Schemas, IncludeServerObject=BOOLEAN, IncludeDatabaseObject=BOOLEAN, IncludeSchemaObject=BOOLEAN, BracketObjects=BOOLEAN)
Tables = ''
If IncludeServerObject NE True$ then IncludeServerObject = False$
If IncludeDatabaseObject NE True$ then IncludeDatabaseObject = False$
If IncludeSchemaObject NE True$ then IncludeSchemaObject = False$
If BracketObjects NE True$ then BracketObjects = False$
If Databases EQ '' then Schemas = ''
If (objConnection NE '') OR (Server NE '') then
If objConnection EQ '' then
objConnection = SQL_Services('GetConnectionObject', Server, 3)
NewObject = True$
end else
NewObject = False$
end
If Error_Services('NoError') then
If Databases EQ '' then Databases = SQL_Services('GetDatabases', objConnection, Server)
* If @USER4 EQ 'DANIEL_ST' then
* debug
* ConnectionState = Get_Property.Net(objConnection, "State")
* end
If Error_Services('NoError') AND (Databases NE '') then
For Each Database in Databases using @FM
If Schemas EQ '' then Schemas = SQL_Services('GetSchemas', objConnection, Server, Database)
* If @USER4 EQ 'DANIEL_ST' then
* debug
* ConnectionState = Get_Property.Net(objConnection, "State")
* end
If UseRevDotNet EQ True$ and Schemas EQ 0 then Schemas = ''
If Error_Services('NoError') AND (Schemas NE '') then
For Each Schema in Schemas using @FM
SQLQuery = "SELECT TABLE_NAME FROM [" : Database : "].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" : Schema : "'"
TableNames = SQL_Services('ExecuteQuery', objConnection, SQLQuery, True$)
Convert @RM to @FM in TableNames
If Error_Services('NoError') AND (TableNames NE '') then
If (IncludeServerObject EQ True$) OR (IncludeDatabaseObject EQ True$) OR (IncludeSchemaObject EQ True$) then
For Each Table in TableNames using @FM
TableObject = Table
If IncludeSchemaObject EQ True$ then
TableObject = Schema : '.' : TableObject
If IncludeDatabaseObject EQ True$ then
TableObject = Database : '.' : TableObject
If IncludeServerObject EQ True$ then
TableObject = Server : '.' : TableObject
end
end
end
Tables := TableObject : @FM
Next Table
end else
Tables := TableNames : @FM
end
end
Next Schema
Schemas = ''
end
Next Database
end
Tables[-1, 1] = ''
If (Tables NE '') AND (BracketObjects EQ True$) then
Swap '.' with '].[' in Tables
Swap @FM with ']' : @FM : '[' in Tables
Tables = '[' : Tables : ']'
Tables = SRP_Array('SortRows', Tables, 'AL1', 'LIST', @FM, @VM)
end
end
If NewObject EQ True$ then
ErrorMessage = Error_Services('GetMessage')
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
end
end else
Error_Services('Add', 'objConnection and Server arguments were both missing in the ' : Service : ' service.')
end
Response = Tables
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTableColumns
//
// objConnection - Connection Object (see GetConnectionObject service.) - [Optional, but Server is then Required]
// Server - Name of a defined server. - [Optional, but objConnection is then Required]
// Database - Database object for the table. - [Optional]
// Schema - Schema object for the table. - [Optional]
// Table - Database Table whose column data is being requested. The Table argument might have the Server,
// Database, and/or Schema objects embedded. If so, then these will override any values specified
// in the Server, Database, or Schema arguments. - [Required]
//
// Returns an @FM/@VM array of database column information.
//----------------------------------------------------------------------------------------------------------------------
Service GetTableColumns(objConnection, Server, Database, Schema, Table)
TableColumns = ''
If Table NE '' then
Convert '[]' to '' in Table ; // Remove any brackets so the query won't fail.
If Index(Table, '.', 1) then
// Table came formatted with other objects. Parse these out.
NumObjects = DCount(Table, '.')
Begin Case
Case NumObjects EQ 4
Server = Table[1, '.']
Database = Table[Col2() + 1, '.']
Schema = Table[Col2() + 1, '.']
Table = Table[Col2() + 1, '.']
Case NumObjects EQ 3
Database = Table[1, '.']
Schema = Table[Col2() + 1, '.']
Table = Table[Col2() + 1, '.']
Case NumObjects EQ 2
Schema = Table[1, '.']
Table = Table[Col2() + 1, '.']
End Case
end
If (objConnection NE '') OR (Server NE '') then
If objConnection EQ '' then
objConnection = SQL_Services('GetConnectionObject', Server, 3)
NewObject = True$
end else
NewObject = False$
end
If Error_Services('NoError') then
ErrorMessage = ''
// This statement allows us to return PK and Null constraints.
If Database NE '' then
SQL_Services('ExecuteQuery', objConnection, "USE " : Database, False$)
end
If Error_Services('NoError') then
QueryStatement = ""
QueryStatement := "SELECT "
QueryStatement := " c.name 'Column Name', "
QueryStatement := " t.Name 'Data type', "
QueryStatement := " c.max_length 'Max Length', "
QueryStatement := " c.is_nullable, "
QueryStatement := " ISNULL(i.is_primary_key, 0) 'Primary Key' "
QueryStatement := "FROM "
QueryStatement := " sys.columns c "
QueryStatement := "INNER JOIN "
QueryStatement := " sys.types t ON c.user_type_id = t.user_type_id "
QueryStatement := "LEFT OUTER JOIN "
QueryStatement := " sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id "
QueryStatement := "LEFT OUTER JOIN "
QueryStatement := " sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id "
QueryStatement := "WHERE"
QueryStatement := " c.object_id = OBJECT_ID('"
If Database NE '' then QueryStatement := "[" : Database : "]."
If Schema NE '' then QueryStatement := "[" : Schema : "]."
QueryStatement := "[" : Table : "]')"
TableColumns = SQL_Services('ExecuteQuery', objConnection, QueryStatement, True$)
If Error_Services('NoError') then
Convert @FM to @VM in TableColumns
Convert @RM to @FM in TableColumns
TableColumns = SRP_Array('SortRows', TableColumns, 'DR5' : @FM : 'AL1', 'LIST', @FM, @VM)
end else
ErrorMessage = Error_Services('GetMessage')
end
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
end
end
If NewObject EQ True$ then
ErrorMessage = Error_Services('GetMessage')
SQL_Services('DestroyConnectionObject', objConnection)
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
end
end else
Error_Services('Add', 'The Server or Table argument was missing in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'Table argument was missing in the ' : Service : ' service.')
end
Response = TableColumns
end service
//----------------------------------------------------------------------------------------------------------------------
// GetPrimarySQLTable
//
// OITableName - The name of the OpenInsight table that is mapped to the primary SQL table. - [Required]
//
// Returns the name of the primary SQL table that the indicated OpenInsight table is mapped to.
//----------------------------------------------------------------------------------------------------------------------
Service GetPrimarySQLTable(OITableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName
PrimarySQLTable = Memory_Services('GetValue', ServiceKeyID)
If PrimarySQLTable EQ '' then
If OITableName NE '' then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
PrimarySQLTable = SRP_JSON(MapObj, 'GETVALUE', 'PrimarySQLTable.Name')
SRP_JSON(MapObj, 'RELEASE')
end
If PrimarySQLTable NE '' then Memory_Services('SetValue', ServiceKeyID, PrimarySQLTable)
end else
Error_Services('Add', 'The OITableName argument was missing in the ' : Service : ' service.')
end
end
Response = PrimarySQLTable
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSecondarySQLTables
//
// OITableName - The name of the OpenInsight table that is mapped to secondary SQL tables. - [Required]
//
// Returns an @FM delimited list of the secondary SQL tables that the indicated OpenInsight table is mapped to.
//----------------------------------------------------------------------------------------------------------------------
Service GetSecondarySQLTables(OITableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName
SecondarySQLTables = Memory_Services('GetValue', ServiceKeyID)
If SecondarySQLTables EQ '' then
If OITableName NE '' then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
TablesArray = SRP_JSON(MapObj, 'GET', 'SecondarySQLTables')
NumTables = SRP_JSON(TablesArray, 'GETCOUNT')
MatchFound = False$
For TableNum = 1 to NumTables
SecondarySQLTables := SRP_JSON(TablesArray, 'GETVALUE', '[' : TableNum : '].Name', '') : @FM
Until MatchFound
Next TableNum
SRP_JSON(TablesArray, 'RELEASE')
SRP_JSON(MapObj, 'RELEASE')
end
SecondarySQLTables[-1, 1] = ''
If SecondarySQLTables NE '' then Memory_Services('SetValue', ServiceKeyID, SecondarySQLTables)
end else
Error_Services('Add', 'The OITableName argument was missing in the ' : Service : ' service.')
end
end
Response = SecondarySQLTables
end service
//----------------------------------------------------------------------------------------------------------------------
// GetStaticSQLColumnNames
//
// OITableName - The name of the OpenInsight table that columns mapped to a SQL table with static values. - [Required]
//
// Returns an @FM delimited list of SQL column names that have a static value. These are usually used in a SQL insert
// statement along with the mapped columns.
//----------------------------------------------------------------------------------------------------------------------
Service GetStaticSQLColumnNames(OITableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName
StaticSQLColumnNames = Memory_Services('GetValue', ServiceKeyID)
If StaticSQLColumnNames EQ '' then
If (OITableName NE '') then
// Add all OpenInsight columns defined in the SQL Join Clause.
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
StaticColumnsArray = SRP_JSON(MapObj, 'GET', 'StaticColumns')
NumColumns = SRP_JSON(StaticColumnsArray, 'GETCOUNT')
For ColumnNum = 1 to NumColumns
objStaticColumn = SRP_JSON(StaticColumnsArray, 'GET', '[' : ColumnNum : ']')
StaticSQLColumnNames := SRP_JSON(objStaticColumn, 'GETVALUE', 'SQLColumnName') : @FM
SRP_JSON(objStaticColumn, 'RELEASE')
Next NumColumns
StaticSQLColumnNames[-1, 1] = ''
SRP_JSON(StaticColumnsArray, 'RELEASE')
SRP_JSON(MapObj, 'RELEASE')
end
If StaticSQLColumnNames NE '' then Memory_Services('SetValue', ServiceKeyID, StaticSQLColumnNames)
end else
Error_Services('Add', 'The OITableName argument was missing in the ' : Service : ' service.')
end
end
Response = StaticSQLColumnNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetStaticSQLColumnValues
//
// OITableName - The name of the OpenInsight table that columns mapped to a SQL table with static values. - [Required]
//
// Returns an @FM delimited list of values for SQL column names that have a static value. These are usually used in a
// SQL insert statement along with the mapped columns.
//----------------------------------------------------------------------------------------------------------------------
Service GetStaticSQLColumnValues(OITableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName
StaticSQLColumnValues = Memory_Services('GetValue', ServiceKeyID)
If StaticSQLColumnValues EQ '' then
If (OITableName NE '') then
// Add all OpenInsight columns defined in the SQL Join Clause.
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
StaticColumnsArray = SRP_JSON(MapObj, 'GET', 'StaticColumns')
NumColumns = SRP_JSON(StaticColumnsArray, 'GETCOUNT')
For ColumnNum = 1 to NumColumns
objStaticColumn = SRP_JSON(StaticColumnsArray, 'GET', '[' : ColumnNum : ']')
StaticValue = SRP_JSON(objStaticColumn, 'GETVALUE', 'StaticValue')
StaticValue = "'" : StaticValue : "'"
StaticSQLColumnValues := StaticValue : @FM
SRP_JSON(objStaticColumn, 'RELEASE')
Next NumColumns
StaticSQLColumnValues[-1, 1] = ''
SRP_JSON(StaticColumnsArray, 'RELEASE')
SRP_JSON(MapObj, 'RELEASE')
end
If StaticSQLColumnValues NE '' then Memory_Services('SetValue', ServiceKeyID, StaticSQLColumnValues)
end else
Error_Services('Add', 'The OITableName argument was missing in the ' : Service : ' service.')
end
end
Response = StaticSQLColumnValues
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAMVMaster
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
//
// Returns the name of the OpenInsight column used as the AMV (associated multivalue) master used to determine the
// number of values needed to write into the secondary SQL table.
//----------------------------------------------------------------------------------------------------------------------
Service GetAMVMaster(OITableName, SQLTableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName : '*' : SQLTableName
AMVMaster = Memory_Services('GetValue', ServiceKeyID)
If AMVMaster EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
JoinArray = '' ; // Initialize the array.
If SRP_JSON(MapObj, 'Parse', OITableToSQLMap) EQ '' then
PrimarySQLTableName = SRP_JSON(MapObj, 'GetValue', 'PrimarySQLTable.Name')
If SQLTableName _EQC PrimarySQLTableName then
// Primary SQL tables do not have a Seq Key. Just return the empty string.
end else
// Look for a matching secondary SQL table.
TableArray = SRP_JSON(MapObj, 'Get', 'SecondarySQLTables')
TableObjs = SRP_JSON(TableArray, 'GetElements')
TableFound = False$
For Each TableObj in TableObjs using @FM
SecondarySQLTableName = SRP_JSON(TableObj, 'GETVALUE', 'Name', '')
If SQLTableName _EQC SecondarySQLTableName then
JoinClassArray = SRP_JSON(TableObj, 'Get', 'JoinClause')
JoinClassObjs = SRP_JSON(JoinClassArray, 'GetElements')
For Each JoinClassObj in JoinClassObjs using @FM
If SRP_JSON(JoinClassObj, 'GetValue', 'AMVMaster') EQ True$ then
AMVMaster = SRP_JSON(JoinClassObj, 'GetValue', 'OIColumnName')
end
SRP_JSON(JoinClassObj, 'Release')
Until AMVMaster NE ''
Next JoinClassObj
TableFound = True$
SRP_JSON(JoinClassArray, 'Release')
end
SRP_JSON(TableObj, 'Release')
Until TableFound
Next TableObj
SRP_JSON(TableArray, 'Release')
end
SRP_JSON(MapObj, 'Release')
end
If AMVMaster NE '' then
Memory_Services('SetValue', ServiceKeyID, AMVMaster)
end
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = AMVMaster
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedJoinedOIColumnNames
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// ValuesReturned - A return varabiable that will contain the type of values each associated column should return.
// See below for more information. - [Optional]
//
// Returns an @FM list of column names from the indicated OpenInsight table that are used to join with the indicated
// SQL table. This service will also populate the ValuesReturned variable with the intended value to be returned by the
// associated column (.e.g, Column Data or Index Position).
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedJoinedOIColumnNames(OITableName, SQLTableName, Ref ValuesReturned)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName : '*' : SQLTableName
ColumnNames = Memory_Services('GetValue', ServiceKeyID)
ValuesReturned = Memory_Services('GetValue', ServiceKeyID : '*ValuesReturned')
If ColumnNames EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
JoinArray = '' ; // Initialize the array.
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
PrimarySQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'PrimarySQLTable.Name')
If SQLTableName _EQC PrimarySQLTableName then
// Use the join array from the primary SQL Table.
JoinArray = SRP_JSON(MapObj, 'GET', 'PrimarySQLTable.JoinClause')
end else
// Look for a matching secondary SQL table.
TablesArray = SRP_JSON(MapObj, 'GET', 'SecondarySQLTables')
NumTables = SRP_JSON(TablesArray, 'GETCOUNT')
MatchFound = False$
For TableNum = 1 to NumTables
TableObj = SRP_JSON(TablesArray, 'GET', '[' : TableNum : ']')
SecondarySQLTableName = SRP_JSON(TableObj, 'GETVALUE', 'Name', '')
If SQLTableName _EQC SecondarySQLTableName then
JoinArray = SRP_JSON(TableObj, 'GET', 'JoinClause')
MatchFound = True$
end
SRP_JSON(TableObj, 'RELEASE')
Until MatchFound
Next TableNum
SRP_JSON(TablesArray, 'RELEASE')
end
SRP_JSON(MapObj, 'RELEASE')
end
If JoinArray GT 0 then
NumColumns = SRP_JSON(JoinArray, 'GETCOUNT')
For ColumnNo = 1 to NumColumns
OIColumnName = SRP_JSON(JoinArray, 'GETVALUE', '[' : ColumnNo : ']' : 'OIColumnName', '')
ValueReturned = SRP_JSON(JoinArray, 'GETVALUE', '[' : ColumnNo : ']' : 'ValueReturned', '')
ColumnNames := OIColumnName : @FM
ValuesReturned := ValueReturned : @FM
Next ColumnNo
ColumnNames[-1, 1] = ''
ValuesReturned[-1, 1] = ''
SRP_JSON(JoinArray, 'RELEASE')
end
If ColumnNames NE '' then
Memory_Services('SetValue', ServiceKeyID, ColumnNames)
Memory_Services('SetValue', ServiceKeyID : '*ValuesReturned', ValuesReturned)
end
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = ColumnNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedJoinedSQLColumnNames
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
//
// Returns an @FM list of column names from the indicated SQL table that are used to join with the indicated OpenInsight
// table.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedJoinedSQLColumnNames(OITableName, SQLTableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName : '*' : SQLTableName
ColumnNames = Memory_Services('GetValue', ServiceKeyID)
If ColumnNames EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
JoinArray = '' ; // Initialize the array.
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
PrimarySQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'PrimarySQLTable.Name')
If SQLTableName _EQC PrimarySQLTableName then
// Use the join array from the primary SQL Table.
JoinArray = SRP_JSON(MapObj, 'GET', 'PrimarySQLTable.JoinClause')
end else
// Look for a matching secondary SQL table.
TablesArray = SRP_JSON(MapObj, 'GET', 'SecondarySQLTables')
NumTables = SRP_JSON(TablesArray, 'GETCOUNT')
MatchFound = False$
For TableNum = 1 to NumTables
TableObj = SRP_JSON(TablesArray, 'GET', '[' : TableNum : ']')
SecondarySQLTableName = SRP_JSON(TableObj, 'GETVALUE', 'Name', '')
If SQLTableName _EQC SecondarySQLTableName then
JoinArray = SRP_JSON(TableObj, 'GET', 'JoinClause')
MatchFound = True$
end
SRP_JSON(TableObj, 'RELEASE')
Until MatchFound
Next TableNum
SRP_JSON(TablesArray, 'RELEASE')
end
SRP_JSON(MapObj, 'RELEASE')
end
If JoinArray GT 0 then
NumColumns = SRP_JSON(JoinArray, 'GETCOUNT')
For ColumnNo = 1 to NumColumns
SQLColumnName = SRP_JSON(JoinArray, 'GETVALUE', '[' : ColumnNo : ']' : 'SQLColumnName', '')
ColumnNames := SQLColumnName : @FM
Next ColumnNo
ColumnNames[-1, 1] = ''
SRP_JSON(JoinArray, 'RELEASE')
end
If ColumnNames NE '' then
Memory_Services('SetValue', ServiceKeyID, ColumnNames)
end
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = ColumnNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedJoinedOperators
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
//
// Returns an @FM list of operators from the indicated SQL table that are used to join with the indicated OpenInsight
// table.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedJoinedOperators(OITableName, SQLTableName)
Convert @Lower_Case to @Upper_Case in OITableName
ServiceKeyID := '*' : OITableName : '*' : SQLTableName
Operators = Memory_Services('GetValue', ServiceKeyID)
If Operators EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
OITableToSQLMap = SQL_Services('GetOITableToSQLMap', OITableName)
JoinArray = '' ; // Initialize the array.
If SRP_JSON(MapObj, 'PARSE', OITableToSQLMap) EQ '' then
PrimarySQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'PrimarySQLTable.Name')
If SQLTableName _EQC PrimarySQLTableName then
// Use the join array from the primary SQL Table.
JoinArray = SRP_JSON(MapObj, 'GET', 'PrimarySQLTable.JoinClause')
end else
// Look for a matching secondary SQL table.
TablesArray = SRP_JSON(MapObj, 'GET', 'SecondarySQLTables')
NumTables = SRP_JSON(TablesArray, 'GETCOUNT')
MatchFound = False$
For TableNum = 1 to NumTables
TableObj = SRP_JSON(TablesArray, 'GET', '[' : TableNum : ']')
SecondarySQLTableName = SRP_JSON(TableObj, 'GETVALUE', 'Name', '')
If SQLTableName _EQC SecondarySQLTableName then
JoinArray = SRP_JSON(TableObj, 'GET', 'JoinClause')
MatchFound = True$
end
SRP_JSON(TableObj, 'RELEASE')
Until MatchFound
Next TableNum
SRP_JSON(TablesArray, 'RELEASE')
end
SRP_JSON(MapObj, 'RELEASE')
end
If JoinArray GT 0 then
NumColumns = SRP_JSON(JoinArray, 'GETCOUNT')
For ColumnNo = 1 to NumColumns
Operator = SRP_JSON(JoinArray, 'GETVALUE', '[' : ColumnNo : ']' : 'Operator', '')
Operators := Operator : @FM
Next ColumnNo
Operators[-1, 1] = ''
SRP_JSON(JoinArray, 'RELEASE')
end
If Operators NE '' then
Memory_Services('SetValue', ServiceKeyID, Operators)
end
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = Operators
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedJoinedSQLColumnValues
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table to. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being written to SQL. - [Required]
// OIRow - The OpenInsight row being written to SQL. - [Optional]
// AMVPosition - The position within the multivalue column that should be used in the join clause if the OpenInsight
// column is supposed to use its Index Position. - [Optional]
//
// Returns an @FM delimited list of SQL column values for the indicated table that are derived from the indicated
// OpenInsight table and associated joined columns. This service is normally called to create a fully formed Insert
// query statement. Note: OIRow will likely be an empty string since most join clauses will be based on the OpenInsight
// Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedJoinedSQLColumnValues(OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition)
Convert @Lower_Case to @Upper_Case in OITableName
If Num(AMVPosition) else AMVPosition = ''
ColumnValues = ''
If (OITableName NE '') AND (SQLTableName NE '') AND (OIKeyID NE '') then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
OIColumnNames = SQL_Services('GetMappedJoinedOIColumnNames', OITableName, SQLTableName, ValuesReturned)
If Error_Services('NoError') then
If OIColumnNames NE '' then
For Each OIColumnName in OIColumnNames using @FM setting fPos
ValueReturned = ValuesReturned<fPos>
If ValueReturned EQ '' then ValueReturned = 'Column Data'
Locate OIColumnName in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnToSQLMap = SQL_Services('GetOIColumnToSQLMap', OITableName, OIColumnName)
If Error_Services('NoError') then
If SRP_JSON(MapObj, 'PARSE', OIColumnToSQLMap) EQ '' then
SQLColumnType = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnType')
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
IsOIKey = False$ ; // Assume false for now.
If ValueReturned EQ 'Column Data' then
If OIColumnType EQ 'F' then
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnPos GT 0 then
OIColumnValue = OIRow<OIColumnPos>
end else
IsOIKey = True$
OIKeyPart = FieldArray<FIELDS_PART$, vPos>
OIColumnValue = Field(OIKeyID, '*', OIKeyPart, 1)
If OIColumnValue EQ '' then
Error_Services('Add', 'Key ID Column ' : OIColumnName : ' was assigned an empty string value in ' : Service : '.')
end
end
end else
// OIColumnValue = Calculate(OIColumnName) ; // Actual logic used in MFS
OIColumnValue = Xlate(OITablename, OIKeyID, OIColumnName, 'X')
end
If (AMVPosition NE '') AND (IsOIKey NE True$) then
OIColumnValue = OIColumnValue<0, AMVPosition>
end
end else
If AMVPosition EQ '' then AMVPosition = 1
OIColumnValue = AMVPosition
end
If ValueReturned EQ 'Column Data' then
// Make applicable data conversions.
Begin Case
Case OIColumnValue EQ ''
// Empty strings are treated as NULL values.
OIColumnValue = 'NULL'
Case InList('varchar,nvarchar,char,nchar', SQLColumnType, ',')
// Single quote the value.
SQLColumnLength = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnLength')
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
If (SQLColumnLength EQ '') OR (SQLColumnLength EQ '-1') then SQLColumnLength = Len(OIColumnValue)
OIColumnValue = OIColumnValue[1, SQLColumnLength, 1]
Swap "'" with "''" in OIColumnValue
OIColumnValue = "'" : OIColumnValue : "'"
Case InList('tinyint,smallint,bigint,int', SQLColumnType, ',')
// Treat as an integer.
OIColumnConv = 'MD0'
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
Case InList('decimal,numeric,float,real', SQLColumnType, ',')
// Treat as a floating point number using any OI column output conversion if it
// exists.
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
Convert 'Z' to '' in OIColumnConv ; // No empty strings with numeric columns.
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
Case SQLColumnType _EQC 'bit'
// Treat as a Boolean, but only return a 1, 0, or NULL.
If OIColumnValue EQ '' then
OIColumnValue = 'NULL'
end else
If OIColumnValue NE False$ then OIColumnValue = True$
end
Case SQLColumnType _EQC 'date'
OIColumnValue = "'" : (SRP_Date('Format', OIColumnValue, 'YYYY-MM-DD')) : "'"
Case SQLColumnType _EQC 'datetime'
OIColumnValue = "'" : (SRP_DateTime('Format', OIColumnValue, 'YYYY-MM-DD hh:mm:ss')) : "'"
Case SQLColumnType _EQC 'time'
OIColumnValue = "'" : (SRP_Time('Format', OIColumnValue, 'hh:mm:ss')) : "'"
Case Otherwise$
// Treat as a character type.
SQLColumnLength = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnLength')
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
If (SQLColumnLength EQ '') OR (SQLColumnLength EQ '-1') then SQLColumnLength = Len(OIColumnValue)
OIColumnValue = OIColumnValue[1, SQLColumnLength, 1]
Swap "'" with "''" in OIColumnValue
OIColumnValue = "'" : OIColumnValue : "'"
End Case
end
// Basic conversion rules.
Convert \09\ to ' ' in OIColumnValue
Swap \0D0A\ with ' ' in OIColumnValue
Convert @VM to '|' in OIColumnValue
Convert @SVM to ' ' in OIColumnValue
Convert @TM to ' ' in OIColumnValue
Convert @STM to ' ' in OIColumnValue
ColumnValues := OIColumnValue : @FM
SRP_JSON(MapObj, 'RELEASE')
end
end
end
While Error_Services('NoError')
Next OIColumnName
end
ColumnValues[-1, 1] = ''
end
end else
Error_Services('Add', 'The OITableName, SQLTableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
Response = ColumnValues
end service
//----------------------------------------------------------------------------------------------------------------------
// GetJoinClause
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being written to SQL. - [Required]
// OIRow - The OpenInsight row being written to SQL. - [Optional]
// AMVPosition - The position within the multivalue column that should be used in the join clause if the
// OpenInsight column is supposed to use its Index Position. - [Optional]
// IgnoreAMVMaster - Boolean falg to indicate if the joined column associated with the OpenInsight AMV Master should
// be ignored. This is necessary for Join Clauses used for Select and Delete statements. - [Optional]
//
// Returns a well formed join clause using the indicated OpenInsight Key ID and row for the indicated OpenInsight table
// and SQL table. Note: OIRow will likely be an empty string since most join clauses will be based on the OpenInsight
// Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service GetJoinClause(OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition, IgnoreAMVMaster=BOOLEAN)
Convert @Lower_Case to @Upper_Case in OITableName
JoinClause = ''
If IgnoreAMVMaster NE True$ then IgnoreAMVMaster = False$
If (OITableName NE '') AND (SQLTableName NE '') AND (OIKeyID NE '') then
JoinedSQLColumns = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SQLTableName)
If JoinedSQLColumns NE '' then
JoinedOperators = SQL_Services('GetMappedJoinedOperators', OITableName, SQLTableName)
JoinedSQLValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition)
If IgnoreAMVMaster EQ True$ then
// Get all of the OpenInsight columns associated with this join and the AMV Master. Remove the SQL column,
// operator, and value associated with the AMV Master.
AMVMaster = SQL_Services('GetAMVMaster', OITableName, SQLTableName)
If AMVMaster NE '' then
JoinedOIColumns = SQL_Services('GetMappedJoinedOIColumnNames', OITableName, SQLTableName)
Locate AMVMaster in JoinedOIColumns using @FM setting Pos then
JoinedSQLColumns = Delete(JoinedSQLColumns, Pos, 0, 0)
JoinedOperators = Delete(JoinedOperators, Pos, 0, 0)
JoinedSQLValues = Delete(JoinedSQLValues, Pos, 0, 0)
end
end
end
For Each JoinedColumn in JoinedSQLColumns using @FM setting Pos
JoinClause := JoinedColumn : ' '
JoinClause := JoinedOperators<Pos> : ' '
JoinClause := JoinedSQLValues<Pos>
JoinClause := @FM
Next JoinedColumn
JoinClause[-1, 1] = ''
Swap @FM with ' AND ' in JoinClause
end
end else
Error_Services('Add', 'The OITableName, SQLTableName, OIKeyID argument was missing in the ' : Service : ' service.')
end
Response = JoinClause
end service
//----------------------------------------------------------------------------------------------------------------------
// GetJoinClause
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being written to SQL. - [Required]
// OIRow - The OpenInsight row being written to SQL. - [Optional]
// AMVPosition - The position within the multivalue column that should be used in the join clause if the
// OpenInsight column is supposed to use its Index Position. - [Optional]
// IgnoreAMVMaster - Boolean falg to indicate if the joined column associated with the OpenInsight AMV Master should
// be ignored. This is necessary for Join Clauses used for Select and Delete statements. - [Optional]
//
// Returns a well formed join clause using the indicated OpenInsight Key ID and row for the indicated OpenInsight table
// and SQL table. Note: OIRow will likely be an empty string since most join clauses will be based on the OpenInsight
// Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service GetMergeClause(OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition, IgnoreAMVMaster=BOOLEAN)
Convert @Lower_Case to @Upper_Case in OITableName
JoinClause = ''
If IgnoreAMVMaster NE True$ then IgnoreAMVMaster = False$
If (OITableName NE '') AND (SQLTableName NE '') AND (OIKeyID NE '') then
JoinedSQLColumns = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SQLTableName)
If JoinedSQLColumns NE '' then
JoinedOperators = SQL_Services('GetMappedJoinedOperators', OITableName, SQLTableName)
JoinedSQLValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition)
If IgnoreAMVMaster EQ True$ then
// Get all of the OpenInsight columns associated with this join and the AMV Master. Remove the SQL column,
// operator, and value associated with the AMV Master.
AMVMaster = SQL_Services('GetAMVMaster', OITableName, SQLTableName)
If AMVMaster NE '' then
JoinedOIColumns = SQL_Services('GetMappedJoinedOIColumnNames', OITableName, SQLTableName)
Locate AMVMaster in JoinedOIColumns using @FM setting Pos then
JoinedSQLColumns = Delete(JoinedSQLColumns, Pos, 0, 0)
JoinedOperators = Delete(JoinedOperators, Pos, 0, 0)
JoinedSQLValues = Delete(JoinedSQLValues, Pos, 0, 0)
end
end
end
For Each JoinedColumn in JoinedSQLColumns using @FM setting Pos
JoinClause := 'tgt.':JoinedColumn : ' '
JoinClause := JoinedOperators<Pos> : ' '
JoinClause := 'src.':JoinedColumn
JoinClause := @FM
Next JoinedColumn
JoinClause[-1, 1] = ''
Swap @FM with ' AND ' in JoinClause
end
end else
Error_Services('Add', 'The OITableName, SQLTableName, OIKeyID argument was missing in the ' : Service : ' service.')
end
Response = JoinClause
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedOIColumnNames
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// ExcludeJoinedColumns - Boolean flag indicating if the columns used for the join should be excluded from the
// list of columns returned. This would be done if the columns are used to insert or update
// the SQL table. Default is true. - [Optional]
//
// Returns an @FM delimited list of OpenInsight column names from the indicated table that are mapped to the indicated
// SQL table.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedOIColumnNames(OITableName, SQLTableName, ExcludeJoinedColumns=BOOLEAN)
Convert @Lower_Case to @Upper_Case in OITableName
If ExcludeJoinedColumns NE False$ then ExcludeJoinedColumns = True$
ServiceKeyID := '*' : OITableName : '*' : SQLTableName : '*' : ExcludeJoinedColumns
ColumnNames = Memory_Services('GetValue', ServiceKeyID)
If ColumnNames EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
// Go through all of the OpenInsight column SQL maps and add any column which is bound to the same SQL
// table. Note, one or more of these columns might already be in the list from the
// GetMappedJoinedOIColumnNames service. These will be skipped.
AllOIColumnToSQLMaps = SQL_Services('GetAllOIColumnToSQLMaps', OITableName)
For Each OIColumnToSQLMapList in AllOIColumnToSQLMaps using @FM setting fPos
(OIColumnName, OIColumnToSQLMap) using @VM = OIColumnToSQLMapList
If SRP_JSON(MapObj, 'PARSE', OIColumnToSQLMap) EQ '' then
MappedSQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'SQLTableName')
MappedSQLColumnName = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnName')
If (MappedSQLTableName NE '') AND (MappedSQLColumnName NE '') AND (SQLTableName EQ MappedSQLTableName) then
Locate OIColumnName in ColumnNames using @FM setting fPos else
ColumnNames := OIColumnName : @FM
end
end
SRP_JSON(MapObj, 'Release')
end
Next OIColumnToSQLMap
If ExcludeJoinedColumns EQ True$ then
// Get all OpenInsight columns defined in the SQL Join Clause. Then remove any that are rely upon Column
// Data mapping rather than Index Position. This will avoid duplicate columns being used in a SQL statement.
JoinedValuesReturned = ''
JoinedOIColumns = SQL_Services('GetMappedJoinedOIColumnNames', OITableName, SQLTableName, JoinedValuesReturned)
If JoinedOIColumns NE '' then
For Each JoinedColumnName in JoinedOIColumns using @FM Setting JoinedPos
Locate JoinedColumnName in ColumnNames using @FM setting Pos then
If JoinedValuesReturned<JoinedPos> EQ 'Column Data' then
ColumnNames = Delete(ColumnNames, Pos, 0, 0)
end
end
Next JoinedColumnName
end
end
ColumnNames[-1, 1] = ''
If ColumnNames NE '' then
Memory_Services('SetValue', ServiceKeyID, ColumnNames)
end
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = ColumnNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedOIColumnValues
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// SQLRow - The SQL row that will be mapped to the OpenInsight row. - [Required]
// OIRow - The OpenInsight row with pre-existing data. See below for more information. - [Optional]
//
// Returns an OpenInsight data row for the indicated table that are derived from the indicated SQL table and
// corresponding SQL data. Note, since data can come from multiple SQL tables, the OIRow arguments can already contain
// data from a previous call to this service. This allows primary and secondary SQL tables to be passed into this
// service so that all relevant SQL data can be denormalized into a single OpenInsight data row. This service is
// normally called to create a denormalized OpenInsight row.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedOIColumnValues(OITableName, SQLTableName, SQLData, OIRow)
Convert @Lower_Case to @Upper_Case in OITableName
If (OITableName NE '') AND (SQLTableName NE '') AND (SQLData NE '') then
MappedOIColumnNames = SQL_Services('GetMappedOIColumnNames', OITableName, SQLTableName, False$)
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, SQLTableName, '', False$)
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
If Error_Services('NoError') then
For Each SQLRow in SQLData using @RM setting ValuePos
For Each SQLColumnName in MappedSQLColumnNames using @FM setting fPos
OIColumnName = MappedOIColumnNames<fPos>
Locate OIColumnName in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnType EQ 'F' AND OIColumnPos NE 0 then
OIColumnToSQLMap = SQL_Services('GetOIColumnToSQLMap', OITableName, OIColumnName)
If Error_Services('NoError') then
If SRP_JSON(MapObj, 'PARSE', OIColumnToSQLMap) EQ '' then
SQLColumnType = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnType')
OIColumnValue = SQLRow<fPos>
Swap '<@VM>' with @VM in OIColumnValue
Swap @SVM with '<@SVM>' in OIColumnValue
Swap @TM with '<@TM>' in OIColumnValue
Swap @STM with '<@STM>' in OIColumnValue
Begin Case
Case InList('varchar,nvarchar,char,nchar', SQLColumnType, ',')
// Single quote the value.
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Iconv(OIColumnValue, OIColumnConv)
end
Case InList('tinyint,smallint,bigint,int', SQLColumnType, ',')
// Treat as an integer.
OIColumnConv = 'MD0'
If OIColumnConv NE '' then
OIColumnValue = Iconv(OIColumnValue, OIColumnConv)
end
Case InList('decimal,numeric,float,real', SQLColumnType, ',')
// Treat as a floating point number using any OI column output conversion if it
// exists.
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Iconv(OIColumnValue, OIColumnConv)
end
Case SQLColumnType _EQC 'date'
OIColumnValue = SRP_Date('Parse', OIColumnValue, 'MM/DD/YYYY')
Case SQLColumnType _EQC 'datetime'
OIColumnValue = SRP_DateTime('Parse', OIColumnValue, 'MM/DD/YYYY hh:mm:ss')
Case SQLColumnType _EQC 'time'
OIColumnValue = SRP_Time('Parse', OIColumnValue, 'hh:mm:ss')
Case Otherwise$
// Treat as a character type.
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Iconv(OIColumnValue, OIColumnConv)
end
End Case
OIRow<OIColumnPos, ValuePos> = OIColumnValue
end
SRP_JSON(MapObj, 'RELEASE')
end
end
end
Next SQLColumnName
Next SQLRow
end
end else
Error_Services('Add', 'The SQLTableName, SQLData, or OITableName argument was missing in the ' : Service : ' service.')
end
Response = OIRow
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedSQLColumnNames
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to
// SQL. If empty, all columns that have a map defintion will be used. - [Optional]
// ExcludeJoinedColumns - Boolean flag indicating if the columns used for the join should be excluded from the
// list of columns returned. This would be done if the columns are used to insert or update
// the SQL table. Default is true. - [Optional]
//
// Returns an @FM delimited list of SQL column names from the indicated table that are mapped from the indicated
// OpenInsight table and associated OpenInsight columns.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedSQLColumnNames(OITableName, SQLTableName, OIColumns, ExcludeJoinedColumns)
Convert @Lower_Case to @Upper_Case in OITableName
If ExcludeJoinedColumns NE False$ then ExcludeJoinedColumns = True$
ServiceKeyID := '*' : OITableName : '*' : SQLTableName : '*' : ExcludeJoinedColumns
ColumnNames = Memory_Services('GetValue', ServiceKeyID)
If ColumnNames EQ '' then
If (OITableName NE '') AND (SQLTableName NE '') then
If OIColumns NE '' then
Transfer OIColumns to OIColumnNames
end else
// The GetMappedOIColumnNames service will automatically remove any columns that are also mapped in
// a join clause with the "Column Data" return value attribute.
OIColumnNames = SQL_Services('GetMappedOIColumnNames', OITableName, SQLTableName, ExcludeJoinedColumns)
end
If OIColumnNames NE '' then
For Each OIColumnName in OIColumnNames using @FM setting fPos
OIColumnToSQLMap = SQL_Services('GetOIColumnToSQLMap', OITableName, OIColumnName)
If Error_Services('NoError') then
If SRP_JSON(MapObj, 'PARSE', OIColumnToSQLMap) EQ '' then
MappedSQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'SQLTableName')
MappedSQLColumnName = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnName')
If (MappedSQLTableName EQ SQLTablename) AND (MappedSQLColumnName NE '') then
ColumnNames := MappedSQLColumnName : @FM
end
SRP_JSON(MapObj, 'RELEASE')
end
end
Next OIColumnName
end
ColumnNames[-1, 1] = ''
If ColumnNames NE '' then Memory_Services('SetValue', ServiceKeyID, ColumnNames)
end else
Error_Services('Add', 'The OITableName or SQLTableName argument was missing in the ' : Service : ' service.')
end
end
Response = ColumnNames
end service
//----------------------------------------------------------------------------------------------------------------------
// GetMappedSQLColumnValues
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table to. - [Required]
// SQLTableName - The name of the SQL table that the Openinsight table is mapped to. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being written to SQL. - [Required]
// OIRow - The OpenInsight row being written to SQL. - [Required]
// AMVPosition - The position within the multivalue column that should be used in the join clause if the OpenInsight
// column is supposed to use its Index Position. - [Optional]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to SQL. If empty,
// all columns that have a map defintion will be used. - [Optional]
//
// Returns an @FM delimited list of SQL column values for the indicated table that are derived from the indicated
// OpenInsight table and associated OpenInsight columns. This service is normally called to create a fully formed Insert
// query statement.
//----------------------------------------------------------------------------------------------------------------------
Service GetMappedSQLColumnValues(OITableName, SQLTableName, OIKeyID, OIRow, AMVPosition, OIColumns)
Convert @Lower_Case to @Upper_Case in OITableName
If Num(AMVPosition) else AMVPosition = ''
ColumnValues = ''
If (OITableName NE '') AND (SQLTableName NE '') AND (OIKeyID NE '') AND (OIRow NE '') then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
If OIColumns NE '' then
Transfer OIColumns to OIColumnNames
end else
// The GetMappedOIColumnNames service will automatically remove any columns that are also mapped in
// a join clause with the "Column Data" return value attribute.
OIColumnNames = SQL_Services('GetMappedOIColumnNames', OITableName, SQLTableName, True$)
end
If OIColumnNames NE '' then
For Each OIColumnName in OIColumnNames using @FM setting fPos
Locate OIColumnName in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnToSQLMap = SQL_Services('GetOIColumnToSQLMap', OITableName, OIColumnName)
If Error_Services('NoError') then
If SRP_JSON(MapObj, 'PARSE', OIColumnToSQLMap) EQ '' then
MappedSQLTableName = SRP_JSON(MapObj, 'GETVALUE', 'SQLTableName')
If MappedSQLTableName EQ SQLTablename then
SQLColumnType = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnType')
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
IsOIKey = False$ ; // Assume false for now.
If OIColumnType EQ 'F' then
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnPos GT 0 then
OIColumnValue = OIRow<OIColumnPos>
end else
IsOIKey = True$
OIKeyPart = FieldArray<FIELDS_PART$, vPos>
OIColumnValue = Field(OIKeyID, '*', OIKeyPart, 1)
If OIColumnValue EQ '' then
Error_Services('Add', 'Key ID Column ' : OIColumnName : ' was assigned an empty string value in ' : Service : '.')
end
end
end else
// OIColumnValue = Calculate(OIColumnName) ; // Actual logic used in MFS
OIColumnValue = Xlate(OITablename, OIKeyID, OIColumnName, 'X')
end
If (AMVPosition NE '') AND (IsOIKey NE True$) then
OIColumnValue = OIColumnValue<0, AMVPosition>
end
Begin Case
Case SQLColumnType _EQC 'uniqueidentifier'
OIColumnValue = 'NEWID()'
Case OIColumnValue EQ ''
// Empty strings are treated as NULL values.
OIColumnValue = 'NULL'
Case InList('varchar,nvarchar,char,nchar', SQLColumnType, ',')
// Single quote the value.
SQLColumnLength = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnLength')
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
If (SQLColumnLength EQ '') OR (SQLColumnLength EQ '-1') then SQLColumnLength = Len(OIColumnValue)
OIColumnValue = OIColumnValue[1, SQLColumnLength, 1]
Swap "'" with "''" in OIColumnValue
OIColumnValue = "'" : OIColumnValue : "'"
Case InList('tinyint,smallint,bigint,int', SQLColumnType, ',')
// Treat as an integer.
OIColumnConv = 'MD0'
If Len(OIColumnConv) then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
If Not(Num(OIColumnValue)) then
// Not a true number so format like a string.
OIColumnValue = "'" : OIColumnValue : "'"
end
end else
// Empty value so treat it as a NULL value.
OIColumnValue = 'NULL'
end
Case InList('decimal,numeric,float,real', SQLColumnType, ',')
// Treat as a floating point number using any OI column output conversion if it
// exists.
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
Convert 'Z' to '' in OIColumnConv ; // No empty strings with numeric columns.
If Len(OIColumnConv) then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
If Not(Num(OIColumnValue)) then
// Not a true number so format like a string.
OIColumnValue = "'" : OIColumnValue : "'"
end
end else
// Empty value so treat it as a NULL value.
OIColumnValue = 'NULL'
end
Case SQLColumnType _EQC 'bit'
// Treat as a Boolean, but only return a 1, 0, or NULL.
If OIColumnValue EQ '' then
OIColumnValue = 'NULL'
end else
If OIColumnValue NE False$ then OIColumnValue = True$
end
Case SQLColumnType _EQC 'date'
OIColumnValue = "'" : (SRP_Date('Format', OIColumnValue, 'YYYY-MM-DD')) : "'"
Case SQLColumnType _EQC 'datetime'
OIColumnValue = "'" : (SRP_DateTime('Format', OIColumnValue, 'YYYY-MM-DD hh:mm:ss')) : "'"
Case SQLColumnType _EQC 'time'
OIColumnValue = "'" : (SRP_Time('Format', OIColumnValue, 'hh:mm:ss')) : "'"
Case Otherwise$
// Treat as a character type.
SQLColumnLength = SRP_JSON(MapObj, 'GETVALUE', 'SQLColumnLength')
OIColumnConv = FieldArray<FIELDS_CONV$, vPos>
If OIColumnConv NE '' then
OIColumnValue = Fmt(OIColumnValue, OIColumnConv)
end
If (SQLColumnLength EQ '') OR (SQLColumnLength EQ '-1') then SQLColumnLength = Len(OIColumnValue)
OIColumnValue = OIColumnValue[1, SQLColumnLength, 1]
Swap "'" with "''" in OIColumnValue
OIColumnValue = "'" : OIColumnValue : "'"
End Case
// Basic conversion rules.
Convert \09\ to ' ' in OIColumnValue
Swap \0D0A\ with ' ' in OIColumnValue
Convert @VM to '|' in OIColumnValue
Convert @SVM to ' ' in OIColumnValue
Convert @TM to ' ' in OIColumnValue
Convert @STM to ' ' in OIColumnValue
ColumnValues := OIColumnValue : @FM
end
SRP_JSON(MapObj, 'RELEASE')
end
Error_Services('Clear') ; // Any errors at this point would have been created during calculated column logic, which is unrelated to this service.
end
end
While Error_Services('NoError')
Next OIColumnName
end
ColumnValues[-1, 1] = ''
end else
Error_Services('Add', 'The OITableName, SQLTableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
Response = ColumnValues
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSQLInsertStatements
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being deleted from SQL. - [Required]
// OIRow - The OpenInsight row associated with the OpenInsight Key ID. - [Optional]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to SQL. If empty,
// all columns that have a map defintion will be used. - [Optional]
//
// Returns an @FM delimited list of SQL insert statements for the SQL table mapped to the indicated OpenInsight table.
// This will automatically create all SQL insert statements for secondary SQL tables as well.
//----------------------------------------------------------------------------------------------------------------------
Service GetSQLInsertStatements(OITableName, OIKeyID, OIRow, OIColumns)
Convert @Lower_Case to @Upper_Case in OITableName
SQLInsertStatements = ''
If (OITableName NE '') AND (OIKeyID NE '') AND (OIRow NE '') then
// Start with the primary SQL table that is mapped to this OpenInsight table.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, PrimarySQLTableName, OIColumns)
If MappedSQLColumnNames NE '' then MappedSQLColumnNames := @FM
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, PrimarySQLTableName, OIKeyID, OIRow, '', OIColumns)
If MappedSQLColumnValues NE '' then MappedSQLColumnValues := @FM
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, PrimarySQLTableName)
If JoinedSQLColumnNames NE '' then
MappedSQLColumnNames := JoinedSQLColumnNames : @FM
JoinedSQLColumnValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, PrimarySQLTableName, OIKeyID, OIRow)
MappedSQLColumnValues := JoinedSQLColumnValues : @FM
end
StaticSQLColumnNames = SQL_Services('GetStaticSQLColumnNames', OITableName)
If StaticSQLColumnNames NE '' then
MappedSQLColumnNames := StaticSQLColumnNames : @FM
StaticSQLColumnValues = SQL_Services('GetStaticSQLColumnValues', OITableName)
MappedSQLColumnValues := StaticSQLColumnValues : @FM
end
MappedSQLColumnNames[-1, 1] = ''
MappedSQLColumnValues[-1, 1] = ''
Swap @FM with ', ' in MappedSQLColumnNames
Swap @FM with ", " in MappedSQLColumnValues
SQLInsertStatement = 'INSERT INTO ' : PrimarySQLTableName : ' '
SQLInsertStatement := '('
SQLInsertStatement := MappedSQLColumnNames
SQLInsertStatement := ') VALUES ('
SQLInsertStatement := MappedSQLColumnValues
SQLInsertStatement := ')'
SQLInsertStatements := SQLInsertStatement : @FM
If Error_Services('NoError') then
// Add any secondary SQL table inserts that might be required.
SecondarySQLTableNames = SQL_Services('GetSecondarySQLTables', OITableName)
If SecondarySQLTableNames NE '' then
For Each SecondarySQLTableName in SecondarySQLTableNames using @FM
OIColumnValue = '' ; // Default to empty string. Update if AMV Master is found.
NumPositions = 1 ; // Default to only 1 index position. Update if AMV Master is found.
AMVMaster = SQL_Services('GetAMVMaster', OITableName, SecondarySQLTableName)
If AMVMaster NE '' then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
If Error_Services('NoError') then
Locate AMVMaster in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
If OIColumnType EQ 'F' then
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnPos GT 0 then
OIColumnValue = OIRow<OIColumnPos>
end else
OIKeyPart = FieldArray<FIELDS_PART$, vPos>
OIColumnValue = Field(OIKeyID, '*', OIKeyPart, 1)
end
end else
// OIColumnValue = Calculate(OIColumnName) ; // Actual logic used in MFS
OIColumnValue = Xlate(OITablename, OIKeyID, OIColumnName, 'X')
end
NumPositions = DCount(OIColumnValue, @VM)
end
end
end
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, SecondarySQLTableName)
If MappedSQLColumnNames NE '' then
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SecondarySQLTableName)
If JoinedSQLColumnNames NE '' then
MappedSQLColumnNames := @FM : JoinedSQLColumnNames
end
Swap @FM with ', ' in MappedSQLColumnNames
For AMVPosition = 1 to NumPositions
If OIColumnValue<0, AMVPosition> NE '' then
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
If JoinedSQLColumnNames NE '' then
JoinedSQLColumnValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
MappedSQLColumnValues := @FM : JoinedSQLColumnValues
end
Swap @FM with ', ' in MappedSQLColumnValues
SQLInsertStatement = 'INSERT INTO ' : SecondarySQLTableName : ' '
SQLInsertStatement := '('
SQLInsertStatement := MappedSQLColumnNames
SQLInsertStatement := ') VALUES ('
SQLInsertStatement := MappedSQLColumnValues
SQLInsertStatement := ')'
SQLInsertStatements := SQLInsertStatement : @FM
end
Next AMVPosition
end
Next SecondarySQLTableName
end
end
SQLInsertStatements[-1, 1] = ''
end else
Error_Services('Add', 'The OITableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
Response = SQLInsertStatements
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSQLUpdateStatements
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being deleted from SQL. - [Required]
// OIRow - The OpenInsight row associated with the OpenInsight Key ID. - [Optional]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to SQL. If empty,
// all columns that have a map defintion will be used. - [Optional]
//
// Returns an @FM delimited list of SQL update statements for the SQL table mapped to the indicated OpenInsight table.
// This will automatically create all SQL update statements for secondary SQL tables as well.
//----------------------------------------------------------------------------------------------------------------------
Service GetSQLUpdateStatements(OITableName, OIKeyID, OIRow, OIColumns)
Convert @Lower_Case to @Upper_Case in OITableName
SQLUpdateStatements = ''
If (OITableName NE '') AND (OIKeyID NE '') AND (OIRow NE '') then
// Start with the primary SQL table that is mapped to this OpenInsight table.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
JoinClause = SQL_Services('GetJoinClause', OITableName, PrimarySQLTableName, OIKeyID, OIRow)
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, PrimarySQLTableName, OIColumns)
If MappedSQLColumnNames NE '' then MappedSQLColumnNames := @FM
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, PrimarySQLTableName, OIKeyID, OIRow, '', OIColumns)
If MappedSQLColumnValues NE '' then MappedSQLColumnValues := @FM
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, PrimarySQLTableName)
StaticSQLColumnNames = SQL_Services('GetStaticSQLColumnNames', OITableName)
If StaticSQLColumnNames NE '' then
MappedSQLColumnNames := StaticSQLColumnNames : @FM
StaticSQLColumnValues = SQL_Services('GetStaticSQLColumnValues', OITableName)
MappedSQLColumnValues := StaticSQLColumnValues : @FM
end
MappedSQLColumnNames[-1, 1] = ''
MappedSQLColumnValues[-1, 1] = ''
SQLUpdateStatement = ''
If MappedSQLColumnNames NE '' then
SQLUpdateStatement := 'UPDATE ' : PrimarySQLTableName : ' SET '
For Each SQLColumnName in MappedSQLColumnNames using @FM setting fPos
SQLUpdateStatement := SQLColumnName : '=' : MappedSQLColumnValues<fPos> : ', '
Next SQLColumnName
SQLUpdateStatement[-2, 1] = ''
SQLUpdateStatement := 'WHERE '
SQLUpdateStatement := JoinClause : ' '
SQLUpdateStatements := SQLUpdateStatement : @FM
end
If Error_Services('NoError') then
// Add any secondary SQL table inserts that might be required.
SecondarySQLTableNames = SQL_Services('GetSecondarySQLTables', OITableName)
If SecondarySQLTableNames NE '' then
For Each SecondarySQLTableName in SecondarySQLTableNames using @FM
OIColumnValue = '' ; // Default to empty string. Update if AMV Master is found.
NumPositions = 1 ; // Default to only 1 index position. Update if AMV Master is found.
AMVMaster = SQL_Services('GetAMVMaster', OITableName, SecondarySQLTableName)
If AMVMaster NE '' then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
If Error_Services('NoError') then
Locate AMVMaster in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
If OIColumnType EQ 'F' then
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnPos GT 0 then
OIColumnValue = OIRow<OIColumnPos>
end else
OIKeyPart = FieldArray<FIELDS_PART$, vPos>
OIColumnValue = Field(OIKeyID, '*', OIKeyPart, 1)
end
end else
// OIColumnValue = Calculate(OIColumnName) ; // Actual logic used in MFS
OIColumnValue = Xlate(OITablename, OIKeyID, OIColumnName, 'X')
end
NumPositions = DCount(OIColumnValue, @VM)
end
end
end
// Remove all rows from the secondary table. These will be added back using the INSERT statements as needed.
SQLUpdateStatement = 'DELETE FROM ' : SecondarySQLTableName : ' '
SQLUpdateStatement := 'WHERE '
SQLUpdateStatement := JoinClause
SQLUpdateStatements := SQLUpdateStatement : @FM
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, SecondarySQLTableName)
If MappedSQLColumnNames NE '' then
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SecondarySQLTableName)
If JoinedSQLColumnNames NE '' then
MappedSQLColumnNames := @FM : JoinedSQLColumnNames
end
Swap @FM with ', ' in MappedSQLColumnNames
For AMVPosition = 1 to NumPositions
If OIColumnValue<0, AMVPosition> NE '' then
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
If JoinedSQLColumnNames NE '' then
JoinedSQLColumnValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
MappedSQLColumnValues := @FM : JoinedSQLColumnValues
end
Swap @FM with ', ' in MappedSQLColumnValues
SQLUpdateStatement = 'INSERT INTO ' : SecondarySQLTableName : ' '
SQLUpdateStatement := '('
SQLUpdateStatement := MappedSQLColumnNames
SQLUpdateStatement := ') VALUES ('
SQLUpdateStatement := MappedSQLColumnValues
SQLUpdateStatement := ')'
SQLUpdateStatements := SQLUpdateStatement : @FM
end
Next AMVPosition
end
Next SecondarySQLTableName
end
end
SQLUpdateStatements[-1, 1] = ''
end else
Error_Services('Add', 'The OITableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
Response = SQLUpdateStatements
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSQLMergeStatements
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being deleted from SQL. - [Required]
// OIRow - The OpenInsight row associated with the OpenInsight Key ID. - [Optional]
// OIColumns - An @FM delimited list of OpenInsight table columns that should only be used to write to SQL. If empty,
// all columns that have a map defintion will be used. - [Optional]
//
// Returns an @FM delimited list of SQL insert statements for the SQL table mapped to the indicated OpenInsight table.
// This will automatically create all SQL insert statements for secondary SQL tables as well.
//----------------------------------------------------------------------------------------------------------------------
Service GetSQLMergeStatements(OITableName, OIKeyID, OIRow, OIColumns)
Convert @Lower_Case to @Upper_Case in OITableName
SQLInsertStatements = ''
If (OITableName NE '') AND (OIKeyID NE '') AND (OIRow NE '') then
// Start with the primary SQL table that is mapped to this OpenInsight table.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, PrimarySQLTableName, OIColumns)
MergeClause = SQL_Services('GetMergeClause', OITableName, PrimarySQLTableName, OIKeyID, OIRow)
If MappedSQLColumnNames NE '' then MappedSQLColumnNames := @FM
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, PrimarySQLTableName, OIKeyID, OIRow, '', OIColumns)
If MappedSQLColumnValues NE '' then MappedSQLColumnValues := @FM
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, PrimarySQLTableName)
If JoinedSQLColumnNames NE '' then
MappedSQLColumnNames := JoinedSQLColumnNames : @FM
JoinedSQLColumnValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, PrimarySQLTableName, OIKeyID, OIRow)
MappedSQLColumnValues := JoinedSQLColumnValues : @FM
end
StaticSQLColumnNames = SQL_Services('GetStaticSQLColumnNames', OITableName)
If StaticSQLColumnNames NE '' then
MappedSQLColumnNames := StaticSQLColumnNames : @FM
StaticSQLColumnValues = SQL_Services('GetStaticSQLColumnValues', OITableName)
MappedSQLColumnValues := StaticSQLColumnValues : @FM
end
MappedSQLColumnNames[-1, 1] = ''
MappedSQLColumnValues[-1, 1] = ''
Swap @FM with ', ' in MappedSQLColumnNames
Swap @FM with ", " in MappedSQLColumnValues
SQLInsertStatement = 'BEGIN '
SQLInsertStatement := 'SET NOCOUNT ON; '
SQLInsertStatement := 'MERGE ':PrimarySQLTableName:' AS tgt '
SQLInsertStatement := 'USING (VALUES (':MappedSQLColumnValues:')) AS src (':MappedSQLColumnNames:') '
SQLInsertStatement := 'ON (':MergeClause:') '
SQLInsertStatement := 'WHEN MATCHED THEN '
SQLInsertStatement := ' UPDATE SET '
For Each SQLColumnName in MappedSQLColumnNames using ','setting fPos
SQLColumnName = Trim(SQLColumnName)
SQLInsertStatement := SQLColumnName : ' = src.' : SQLColumnName : ', '
Next SQLColumnName
SQLInsertStatement[-2, 1] = ''
SQLInsertStatement := 'WHEN NOT MATCHED THEN '
SQLInsertStatement := ' INSERT (':MappedSQLColumnNames:') '
SQLInsertStatement := ' VALUES (':MappedSQLColumnValues:'); '
SQLInsertStatement := 'END;'
SQLInsertStatements := SQLInsertStatement : @FM
If Error_Services('NoError') then
// Add any secondary SQL table inserts that might be required.
SecondarySQLTableNames = SQL_Services('GetSecondarySQLTables', OITableName)
If SecondarySQLTableNames NE '' then
For Each SecondarySQLTableName in SecondarySQLTableNames using @FM
OIColumnValue = '' ; // Default to empty string. Update if AMV Master is found.
NumPositions = 1 ; // Default to only 1 index position. Update if AMV Master is found.
AMVMaster = SQL_Services('GetAMVMaster', OITableName, SecondarySQLTableName)
If AMVMaster NE '' then
FieldArray = Database_Services('ReadDataRow', 'DICT.' : OITablename, '%FIELDS%')
If Error_Services('NoError') then
Locate AMVMaster in FieldArray<FIELDS_NAME$> using @VM setting vPos then
OIColumnType = FieldArray<FIELDS_TYPE$, vPos>
If OIColumnType EQ 'F' then
OIColumnPos = FieldArray<FIELDS_FIELD_NO$, vPos>
If OIColumnPos GT 0 then
OIColumnValue = OIRow<OIColumnPos>
end else
OIKeyPart = FieldArray<FIELDS_PART$, vPos>
OIColumnValue = Field(OIKeyID, '*', OIKeyPart, 1)
end
end else
// OIColumnValue = Calculate(OIColumnName) ; // Actual logic used in MFS
OIColumnValue = Xlate(OITablename, OIKeyID, OIColumnName, 'X')
end
NumPositions = DCount(OIColumnValue, @VM)
end
end
end
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, SecondarySQLTableName)
If MappedSQLColumnNames NE '' then
JoinedSQLColumnNames = SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SecondarySQLTableName)
If JoinedSQLColumnNames NE '' then
MappedSQLColumnNames := @FM : JoinedSQLColumnNames
end
Swap @FM with ', ' in MappedSQLColumnNames
For AMVPosition = 1 to NumPositions
If OIColumnValue<0, AMVPosition> NE '' then
MergeClause = SQL_Services('GetMergeClause', OITableName, SecondarySQLTableName, OIKeyID, OIRow)
MappedSQLColumnValues = SQL_Services('GetMappedSQLColumnValues', OITablename, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
If JoinedSQLColumnNames NE '' then
JoinedSQLColumnValues = SQL_Services('GetMappedJoinedSQLColumnValues', OITableName, SecondarySQLTableName, OIKeyID, OIRow, AMVPosition)
MappedSQLColumnValues := @FM : JoinedSQLColumnValues
end
Swap @FM with ', ' in MappedSQLColumnValues
SQLInsertStatement = 'BEGIN '
SQLInsertStatement := 'SET NOCOUNT ON; '
SQLInsertStatement := 'MERGE ':SecondarySQLTableName:' AS tgt '
SQLInsertStatement := 'USING (VALUES (':MappedSQLColumnValues:')) AS src (':MappedSQLColumnNames:') '
SQLInsertStatement := 'ON (':MergeClause:') '
SQLInsertStatement := 'WHEN MATCHED THEN '
SQLInsertStatement := ' UPDATE SET '
For Each SQLColumnName in MappedSQLColumnNames using ',' setting fPos
SQLColumnName = Trim(SQLColumnName)
SQLInsertStatement := SQLColumnName : ' = src.' : SQLColumnName : ', '
Next SQLColumnName
SQLInsertStatement[-2, 1] = ''
SQLInsertStatement := 'WHEN NOT MATCHED THEN '
SQLInsertStatement := ' INSERT (':MappedSQLColumnNames:') '
SQLInsertStatement := ' VALUES (':MappedSQLColumnValues:'); '
SQLInsertStatement := 'END;'
SQLInsertStatements := SQLInsertStatement : @FM
end
Next AMVPosition
end
Next SecondarySQLTableName
end
end
SQLInsertStatements[-1, 1] = ''
end else
Error_Services('Add', 'The OITableName, OIKeyID, or OIRow argument was missing in the ' : Service : ' service.')
end
Response = SQLInsertStatements
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSQLSelectStatement
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being deleted from SQL. - [Required]
// OIRow - The OpenInsight row associated with the OpenInsight Key ID. - [Optional]
//
// Returns the SQL select statement for the indicated SQL table based on its mapping to the indicated OpenInsight table.
//----------------------------------------------------------------------------------------------------------------------
Service GetSQLSelectStatement(OITableName, SQLTableName, OIKeyID, OIRow)
Convert @Lower_Case to @Upper_Case in OITableName
SQLSelectStatement = ''
If (OITableName NE '') AND (SQLTableName NE '') AND (OIKeyID NE '') then
JoinClause = SQL_Services('GetJoinClause', OITableName, SQLTableName, OIKeyID, OIRow, '', True$)
If JoinClause NE '' then
MappedSQLColumnNames = SQL_Services('GetMappedSQLColumnNames', OITableName, SQLTableName)
If MappedSQLColumnNames NE '' then
// Include the join columns among the columns being returned so their values can be updated in their
// joined OpenInsight columns (if applicable).
MappedSQLColumnNames := @FM : SQL_Services('GetMappedJoinedSQLColumnNames', OITableName, SQLTableName)
Swap @FM with ', ' in MappedSQLColumnNames
SQLSelectStatement := 'SELECT '
SQLSelectStatement := MappedSQLColumnNames : ' '
SQLSelectStatement := 'FROM ' : SQLTableName : ' '
SQLSelectStatement := 'WHERE '
SQLSelectStatement := JoinClause : ' '
end
end
end else
Error_Services('Add', 'The OITableName, SQLTableName, or OIKeyID argument was missing in the ' : Service : ' service.')
end
Response = SQLSelectStatement
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSQLDeleteStatements
//
// OITableName - The name of the OpenInsight table that is mapped to the SQL table. - [Required]
// OIKeyID - The Key ID to the OpenInsight row being deleted from SQL. - [Required]
// OIRow - The OpenInsight row associated with the OpenInsight Key ID. - [Optional]
//
// Returns an @FM delimited list of SQL delete statements for the SQL table mapped to the indicated OpenInsight table.
// This will automatically create all SQL delete statements for secondary SQL tables as well. Note: OIRow will likely be
// an empty string since most join clauses will be based on the OpenInsight Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service GetSQLDeleteStatements(OITableName, OIKeyID, OIRow)
Convert @Lower_Case to @Upper_Case in OITableName
SQLDeleteStatements = ''
If (OITableName NE '') AND (OIKeyID NE '') then
// Start with the primary SQL table that is mapped to this OpenInsight table.
PrimarySQLTableName = SQL_Services('GetPrimarySQLTable', OITableName)
JoinClause = SQL_Services('GetJoinClause', OITableName, PrimarySQLTableName, OIKeyID, OIRow, '', True$)
SQLDeleteStatement = 'DELETE FROM ' : PrimarySQLTableName : ' '
SQLDeleteStatement := 'WHERE '
SQLDeleteStatement := JoinClause
SQLDeleteStatements := SQLDeleteStatement : @FM
// Add any secondary SQL table inserts that might be required.
SecondarySQLTableNames = SQL_Services('GetSecondarySQLTables', OITableName)
If SecondarySQLTableNames NE '' then
For Each SecondarySQLTableName in SecondarySQLTableNames using @FM
JoinClause = SQL_Services('GetJoinClause', OITableName, SecondarySQLTableName, OIKeyID, OIRow, '', True$)
SQLDeleteStatement = 'DELETE FROM ' : SecondarySQLTableName : ' '
SQLDeleteStatement := 'WHERE '
SQLDeleteStatement := JoinClause
SQLDeleteStatements := SQLDeleteStatement : @FM
Next SecondarySQLTableName
end
SQLDeleteStatements[-1, 1] = ''
end else
Error_Services('Add', 'The OITableName or OIKeyID argument was missing in the ' : Service : ' service.')
end
Response = SQLDeleteStatements
end service
//----------------------------------------------------------------------------------------------------------------------
// PostSQLRequest
//
// This service can be used to post SQL queries to databases that are not reachable from the originating server.
// Requests are processed within the ProcessSQLRequests service.
//
// Input:
// ServerID - Key to SERVERS record containing external SQL database connection string
// Query - SQL query to execute
//
// Output:
// Response - Query response
//----------------------------------------------------------------------------------------------------------------------
Service PostSQLRequest(ServerID, Query)
Response = ''
If (ServerID NE '') and (Query NE '') then
RequestDate = Date()
RequestTime = Time()
RequestKeyID = @Station:'*':RequestDate :'*':RequestTime
RequestRow = ''
RequestRow<SQL_REQUESTS.DB_PATH$> = ServerID
RequestRow<SQL_REQUESTS.QUERY$> = Query
Database_Services('WriteDataRow', 'SQL_REQUESTS', RequestKeyID, RequestRow, True$, False$, True$)
If Error_Services('NoError') then
TimeExpired = False$
Start = GetTickCount()
Loop
RequestRow = Database_Services('ReadDataRow', 'SQL_REQUESTS', RequestKeyID)
ResponseDate = RequestRow<SQL_REQUESTS.RESPONSE_DATE$>
If ResponseDate NE '' then
Response = RequestRow<SQL_REQUESTS.RESPONSE$>
Response = SRP_Decode(Response)
end
// Time will expire after 60 seconds.
If GetTickCount() - Start GE 60000 then TimeExpired = True$
Until (ResponseDate NE '') OR TimeExpired
Sleepery(10)
WinYield()
Yield();Yield();Yield();Yield();Yield();Yield();Yield();Yield()
Repeat
If TimeExpired then
Error_Services('Add', 'SQL request timed out in the ' : Service : ' service.')
end
Open 'SQL_REQUESTS' to hSQLRequests then
Delete hSQLRequests, RequestKeyID else
Null
//Error_Services('Add', 'Error in ':Service:' service. Failed to delete SQL_REQUESTS ':RequestKeyID)
end
end
end
end else
If RowExists('SQL_REQUESTS', RequestKeyID) then
Open 'SQL_REQUESTS' to hSQLRequests then
Delete hSQLRequests, RequestKeyID else
Null
//Error_Services('Add', 'Error in ':Service:' service. Failed to delete SQL_REQUESTS ':RequestKeyID)
end
end
end
Error_Services('Add', 'Null parameter passed into service call. All parameters are required.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// PostSQLStatement
//
// This service can be used to post SQL statements to databases that are not reachable from the originating server.
// Requests are processed within the ProcessSQLRequests service.
//
// Input:
// ServerID - Key to SERVERS record containing external SQL database connection string
// Statement - SQL statement to execute
//
// Output:
// Response - Query response
//----------------------------------------------------------------------------------------------------------------------
Service PostSQLStatement(ServerID, Statement)
Response = ''
If (ServerID NE '') and (Statement NE '') then
RequestDate = Date()
RequestTime = Time()
RequestKeyID = @Station:'*':RequestDate :'*':RequestTime
RequestRow = ''
RequestRow<SQL_REQUESTS.DB_PATH$> = ServerID
RequestRow<SQL_REQUESTS.QUERY$> = Statement
Database_Services('WriteDataRow', 'SQL_REQUESTS', RequestKeyID, RequestRow, True$, False$, True$)
If Error_Services('HasError') then
Error_Services('Add', 'Error in ':Service:' service. Failed to post SQL statement to queue!')
end
end else
If RowExists('SQL_REQUESTS', RequestKeyID) then
Open 'SQL_REQUESTS' to hSQLRequests then
Delete hSQLRequests, RequestKeyID else
Error_Services('Add', 'Error in ':Service:' service. Failed to delete SQL_REQUESTS ':RequestKeyID)
end
end
end
Error_Services('Add', 'Null parameter passed into service call. All parameters are required.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// ProcessSQLRequests
//
// Service that attempts to process external SQL requests. These requests are queued in the SQL_REQUESTS table.
//----------------------------------------------------------------------------------------------------------------------
Service ProcessSQLRequests()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
Tablename = 'SQL_REQUESTS'
hSQLRequests = Database_Services('GetTableHandle', Tablename)
If Error_Services('NoError') then
GoSub ClearCursors
Sentence = 'SELECT ':Tablename:' WITH RESPONSE_DATE EQ "" BY REQUEST_DATE BY REQUEST_TIME'
Set_Status(0)
Update_Index(Tablename, 'REQUEST_DATE', False$, True$)
Update_Index(Tablename, 'REQUEST_TIME', False$, True$)
Update_Index(Tablename, 'RESPONSE_DATE', False$, True$)
Update_Index(Tablename, 'RESPONSE_TIME', False$, True$)
RList(Sentence, TARGET_ACTIVELIST$, '', '', '')
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF
RequestRow = Database_Services('ReadDataRow', 'SQL_REQUESTS', RequestKeyID)
ServerID = RequestRow<SQL_REQUESTS.DB_PATH$>
Query = RequestRow<SQL_REQUESTS.QUERY$>
Response = SQL_Services('GetDataRows', ServerID, Query, 3)
Response = SRP_Encode(Response)
RequestRow<SQL_REQUESTS.RESPONSE_DATE$> = Date()
RequestRow<SQL_REQUESTS.RESPONSE_TIME$> = Time()
RequestRow<SQL_REQUESTS.RESPONSE$> = Response
Database_Services('WriteDataRow', 'SQL_REQUESTS', RequestKeyID, RequestRow, True$, False$, True$)
KeyLocked = Database_Services('IsKeyIDLocked', 'SQL_REQUESTS', RequestKeyID)
If KeyLocked then Database_Services('ReleaseKeyIDLock', 'SQL_REQUESTS', RequestKeyID)
Repeat
// Cleanup really old requests (i.e. those that are older than 48 hours)
GoSub ClearCursors
Set_Status(0)
CleanDate = Date() - 1
Sentence = 'SELECT ':Tablename:' WITH RESPONSE_DATE NE "" AND WITH RESPONSE_DATE LT ':Quote(OConv(CleanDate, 'D4/'))
RList(Sentence, TARGET_ACTIVELIST$, '', '', '')
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF
Database_Services('DeleteDataRow', 'SQL_REQUESTS', RequestKeyID)
KeyLocked = Database_Services('IsKeyIDLocked', 'SQL_REQUESTS', RequestKeyID)
If KeyLocked then Database_Services('ReleaseKeyIDLock', 'SQL_REQUESTS', RequestKeyID)
Repeat
// Cleanup old requests that may have been "abandoned" by the requesting process (i.e. those that are older
// than two minutes).
GoSub ClearCursors
Set_Status(0)
CleanTime = Time() - 240
Sentence = 'SELECT ':Tablename:' WITH RESPONSE_DATE NE "" AND WITH REQUEST_TIME LT ':Quote(OConv(CleanTime, 'MT'))
RList(Sentence, TARGET_ACTIVELIST$, '', '', '')
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF
Database_Services('DeleteDataRow', 'SQL_REQUESTS', RequestKeyID)
KeyLocked = Database_Services('IsKeyIDLocked', 'SQL_REQUESTS', RequestKeyID)
If KeyLocked then Database_Services('ReleaseKeyIDLock', 'SQL_REQUESTS', RequestKeyID)
Repeat
end else
ErrorMsg = Error_Services('GetMessage')
end
Unlock hSysLists, ServiceKeyID else Null
end
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ClearCursors:
For counter = 0 to 8
ClearSelect counter
Next counter
return
WriteLog:
Declare function Environment_Services, Logging_Services
Declare subroutine Logging_Services
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\Replication'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' WRITE_OI_Error.csv'
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'Table' :@FM : 'Key'
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
LogData = ''
LogData<1, 1> = LoggingDTM
LogData<1, 2> = @User4
LogData<1, 3> = OITableName
LogData<1, 4> = OIKeyID
LogData<1, 5> = Message
Logging_Services('AppendLog', objLog, LogData, @FM, @VM)
return