|
@@ -78,7 +78,7 @@ const
|
|
|
detRollBack = sqltypes.detRollBack;
|
|
|
detParamValue = sqltypes.detParamValue;
|
|
|
detActualSQL = sqltypes.detActualSQL;
|
|
|
-
|
|
|
+ DefaultMacroChar = '%';
|
|
|
Type
|
|
|
TRowsCount = LargeInt;
|
|
|
|
|
@@ -361,6 +361,9 @@ type
|
|
|
FDatabase: TSQLConnection;
|
|
|
FParamCheck: Boolean;
|
|
|
FParams: TParams;
|
|
|
+ FMacroCheck: Boolean;
|
|
|
+ FMacroChar: Char;
|
|
|
+ FMacros: TParams;
|
|
|
FSQL: TStrings;
|
|
|
FOrigSQL : String;
|
|
|
FServerSQL : String;
|
|
@@ -368,10 +371,15 @@ type
|
|
|
FParseSQL: Boolean;
|
|
|
FDataLink : TDataLink;
|
|
|
FRowsAffected : TRowsCount;
|
|
|
+ function ExpandMacros( OrigSQL: String): String;
|
|
|
procedure SetDatabase(AValue: TSQLConnection);
|
|
|
+ procedure SetMacroChar(AValue: Char);
|
|
|
+ procedure SetMacroCheck(AValue: Boolean);
|
|
|
procedure SetParams(AValue: TParams);
|
|
|
+ procedure SetMacros(AValue: TParams);
|
|
|
procedure SetSQL(AValue: TStrings);
|
|
|
procedure SetTransaction(AValue: TSQLTransaction);
|
|
|
+ procedure RecreateMacros;
|
|
|
Function GetPrepared : Boolean;
|
|
|
Protected
|
|
|
Function CreateDataLink : TDataLink; virtual;
|
|
@@ -398,9 +406,12 @@ type
|
|
|
Property Transaction : TSQLTransaction Read FTransaction Write SetTransaction;
|
|
|
Property SQL : TStrings Read FSQL Write SetSQL;
|
|
|
Property Params : TParams Read FParams Write SetParams;
|
|
|
+ Property Macros : TParams Read FMacros Write SetMacros;
|
|
|
+ property MacroChar: Char read FMacroChar write SetMacroChar default DefaultMacroChar;
|
|
|
Property DataSource : TDataSource Read GetDataSource Write SetDataSource;
|
|
|
Property ParseSQL : Boolean Read FParseSQL Write FParseSQL;
|
|
|
Property ParamCheck : Boolean Read FParamCheck Write FParamCheck default true;
|
|
|
+ Property MacroCheck : Boolean Read FMacroCheck Write SetMacroCheck default false;
|
|
|
Public
|
|
|
constructor Create(AOwner : TComponent); override;
|
|
|
destructor Destroy; override;
|
|
@@ -418,6 +429,8 @@ type
|
|
|
Property DataSource;
|
|
|
Property ParamCheck;
|
|
|
Property Params;
|
|
|
+ Property MacroCheck;
|
|
|
+ Property Macros;
|
|
|
Property ParseSQL;
|
|
|
Property SQL;
|
|
|
Property Transaction;
|
|
@@ -484,8 +497,11 @@ type
|
|
|
FDeleteQry : TCustomSQLQuery;
|
|
|
FSequence : TSQLSequence;
|
|
|
procedure FreeFldBuffers;
|
|
|
+ function GetMacroChar: Char;
|
|
|
function GetParamCheck: Boolean;
|
|
|
function GetParams: TParams;
|
|
|
+ function GetMacroCheck: Boolean;
|
|
|
+ function GetMacros: TParams;
|
|
|
function GetParseSQL: Boolean;
|
|
|
function GetServerIndexDefs: TServerIndexDefs;
|
|
|
function GetSQL: TStringList;
|
|
@@ -493,8 +509,10 @@ type
|
|
|
function GetSQLTransaction: TSQLTransaction;
|
|
|
function GetStatementType : TStatementType;
|
|
|
Function NeedLastInsertID: TField;
|
|
|
+ procedure SetMacroChar(AValue: Char);
|
|
|
procedure SetOptions(AValue: TSQLQueryOptions);
|
|
|
procedure SetParamCheck(AValue: Boolean);
|
|
|
+ procedure SetMacroCheck(AValue: Boolean);
|
|
|
procedure SetSQLConnection(AValue: TSQLConnection);
|
|
|
procedure SetSQLTransaction(AValue: TSQLTransaction);
|
|
|
procedure SetInsertSQL(const AValue: TStringList);
|
|
@@ -502,6 +520,7 @@ type
|
|
|
procedure SetDeleteSQL(const AValue: TStringList);
|
|
|
procedure SetRefreshSQL(const AValue: TStringList);
|
|
|
procedure SetParams(AValue: TParams);
|
|
|
+ procedure SetMacros(AValue: TParams);
|
|
|
procedure SetParseSQL(AValue : Boolean);
|
|
|
procedure SetSQL(const AValue: TStringList);
|
|
|
procedure SetUsePrimaryKeyAsKey(AValue : Boolean);
|
|
@@ -561,6 +580,7 @@ type
|
|
|
procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
|
|
|
function RowsAffected: TRowsCount; virtual;
|
|
|
function ParamByName(Const AParamName : String) : TParam;
|
|
|
+ function MacroByName(Const AParamName : String) : TParam;
|
|
|
Property Prepared : boolean read IsPrepared;
|
|
|
Property SQLConnection : TSQLConnection Read GetSQLConnection Write SetSQLConnection;
|
|
|
Property SQLTransaction: TSQLTransaction Read GetSQLTransaction Write SetSQLTransaction;
|
|
@@ -611,6 +631,9 @@ type
|
|
|
Property Options : TSQLQueryOptions Read FOptions Write SetOptions default [];
|
|
|
property Params : TParams read GetParams Write SetParams;
|
|
|
Property ParamCheck : Boolean Read GetParamCheck Write SetParamCheck default true;
|
|
|
+ property Macros : TParams read GetMacros Write SetMacros;
|
|
|
+ Property MacroCheck : Boolean Read GetMacroCheck Write SetMacroCheck default false;
|
|
|
+ Property MacroChar : Char Read GetMacroChar Write SetMacroChar default DefaultMacroChar;
|
|
|
property ParseSQL : Boolean read GetParseSQL write SetParseSQL default true;
|
|
|
property UpdateMode : TUpdateMode read FUpdateMode write SetUpdateMode default upWhereKeyOnly;
|
|
|
property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey default true;
|
|
@@ -673,6 +696,9 @@ type
|
|
|
Property Options;
|
|
|
property Params;
|
|
|
Property ParamCheck;
|
|
|
+ property Macros;
|
|
|
+ Property MacroCheck;
|
|
|
+ Property MacroChar;
|
|
|
property ParseSQL;
|
|
|
property UpdateMode;
|
|
|
property UsePrimaryKeyAsKey;
|
|
@@ -891,6 +917,7 @@ var
|
|
|
|
|
|
begin
|
|
|
UnPrepare;
|
|
|
+ RecreateMacros;
|
|
|
if not ParamCheck then
|
|
|
exit;
|
|
|
if assigned(DataBase) then
|
|
@@ -927,6 +954,20 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLStatement.SetMacroChar(AValue: Char);
|
|
|
+begin
|
|
|
+ if FMacroChar=AValue then Exit;
|
|
|
+ FMacroChar:=AValue;
|
|
|
+ RecreateMacros;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TCustomSQLStatement.SetMacroCheck(AValue: Boolean);
|
|
|
+begin
|
|
|
+ if FMacroCheck=AValue then Exit;
|
|
|
+ FMacroCheck:=AValue;
|
|
|
+ RecreateMacros;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLStatement.SetTransaction(AValue: TSQLTransaction);
|
|
|
begin
|
|
|
if FTransaction=AValue then Exit;
|
|
@@ -942,6 +983,36 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLStatement.RecreateMacros;
|
|
|
+var
|
|
|
+ NewParams: TSQLDBParams;
|
|
|
+ ConnOptions: TConnOptions;
|
|
|
+ PO : TSQLParseOptions;
|
|
|
+ PB : TParamBinding;
|
|
|
+ RS : String;
|
|
|
+
|
|
|
+begin
|
|
|
+ if MacroCheck then begin
|
|
|
+ if assigned(DataBase) then
|
|
|
+ ConnOptions:=DataBase.ConnOptions
|
|
|
+ else
|
|
|
+ ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
|
|
|
+ NewParams := CreateParams;
|
|
|
+ try
|
|
|
+ PO:=[spoCreate,spoUseMacro];
|
|
|
+ if sqEscapeSlash in ConnOptions then
|
|
|
+ Include(PO,spoEscapeSlash);
|
|
|
+ if sqEscapeRepeat in ConnOptions then
|
|
|
+ Include(PO,spoEscapeRepeat);
|
|
|
+ NewParams.ParseSQL(FSQL.Text, PO, psInterbase, PB, MacroChar,RS);
|
|
|
+ NewParams.AssignValues(FMacros);
|
|
|
+ FMacros.Assign(NewParams);
|
|
|
+ finally
|
|
|
+ NewParams.Free;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLStatement.SetDataSource(AValue: TDataSource);
|
|
|
|
|
|
begin
|
|
@@ -951,7 +1022,7 @@ begin
|
|
|
FDataLink.DataSource:=AValue;
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound: Boolean);
|
|
|
+procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound: Boolean);
|
|
|
begin
|
|
|
if Assigned(DataSource) and Assigned(DataSource.Dataset) then
|
|
|
FParams.CopyParamValuesFromDataset(DataSource.Dataset,CopyBound);
|
|
@@ -963,13 +1034,20 @@ begin
|
|
|
FParams.Assign(AValue);
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLStatement.SetMacros(AValue: TParams);
|
|
|
+begin
|
|
|
+ if FMacros=AValue then Exit;
|
|
|
+ FMacros.Assign(AValue);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLStatement.SetSQL(AValue: TStrings);
|
|
|
begin
|
|
|
if FSQL=AValue then Exit;
|
|
|
FSQL.Assign(AValue);
|
|
|
+ RecreateMacros;
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.DoExecute;
|
|
|
+procedure TCustomSQLStatement.DoExecute;
|
|
|
begin
|
|
|
FRowsAffected:=-1;
|
|
|
If (FParams.Count>0) and Assigned(DataSource) then
|
|
@@ -979,27 +1057,27 @@ begin
|
|
|
Database.Execute(FCursor,Transaction, FParams);
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.GetPrepared: Boolean;
|
|
|
+function TCustomSQLStatement.GetPrepared: Boolean;
|
|
|
begin
|
|
|
Result := Assigned(FCursor) and FCursor.FPrepared;
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.CreateDataLink: TDataLink;
|
|
|
+function TCustomSQLStatement.CreateDataLink: TDataLink;
|
|
|
begin
|
|
|
Result:=TDataLink.Create;
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.CreateParams: TSQLDBParams;
|
|
|
+function TCustomSQLStatement.CreateParams: TSQLDBParams;
|
|
|
begin
|
|
|
Result:=TSQLDBParams.Create(Nil);
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
|
|
|
+function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
|
|
|
begin
|
|
|
Result:=Assigned(Database) and Database.LogEvent(EventType);
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.Log(EventType: TDBEventType; Const Msg: String);
|
|
|
+procedure TCustomSQLStatement.Log(EventType: TDBEventType; const Msg: String);
|
|
|
Var
|
|
|
M : String;
|
|
|
|
|
@@ -1035,6 +1113,9 @@ begin
|
|
|
TStringList(FSQL).OnChange:=@OnChangeSQL;
|
|
|
FParams:=CreateParams;
|
|
|
FParamCheck:=True;
|
|
|
+ FMacros:=CreateParams;
|
|
|
+ FMacroChar:=DefaultMacroChar;
|
|
|
+ FMacroCheck:=False;
|
|
|
FParseSQL:=True;
|
|
|
FRowsAffected:=-1;
|
|
|
end;
|
|
@@ -1047,27 +1128,28 @@ begin
|
|
|
DataSource:=Nil;
|
|
|
FreeAndNil(FDataLink);
|
|
|
FreeAndNil(FParams);
|
|
|
+ FreeAndNil(FMacros);
|
|
|
FreeAndNil(FSQL);
|
|
|
inherited Destroy;
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.GetSchemaType: TSchemaType;
|
|
|
+function TCustomSQLStatement.GetSchemaType: TSchemaType;
|
|
|
|
|
|
begin
|
|
|
Result:=stNoSchema
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.GetSchemaObjectName: String;
|
|
|
+function TCustomSQLStatement.GetSchemaObjectName: String;
|
|
|
begin
|
|
|
Result:='';
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.GetSchemaPattern: String;
|
|
|
+function TCustomSQLStatement.GetSchemaPattern: String;
|
|
|
begin
|
|
|
Result:='';
|
|
|
end;
|
|
|
|
|
|
-Function TCustomSQLStatement.IsSelectable: Boolean;
|
|
|
+function TCustomSQLStatement.IsSelectable: Boolean;
|
|
|
begin
|
|
|
Result:=False;
|
|
|
end;
|
|
@@ -1092,6 +1174,65 @@ begin
|
|
|
DataBase.DeAllocateCursorHandle(FCursor);
|
|
|
end;
|
|
|
|
|
|
+function TCustomSQLStatement.ExpandMacros( OrigSQL : String ) : String;
|
|
|
+
|
|
|
+Const
|
|
|
+ Terminators = SQLDelimiterCharacters+
|
|
|
+ [ #0,'=','+','-','*','\','/','[',']','|' ];
|
|
|
+
|
|
|
+var
|
|
|
+ I: Integer;
|
|
|
+ Ch : Char;
|
|
|
+ TermArr : Set of Char;
|
|
|
+ TempStr, TempMacroName : String;
|
|
|
+ MacroFlag : Boolean;
|
|
|
+
|
|
|
+ Procedure SubstituteMacro;
|
|
|
+
|
|
|
+ var
|
|
|
+ Param: TParam;
|
|
|
+ begin
|
|
|
+ Param := Macros.FindParam( TempMacroName );
|
|
|
+ if Assigned( Param ) then
|
|
|
+ Result := Result + Param.AsString
|
|
|
+ else
|
|
|
+ Result := Result + MacroChar + TempMacroName;
|
|
|
+ TempMacroName:='';
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result := OrigSQL;
|
|
|
+ if not MacroCheck then
|
|
|
+ Exit;
|
|
|
+ TermArr := Terminators +[MacroChar];
|
|
|
+ Result := '';
|
|
|
+ MacroFlag := False;
|
|
|
+ for Ch in OrigSQL do
|
|
|
+ begin
|
|
|
+ if not MacroFlag and (Ch=MacroChar) then
|
|
|
+ begin
|
|
|
+ MacroFlag := True;
|
|
|
+ TempMacroName := '';
|
|
|
+ end
|
|
|
+ else if MacroFlag then
|
|
|
+ begin
|
|
|
+ if not (Ch In TermArr) then
|
|
|
+ TempMacroName := TempMacroName + Ch
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ SubstituteMacro;
|
|
|
+ if Ch <> MacroChar then
|
|
|
+ MacroFlag := False;
|
|
|
+ TempMacroName := '';
|
|
|
+ end
|
|
|
+ end;
|
|
|
+ if not MacroFlag then
|
|
|
+ Result := Result + Ch;
|
|
|
+ end;
|
|
|
+ if (TempMacroName<>'') then
|
|
|
+ SubstituteMacro;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLStatement.DoPrepare;
|
|
|
|
|
|
var
|
|
@@ -1103,7 +1244,7 @@ begin
|
|
|
FOrigSQL := Database.GetSchemaInfoSQL(GetSchemaType, GetSchemaObjectName, GetSchemaPattern);
|
|
|
if (FOrigSQL='') then
|
|
|
DatabaseError(SErrNoStatement);
|
|
|
- FServerSQL:=FOrigSQL;
|
|
|
+ FServerSQL:=ExpandMacros( FOrigSQL );
|
|
|
GetStatementInfo(FServerSQL,StmInfo);
|
|
|
AllocateCursor;
|
|
|
FCursor.FSelectable:=True; // let PrepareStatement and/or Execute alter it
|
|
@@ -1114,7 +1255,7 @@ begin
|
|
|
Database.PrepareStatement(FCursor,Transaction,FServerSQL,FParams);
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.Prepare;
|
|
|
+procedure TCustomSQLStatement.Prepare;
|
|
|
|
|
|
begin
|
|
|
if Prepared then exit;
|
|
@@ -1133,7 +1274,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.Execute;
|
|
|
+procedure TCustomSQLStatement.Execute;
|
|
|
begin
|
|
|
Prepare;
|
|
|
DoExecute;
|
|
@@ -1160,7 +1301,7 @@ begin
|
|
|
Result:=Nil;
|
|
|
end;
|
|
|
|
|
|
-Procedure TCustomSQLStatement.Unprepare;
|
|
|
+procedure TCustomSQLStatement.Unprepare;
|
|
|
begin
|
|
|
// Some SQLConnections does not support statement [un]preparation, but they have allocated local cursor(s)
|
|
|
// so let them do cleanup f.e. cancel pending queries and/or free resultset
|
|
@@ -1169,7 +1310,7 @@ begin
|
|
|
DoUnprepare;
|
|
|
end;
|
|
|
|
|
|
-function TCustomSQLStatement.ParamByName(Const AParamName: String): TParam;
|
|
|
+function TCustomSQLStatement.ParamByName(const AParamName: String): TParam;
|
|
|
begin
|
|
|
Result:=FParams.ParamByName(AParamName);
|
|
|
end;
|
|
@@ -2494,7 +2635,8 @@ end;
|
|
|
|
|
|
{ TCustomSQLQuery }
|
|
|
|
|
|
-Function TCustomSQLQuery.CreateSQLStatement(aOwner : TComponent) : TCustomSQLStatement;
|
|
|
+function TCustomSQLQuery.CreateSQLStatement(aOwner: TComponent
|
|
|
+ ): TCustomSQLStatement;
|
|
|
|
|
|
begin
|
|
|
Result:=TQuerySQLStatement.Create(Self);
|
|
@@ -2551,6 +2693,11 @@ begin
|
|
|
Result:=Params.ParamByName(AParamName);
|
|
|
end;
|
|
|
|
|
|
+function TCustomSQLQuery.MacroByName(const AParamName: String): TParam;
|
|
|
+begin
|
|
|
+ Result:=Macros.ParamByName(AParamName);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLQuery.OnChangeModifySQL(Sender : TObject);
|
|
|
|
|
|
begin
|
|
@@ -2708,10 +2855,13 @@ end;
|
|
|
procedure TCustomSQLQuery.ApplyFilter;
|
|
|
|
|
|
begin
|
|
|
+ FreeFldBuffers;
|
|
|
FStatement.Unprepare;
|
|
|
+ FIsEOF := False;
|
|
|
+ inherited InternalClose;
|
|
|
FStatement.DoPrepare;
|
|
|
FStatement.DoExecute;
|
|
|
- InternalRefresh;
|
|
|
+ inherited InternalOpen;
|
|
|
First;
|
|
|
end;
|
|
|
|
|
@@ -2770,6 +2920,11 @@ begin
|
|
|
SQLConnection.FreeFldBuffers(Cursor);
|
|
|
end;
|
|
|
|
|
|
+function TCustomSQLQuery.GetMacroChar: Char;
|
|
|
+begin
|
|
|
+ Result := FStatement.MacroChar;
|
|
|
+end;
|
|
|
+
|
|
|
function TCustomSQLQuery.GetParamCheck: Boolean;
|
|
|
begin
|
|
|
Result:=FStatement.ParamCheck;
|
|
@@ -2780,6 +2935,16 @@ begin
|
|
|
Result:=FStatement.Params;
|
|
|
end;
|
|
|
|
|
|
+function TCustomSQLQuery.GetMacroCheck: Boolean;
|
|
|
+begin
|
|
|
+ Result:=FStatement.MacroCheck;
|
|
|
+end;
|
|
|
+
|
|
|
+function TCustomSQLQuery.GetMacros: TParams;
|
|
|
+begin
|
|
|
+ Result:=FStatement.Macros;
|
|
|
+end;
|
|
|
+
|
|
|
function TCustomSQLQuery.GetParseSQL: Boolean;
|
|
|
begin
|
|
|
Result:=FStatement.ParseSQL;
|
|
@@ -3068,6 +3233,11 @@ begin
|
|
|
end
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLQuery.SetMacroChar(AValue: Char);
|
|
|
+begin
|
|
|
+ FStatement.MacroChar:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
function TCustomSQLQuery.RefreshLastInsertID(Field: TField): Boolean;
|
|
|
|
|
|
begin
|
|
@@ -3194,6 +3364,11 @@ begin
|
|
|
FStatement.ParamCheck:=AValue;
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLQuery.SetMacroCheck(AValue: Boolean);
|
|
|
+begin
|
|
|
+ FStatement.MacroCheck:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLQuery.SetOptions(AValue: TSQLQueryOptions);
|
|
|
begin
|
|
|
if FOptions=AValue then Exit;
|
|
@@ -3239,6 +3414,11 @@ begin
|
|
|
FStatement.Params.Assign(AValue);
|
|
|
end;
|
|
|
|
|
|
+procedure TCustomSQLQuery.SetMacros(AValue: TParams);
|
|
|
+begin
|
|
|
+ FStatement.Macros.Assign(AValue);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TCustomSQLQuery.SetDataSource(AValue: TDataSource);
|
|
|
|
|
|
Var
|