Re: Strings mit SQLite berechnen
Verfasst: 07.05.2011 01:14
				
				String (bzw. allgemein: Ausdrücke) mit einer Datenbank-Enige berechnen zu lassen ist wirklich Trickreich, dass habe ich schon damals "bewundet".
Doch diese Methode sollte man wirklich nur "ab und zu" verwenden.
Führt man eine solche Funktion z.B. in einer Schleife aus, geht das Programm "relativ schnell" in die Knie.
Dort kommt man um einen "eigenen" Compiler nicht drum rum.
Trotzdem möchte ich in diesem Thema noch eine kleine Erweiterung bereitstellen.
Das ganze heißt bei mir Evaluator.
Mit diesem Include ist es möglich Ausdrücke berechnen zu lassen, und als erweiterung sogar Variablen zu benutzten, als Schnittstelle zwischen PB und dem Evaluator.
Dazu kann man EvaluatorEnvironment erstellen.
			Doch diese Methode sollte man wirklich nur "ab und zu" verwenden.
Führt man eine solche Funktion z.B. in einer Schleife aus, geht das Programm "relativ schnell" in die Knie.
Dort kommt man um einen "eigenen" Compiler nicht drum rum.
Trotzdem möchte ich in diesem Thema noch eine kleine Erweiterung bereitstellen.
Das ganze heißt bei mir Evaluator.
Mit diesem Include ist es möglich Ausdrücke berechnen zu lassen, und als erweiterung sogar Variablen zu benutzten, als Schnittstelle zwischen PB und dem Evaluator.
Dazu kann man EvaluatorEnvironment erstellen.
Code: Alles auswählen
; Konstanten
Enumeration 
   #Evaluator_VariableType_Integer
   #Evaluator_VariableType_Float
   #Evaluator_VariableType_String
EndEnumeration
; Strukturen
Structure EvaluatorVariable
   Type.i
   StructureUnion
      Integer.i
      Float.f
   EndStructureUnion
   String.s
EndStructure
Structure EvaluatorEnvironment
   Map Variable.EvaluatorVariable()
EndStructure
Structure Evaluator
   Database.i
   List Environment.EvaluatorEnvironment()
EndStructure
; Initialisierung
Procedure InitEvaluator()
   Global Evaluator.Evaluator
   UseSQLiteDatabase()
   Evaluator\Database = OpenDatabase(#PB_Any, ":memory:", "", "", #PB_Database_SQLite)
EndProcedure
; Interne Funktion
Procedure.i Evaluator_DatabaseQuery(String.s, *Environment.EvaluatorEnvironment=#Null)
   Protected Valiabels.s, Query.s = "SELECT "+String
   If *Environment And MapSize(*Environment\Variable())
      Query + " FROM ( SELECT "
      ForEach *Environment\Variable()
         If Valiabels : Valiabels + ", " : EndIf
         Select *Environment\Variable()\Type
            Case #Evaluator_VariableType_String
               Valiabels + "'"+ReplaceString(*Environment\Variable()\String, "'", "''")+"'"
            Case #Evaluator_VariableType_Integer
               Valiabels + Str(*Environment\Variable()\Integer)
            Case #Evaluator_VariableType_Float
               Valiabels + StrF(*Environment\Variable()\Float)
         EndSelect
         Valiabels + " AS "+MapKey(*Environment\Variable())
      Next
      Query + Valiabels + ")"
   EndIf
   ProcedureReturn DatabaseQuery(Evaluator\Database, Query)
EndProcedure
; EvaluatorEnvironment 
Procedure.i NewEvaluatorEnvironment()
   ProcedureReturn AddElement(Evaluator\Environment())
EndProcedure
Procedure FreeEvaluatorEnvironment(*Environment.EvaluatorEnvironment)
   ChangeCurrentElement(Evaluator\Environment(), *Environment)
   DeleteElement(Evaluator\Environment())
EndProcedure
Procedure.i SetEvaluatorEnvironmentString(*Environment.EvaluatorEnvironment, Name.s, Value.s="")
   AddMapElement(*Environment\Variable(), Name)
   *Environment\Variable()\Type = #Evaluator_VariableType_String
   *Environment\Variable()\String = Value
EndProcedure
Procedure.i SetEvaluatorEnvironmentInteger(*Environment.EvaluatorEnvironment, Name.s, Value.i=0)
   AddMapElement(*Environment\Variable(), Name) 
   *Environment\Variable()\Type = #Evaluator_VariableType_Integer
   *Environment\Variable()\Integer = Value
EndProcedure
Procedure.i SetEvaluatorEnvironmentFloat(*Environment.EvaluatorEnvironment, Name.s, Value.f=0)
   AddMapElement(*Environment\Variable(), Name) 
   *Environment\Variable()\Type = #Evaluator_VariableType_Float
   *Environment\Variable()\Float = Value
EndProcedure
; Evaluator
Procedure.i Evaluate(String.s, *Environment.EvaluatorEnvironment=#Null)
   If Trim(String) = "" : String = "0" : EndIf
   If Evaluator_DatabaseQuery(String, *Environment)
      If NextDatabaseRow(Evaluator\Database)
         CompilerIf SizeOf(Integer) = SizeOf(Quad)
            ProcedureReturn GetDatabaseQuad(Evaluator\Database, 0)
         CompilerElse
            ProcedureReturn GetDatabaseLong(Evaluator\Database, 0)
         CompilerEndIf
      EndIf
      FinishDatabaseQuery(Evaluator\Database)
   EndIf
EndProcedure
Procedure.s EvaluateS(String.s, *Environment.EvaluatorEnvironment=#Null)
   If Trim(String) = "" : String = "''" : EndIf
   If Evaluator_DatabaseQuery(String, *Environment)
      If NextDatabaseRow(Evaluator\Database)
         ProcedureReturn GetDatabaseString(Evaluator\Database, 0)
      EndIf
      FinishDatabaseQuery(Evaluator\Database)
   EndIf   
EndProcedure
Procedure.f EvaluateF(String.s, *Environment.EvaluatorEnvironment=#Null)
   If Trim(String) = "" : String = "0.0" : EndIf
   If Evaluator_DatabaseQuery(String, *Environment)
      If NextDatabaseRow(Evaluator\Database)
         ProcedureReturn GetDatabaseFloat(Evaluator\Database, 0)
      EndIf
      FinishDatabaseQuery(Evaluator\Database)
   EndIf
EndProcedure
Procedure.s EvaluateError()
   ProcedureReturn DatabaseError()
EndProcedure
; Beispiel
InitEvaluator()
Debug "-----------------"
Debug Evaluate("1 + 2 + 3")
Debug EvaluateF("0.25 * 2")
Debug EvaluateS("'Hallo' || ' Welt'")
Debug "-----------------"
*Environment = NewEvaluatorEnvironment()
SetEvaluatorEnvironmentInteger(*Environment, "n", 64)
SetEvaluatorEnvironmentString(*Environment, "Text", "Hallo Welt")
SetEvaluatorEnvironmentFloat(*Environment, "f", 0.25)
Debug Evaluate("n < 100 AND n > 50", *Environment)
Debug EvaluateF("n * f", *Environment)
Debug EvaluateS("(100 * f) || ' %'", *Environment)