UPDATE: filterArray()

Bob Sneidar bobsneidar at iotecdigital.com
Fri May 17 17:44:25 EDT 2024


I wrote a filterArray() function with a couple dependencies a while ago which uses a memory sqLite database to convert an array to a database, query that database, then return the results as an array. 

I have a new update to filterArray() which allows for a select clause. I found myself wanting to find the maximum value of a column, so I update the function. For an example lets say I wanted the maximum value for the serviceid key in a numbered array (tRecordsA). I could call it like this: 

      put empty into tConditions
      put "max(serviceid) as serviceid" into tSelectClause
      put filterArray(tRecordsA, tConditions, tSelectClause) into tFoundDataA

Since I do not need a where clause here, as tRecordsA only contains the data I want, but a where clause could also be defined. Here are the handlers if anyone is interested. If I missed any dependencies ley me know and I will pass those along as well. 

Bob S



function filterArray pArrayDataA, pConditions, pSelectClause
   put the defaultFolder & "/" & "tempdatabase.db" into tDBName
   put arrayToSQLite(pArrayDataA, tDBName, "arraydata") into tDBID — uses dependency
   if pSelectClause is empty then \
         put "*" into pSelectClause
   
   put "select " & pSelectClause & " from arraydata" into tQueryString
   
   if pConditions is not empty then \
         put " where" && pConditions after tQueryString
   
   try
      put revQueryDatabase(tDBID, tQueryString) into tCursorID
      put cursorToArray(tCursorID) into tFilteredDataA — uses dependency
      return tFilteredDataA
   catch tError
      return empty
   end try
end filterArray


FUNCTION arrayToSQLite pArrayDataA, pDBFile, pDBName, pDBID, pBinaryColumns
   put the keys of pArrayDataA into tArrayKeys
   sort tArrayKeys numeric ascending
   IF pDBFile is empty THEN put ":memory:" into pDBFile
   IF pDBName is empty THEN put "arraydata" into pDBName
   
   TRY
      if pDBID is empty then \
            put revOpenDatabase("sqlite", pDBFile) into pDBID
      
      IF "Error" is in pDBID THEN
         return empty
      END IF
      
      -- attempt to set the encoding
      put "PRAGMA encoding = 'UTF-16'" into tSQL
      revExecuteSQL pDBID, tSQL
      
      -- attempt to drop the table
      put "drop table " & pDBName into tDropSQL
      revExecuteSQL pDBID, tDropSQL
      put  the result into tResult
   CATCH tError
      answer tError
      IF the environment is "development" THEN exit to top ELSE quit
   END TRY
   
   -- create the table
   put "create table" && quote & pDBName & quote \
         & cr into tCreateCommand
   put "(" & quote & "recordid" & quote && "NUMERIC PRIMARY KEY UNIQUE, " \
         & cr AFTER tCreateCommand
   
   put the keys of pArrayDataA [1] into tRecordKeyList
   filter lines of tRecordKeyList without "recordid"
   
   REPEAT for each line tRecordKey in tRecordKeyList
      if pArrayDataA [1] [tRecordKey] is an array or \
            pArrayDataA [1] [tRecordKey] begins with "Salted__" then 
         put "BLOB" into tColumnType
      else
         put VARCHAR into tColumnType
      end if
      
      put quote & tRecordKey & quote && tColumnType & "," && cr AFTER tCreateCommand
   END REPEAT
   
   delete char -3 to -1 of tCreateCommand
   put ")" AFTER tCreateCommand
   
   TRY
      revExecuteSQL pDBID, tCreateCommand
      put the result into tResult
      IF tResult is not 0 THEN breakpoint
   CATCH tError
      breakpoint
   END TRY
   
   put 1 into tRecordCounter
   put "recordid" & cr & tRecordKeyList into tColumns
   
   repeat with i = 1 to the number of lines of tColumns
      put ":" & i into item i of tColumnList
   end repeat
   
   put "(" & tColumnList & ")" into tColumnList
   
   -- insert data
   REPEAT for each line tKey in tArrayKeys
      put 1 into tColumnCounter
      put pArrayDataA [tKey] into tRecordDataA
      put tRecordCounter into tQueryDataA [1]
      
      REPEAT for each line tRecordKey in tRecordKeyList
         add 1 to tColumnCounter
         
         if tRecordDataA [tRecordKey] is an array then
            put arrayEncode(tRecordDataA [tRecordKey]) into tValue
         else
            put tRecordDataA [tRecordKey] into tValue
         end if
         
         put tValue into tQueryDataA [tColumnCounter]
      END REPEAT
      
      put "insert into" && pDBName &&  "VALUES" && tColumnList into tInsertSQL
      
      TRY
         revExecuteSQL pDBID, tInsertSQL, "tQueryDataA"
         put the result into tResult
         if the result is not a number then breakpoint
      CATCH tError
         breakpoint
      END TRY
      
      add 1 to tRecordCounter
   END REPEAT
   
   return pDBID
END arrayToSQLite


FUNCTION cursorToArray pCursorID
   put revNumberOfRecords(pCursorID) into tNumberOfRecords
   if tNumberOfRecords = 0 then \
         return empty
      
   put revDatabaseColumnCount(pCursorID) into tColumnCount
   put revDatabaseColumnNames(pCursorID) into tColumnNames
   
   REPEAT forever
      add 1 to tRecordCount
      REPEAT with i = 1 to tColumnCount
         put revDatabaseColumnNumbered(pCursorID, i) into tColumnValue
         put tColumnValue into aCursorArray [tRecordCount] [item i of tColumnNames]
      END REPEAT
      
      revMoveToNextRecord pCursorID
      if revQueryIsAtEnd(pCursorID) then \
            exit repeat
   END REPEAT
   
   return aCursorArray
END cursorToArray


More information about the use-livecode mailing list