//
Unit ads_DBSqlite; {Copyright(c)2016 Advanced Delphi Systems Richard Maley Advanced Delphi Systems 12613 Maidens Bower Drive Potomac, MD 20854 USA phone 301-840-1554 dickmaley@advdelphisys.com The code herein can be used or modified by anyone. Please retain references to Richard Maley at Advanced Delphi Systems. If you make improvements to the code please send your improvements to dickmaley@advdelphisys.com so that the entire Delphi community can benefit. All comments are welcome. } (*UnitIndex Master Index Implementation Section Download Units
Description: ads_DBSqlite.pas This unit contains the following routines.
Register TQuerySqlite.ClientDatasetSaveChanges TQuerySqlite.GetActive TQuerySqlite.GetDatabase TQuerySqlite.GetFilter TQuerySqlite.GetFiltered TQuerySqlite.GetFilterOptions TQuerySqlite.GetMasterSource TQuerySqlite.GetParamCheck TQuerySqlite.GetReadOnly TQuerySqlite.GetSqlDelete TQuerySqlite.GetSqlInsert TQuerySqlite.GetSqlModify TQuerySqlite.GetSqlSelect TQuerySqlite.SetActive TQuerySqlite.SetDatabase TQuerySqlite.SetFilter TQuerySqlite.SetFiltered TQuerySqlite.SetFilterOptions TQuerySqlite.SetMasterSource TQuerySqlite.SetParamCheck TQuerySqlite.SetReadOnly TQuerySqlite.SetSqlDelete TQuerySqlite.SetSqlInsert TQuerySqlite.SetSqlModify TQuerySqlite.SetSqlSelect
*) Interface Uses Classes, DISQLite3DataSet, DISQLite3Database, Provider, DBClient, DB, DBGrids ; Type TSqliteStringArray = Array Of String; TSqliteCreateTableFieldLines = TSqliteStringArray; TQuerySqlite = Class(TDataSource) Private {Private Section} Protected FClientDataSet: TClientDataSet; FDatabase: TDISQLite3Database; FDataSet: TDataSet; FDataSetProvider: TDataSetProvider; FDISQLite3UniDirQuery: TDISQLite3UniDirQuery; Function GetActive: Boolean; Function GetDatabase: TDISQLite3Database; Function GetFilter: String; Function GetFiltered: Boolean; Function GetFilterOptions: TFilterOptions; Function GetMasterSource: TDataSource; Function GetParamCheck: Boolean; Function GetReadOnly: Boolean; Function GetSqlDelete: WideString; Function GetSqlInsert: WideString; Function GetSqlModify: WideString; Function GetSqlSelect: WideString; Procedure ClientDatasetSaveChanges(DataSet: TDataSet); Procedure SetActive(Const Value: Boolean); Procedure SetDatabase(Const Value: TDISQLite3Database); Procedure SetFilter(Const Value: String); Procedure SetFiltered(Const Value: Boolean); Procedure SetFilterOptions(Const Value: TFilterOptions); Procedure SetMasterSource(Const Value: TDataSource); Procedure SetParamCheck(Const Value: Boolean); Procedure SetReadOnly(Const Value: Boolean); Procedure SetSqlDelete(Const Value: WideString); Procedure SetSqlInsert(Const Value: WideString); Procedure SetSqlModify(Const Value: WideString); Procedure SetSqlSelect(Const Value: WideString); Public Constructor Create(AOwner: TComponent); Override; Destructor Destroy; Override; Class Function DBDropTable(DB: TDISQLite3Database; TableName: String): Boolean; Class Function DBEmptyTable(DB: TDISQLite3Database; TableName: String): Boolean; Class Function DBNextInteger(DB: TDISQLite3Database; TableName, FieldName: String): Integer; Class Function GetCreateTableFieldDefLines(DB: TDISQLite3Database; TableName: String): TSqliteCreateTableFieldLines; Class Function GetCreateTableSQL(DB: TDISQLite3Database; TableName: String): String; Class Function GetDatabaseCreateScript(DB: TDISQLite3Database): String; Class Function GetDatabaseCreateScriptArray(DB: TDISQLite3Database): TSqliteStringArray; Class Function GetMaxFieldWidth(Database: TDISQLite3Database; FieldName, TableName: String): Integer; Class Function GetStringFieldSize(Const AColumn: TDISQLite3Column; Const AFieldDef: TFieldDef): Integer; Overload; Class Function GetStringFieldSize(DB: TDISQLite3Database; TableName, FieldName: String): Integer; Overload; Class Function GetTableNames(DB: TDISQLite3Database): TSqliteStringArray; Class Function PosLast(SubString, Source: String): Integer; Class Function PosLastCaseInsensitive(SubString, Source: String): Integer; Class Procedure AdjustColumnWidths(qry: TQuerySqlite; TableName: String; DBGrid: TDBGrid); Class Procedure InitFieldDef(Const AColumn: TDISQLite3Column; Const AFieldDef: TFieldDef); Public Property CDS: TClientDataset Read FClientDataSet Write FClientDataSet; Property Provider: TDataSetProvider Read FDataSetProvider Write FDataSetProvider; Property Query: TDISQLite3UniDirQuery Read FDISQLite3UniDirQuery Write FDISQLite3UniDirQuery; Published Property Active: Boolean Read GetActive Write SetActive; Property Database: TDISQLite3Database Read GetDatabase Write SetDatabase; Property Filter: String Read GetFilter Write SetFilter; Property Filtered: Boolean Read GetFiltered Write SetFiltered; Property FilterOptions: TFilterOptions Read GetFilterOptions Write SetFilterOptions; Property MasterSource: TDataSource Read GetMasterSource Write SetMasterSource; Property ParamCheck: Boolean Read GetParamCheck Write SetParamCheck; Property Read_Only: Boolean Read GetReadOnly Write SetReadOnly; Property SqlDelete: WideString Read GetSqlDelete Write SetSqlDelete; Property SqlInsert: WideString Read GetSqlInsert Write SetSqlInsert; Property SqlModify: WideString Read GetSqlModify Write SetSqlModify; Property SqlSelect: WideString Read GetSqlSelect Write SetSqlSelect; End; Procedure Register; implementation Uses DBConsts, Dialogs, SysUtils; //Unit Description UnitIndex Master Index
Procedure Register; Begin RegisterComponents('ads_Sqlite', [TQuerySqlite]); End; { TCustomQuerySqlite } Constructor TQuerySqlite.Create(AOwner: TComponent); Begin Inherited; FDISQLite3UniDirQuery := TDISQLite3UniDirQuery.Create(self); FDISQLite3UniDirQuery.OnInitFieldDef := InitFieldDef; FDataSetProvider := TDataSetProvider.Create(Self); FDataSetProvider.DataSet := FDISQLite3UniDirQuery; FDataSetProvider.Name := 'DataSetProvider'; FClientDataSet := TClientDataSet.Create(Self); FClientDataSet.Name := 'InternalClientDataSet'; FClientDataSet.ProviderName := FDataSetProvider.Name; FClientDataSet.SetProvider(FDataSetProvider); FClientDataSet.AfterPost := ClientDatasetSaveChanges; FClientDataSet.AfterDelete := ClientDatasetSaveChanges; DataSet := FClientDataSet; End; Destructor TQuerySqlite.Destroy; Begin FreeAndNil(FDISQLite3UniDirQuery); FreeAndNil(FDataSetProvider); FreeAndNil(FClientDataSet); Inherited; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetActive: Boolean; Begin Result := FClientDataSet.Active; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetDatabase: TDISQLite3Database; Begin Result := FDatabase; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetFilter: String; Begin Result := FClientDataSet.Filter; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetFiltered: Boolean; Begin Result := FClientDataSet.Filtered; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetFilterOptions: TFilterOptions; Begin Result := FClientDataSet.FilterOptions; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetMasterSource: TDataSource; Begin Result := FClientDataSet.MasterSource; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetParamCheck: Boolean; Begin Result := FDISQLite3UniDirQuery.ParamCheck; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetReadOnly: Boolean; Begin Result := FClientDataSet.ReadOnly; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetSqlDelete: WideString; Begin Result := FDISQLite3UniDirQuery.DeleteSQL; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetSqlInsert: WideString; Begin Result := FDISQLite3UniDirQuery.InsertSQL; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetSqlModify: WideString; Begin Result := FDISQLite3UniDirQuery.ModifySQL; End; //Unit Description UnitIndex Master Index
Function TQuerySqlite.GetSqlSelect: WideString; Begin Result := FDISQLite3UniDirQuery.SelectSQL; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.ClientDatasetSaveChanges(DataSet: TDataSet); Begin FClientDataSet.ApplyUpdates(0); End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetActive(Const Value: Boolean); Begin FClientDataSet.Active := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetDatabase(Const Value: TDISQLite3Database); Begin FDatabase := Value; FDISQLite3UniDirQuery.Database := FDatabase; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetFilter(Const Value: String); Begin FClientDataSet.Filter := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetFiltered(Const Value: Boolean); Begin FClientDataSet.Filtered := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetFilterOptions(Const Value: TFilterOptions); Begin FClientDataSet.FilterOptions := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetMasterSource(Const Value: TDataSource); Begin FClientDataSet.MasterSource := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetParamCheck(Const Value: Boolean); Begin FDISQLite3UniDirQuery.ParamCheck := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetReadOnly(Const Value: Boolean); Begin FClientDataSet.ReadOnly := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetSqlDelete(Const Value: WideString); Begin FDISQLite3UniDirQuery.DeleteSQL := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetSqlInsert(Const Value: WideString); Begin FDISQLite3UniDirQuery.InsertSQL := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetSqlModify(Const Value: WideString); Begin FDISQLite3UniDirQuery.ModifySQL := Value; End; //Unit Description UnitIndex Master Index
Procedure TQuerySqlite.SetSqlSelect(Const Value: WideString); Begin FDISQLite3UniDirQuery.SelectSQL := Value; End; Class Procedure TQuerySqlite.InitFieldDef(Const AColumn: TDISQLite3Column; Const AFieldDef: TFieldDef); Begin If AFieldDef.DataType In [ftString, ftMemo, ftFmtMemo, ftFixedChar, ftWideString, ftOraClob, ftFixedWideChar, ftWideMemo] Then Begin AFieldDef.Size := GetStringFieldSize(AColumn, AFieldDef); End; End; Class Function TQuerySqlite.PosLast(SubString, Source: String): Integer; Var sgRevSource: String; sgRevSubStr: String; inLenSource: Integer; inLenSubStr: Integer; inCounter: Integer; inPos: Integer; Begin Result := 0; sgRevSource := ''; sgRevSubStr := ''; inLenSource := Length(Source); inLenSubStr := Length(SubString); For inCounter := inLenSource Downto 1 Do sgRevSource := sgRevSource + Copy(Source, inCounter, 1); For inCounter := inLenSubStr Downto 1 Do sgRevSubStr := sgRevSubStr + Copy(SubString, inCounter, 1); inPos := Pos(sgRevSubStr, sgRevSource); If inPos = 0 Then Exit; Result := inLenSource - inPos - inLenSubStr + 2; End; Class Function TQuerySqlite.PosLastCaseInsensitive(SubString, Source: String): Integer; Begin Result := PosLast(UpperCase(SubString), UpperCase(Source)); End; Class Function TQuerySqlite.GetCreateTableSQL(DB: TDISQLite3Database; TableName: String): String; Var ds: TQuerySqlite; sgSQL: String; Begin Result := ''; Try ds := TQuerySqlite.Create(Nil); ds.SqlSelect := 'Select SQL From sqlite_master Where type="table" And Upper("' + TableName + '")=Upper(tbl_name)'; ds.Database := DB; ds.Active := True; sgSQL := ''; If ds.FClientDataSet.Bof And ds.FClientDataSet.Eof Then Exit; sgSQL := ds.FClientDataSet.FieldByName('sql').AsString; sgSQL := StringReplace(sgSQL, #13 + #10, ' ', [rfReplaceAll]); Result := sgSQL; Finally FreeAndNil(ds); End; End; Class Function TQuerySqlite.GetCreateTableFieldDefLines(DB: TDISQLite3Database; TableName: String): TSqliteCreateTableFieldLines; Var inPos: Integer; sgSQL: String; sgTemp: String; Begin SetLength(Result, 0); Try sgSQL := GetCreateTableSQL(DB, TableName); If Trim(sgSQL) = '' Then Exit; inPos := Pos('(', sgSQL); If inPos = 0 Then Exit; sgTemp := Copy(sgSQL, inPos + 1, Length(sgSQL) - (inPos + 1) + 1); inPos := PosLast(')', sgTemp); If inPos = 0 Then Exit; sgTemp := Copy(sgTemp, 1, inPos - 1); sgTemp := Trim(sgTemp); While True Do Begin inPos := Pos(',', sgTemp); If inPos = 0 Then Begin SetLength(Result, Length(Result) + 1); Result[High(Result)] := sgTemp; Break; End Else Begin SetLength(Result, Length(Result) + 1); Result[High(Result)] := Copy(sgTemp, 1, inPos - 1); sgTemp := Copy(sgTemp, inPos + 1, Length(sgTemp) - (inPos + 1) + 1); End; End; Except End; End; Class Function TQuerySqlite.GetStringFieldSize(DB: TDISQLite3Database; TableName, FieldName: String): Integer; Var boFound: Boolean; FieldLine: String; Fields: TSqliteCreateTableFieldLines; i: Integer; inPos: Integer; inPosSpace: Integer; sgAfterName: String; sgAfterType: String; sgFieldType: String; sgFieldTypePrefix: String; sgFieldTypeSize: String; sgStringTypes: String; sgTemp: String; Begin Result := -1; sgStringTypes := '|CHAR|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|'; Fields := GetCreateTableFieldDefLines(DB, TableName); boFound := False; FieldLine := ''; inPosSpace := -1; For i := 0 To High(Fields) Do Begin Fields[i] := Trim(Fields[i]); inPos := Pos(UpperCase(FieldName), UpperCase(Fields[i])); If inPos = 0 Then Continue; inPosSpace := Pos(' ', Fields[i]); If inPosSpace = 0 Then Continue; sgTemp := Copy(Fields[i], 1, inPosSpace - 1); inPos := Pos(UpperCase(FieldName), UpperCase(sgTemp)); If inPos = 0 Then Continue; FieldLine := UpperCase(Fields[i]); boFound := True; End; If Not boFound Then Exit; sgAfterName := Trim(Copy(FieldLine, inPosSpace + 1, Length(FieldLine) - (inPosSpace + 1) + 1)); sgAfterType := ''; inPosSpace := Pos(' ', sgAfterName); If inPosSpace = 0 Then Begin sgFieldType := sgAfterName; sgAfterType := ''; End Else Begin sgFieldType := Copy(sgAfterName, 1, inPosSpace - 1); sgAfterType := Copy(sgAfterName, inPosSpace + 1, Length(sgAfterName) - (inPosSpace + 1) + 1); End; inPos := Pos('(', sgFieldType); If inPos = 0 Then Begin sgFieldTypePrefix := sgFieldType; sgFieldTypeSize := ''; End Else Begin sgFieldTypePrefix := Copy(sgFieldType, 1, inPos - 1); sgFieldTypeSize := Copy(sgFieldType, inPos + 1, Length(sgFieldType) - (inPos + 1) + 1); sgFieldTypeSize := StringReplace(sgFieldTypeSize, ')', '', [rfReplaceAll]); End; inPos := Pos('|' + sgFieldTypePrefix + '|', sgStringTypes); If inPos <> 0 Then Begin If sgFieldTypeSize = '' Then Begin If sgFieldTypePrefix = 'CLOB' Then Begin Result := 10000; End Else Begin Result := 2000; End; End Else Begin Try Result := StrToInt(sgFieldTypeSize); Except Result := 2000; End; End; End; End; Class Function TQuerySqlite.GetStringFieldSize(Const AColumn: TDISQLite3Column; Const AFieldDef: TFieldDef): Integer; Var inPos: Integer; sgFieldType: String; sgFieldTypePrefix: String; sgFieldTypeSize: String; sgStringTypes: String; Begin Result := -1; sgStringTypes := '|CHAR|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|'; sgFieldType := UpperCase(Acolumn.ColumnDeclaration); inPos := Pos('(', sgFieldType); If inPos = 0 Then Begin sgFieldTypePrefix := sgFieldType; sgFieldTypeSize := ''; End Else Begin sgFieldTypePrefix := Copy(sgFieldType, 1, inPos - 1); sgFieldTypeSize := Copy(sgFieldType, inPos + 1, Length(sgFieldType) - (inPos + 1) + 1); sgFieldTypeSize := StringReplace(sgFieldTypeSize, ')', '', [rfReplaceAll]); End; inPos := Pos('|' + sgFieldTypePrefix + '|', sgStringTypes); If inPos <> 0 Then Begin If sgFieldTypeSize = '' Then Begin If sgFieldTypePrefix = 'CLOB' Then Begin Result := 10000; End Else Begin Result := 2000; End; End Else Begin Try Result := StrToInt(sgFieldTypeSize); Except Result := 2000; End; End; End; End; Class Function TQuerySqlite.GetMaxFieldWidth(Database: TDISQLite3Database; FieldName, TableName: String): Integer; Var qry: TQuerySqlite; Begin Result := -1; qry := TQuerySqlite.Create(Nil); Try qry.SqlSelect := 'Select length(' + FieldName + ') As MaxLen from ' + TableName + ' where length(' + FieldName + ')=(select max(length(' + FieldName + '))' + ' from ' + TableName + ')'; qry.Database := Database; qry.Active := True; If qry.DataSet.bof And qry.DataSet.eof Then Exit; qry.DataSet.First(); Result := qry.DataSet.FieldByName('MaxLen').AsInteger; Finally FreeAndNil(qry); End; End; Class Procedure TQuerySqlite.AdjustColumnWidths(qry: TQuerySqlite; TableName: String; DBGrid: TDBGrid); Var i: Integer; Begin If Not qry.Active Then Exit; If qry.DataSet.Bof And qry.DataSet.EOF Then Exit; For i := 0 To qry.DataSet.FieldCount - 1 Do Begin qry.DataSet.Fields[i].DisplayWidth := TQuerySqlite.GetMaxFieldWidth(qry.Database, qry.DataSet.Fields[i].FieldName, TableName); DBGrid.Columns.RestoreDefaults; End; End; Class Function TQuerySqlite.GetTableNames( DB: TDISQLite3Database): TSqliteStringArray; Var qry: TQuerySqlite; Begin SetLength(Result, 0); qry := TQuerySqlite.Create(Nil); Try qry.SqlSelect := 'Select tbl_name As TableName From sqlite_master where type="table" Order By tbl_name'; qry.Database := DB; qry.Active := True; If qry.DataSet.bof And qry.DataSet.eof Then Exit; qry.DataSet.First(); While Not qry.DataSet.eof Do Begin SetLength(Result, Length(Result) + 1); Result[High(Result)] := qry.DataSet.FieldByName('TableName').AsString; qry.DataSet.Next(); End; Finally FreeAndNil(qry); End; End; Class Function TQuerySqlite.GetDatabaseCreateScript( DB: TDISQLite3Database): String; Var i: Integer; a: TSqliteStringArray; Begin Result := ''; a := GetDatabaseCreateScriptArray(DB); For i := 0 To High(a) Do Begin Result := Result + a[i] + ';' + #13 + #10 + #13 + #10; End; End; Class Function TQuerySqlite.GetDatabaseCreateScriptArray( DB: TDISQLite3Database): TSqliteStringArray; Var a: TSqliteStringArray; i: Integer; s: String; Begin a := TQuerySqlite.GetTableNames(DB); SetLength(Result, 0); For i := 0 To High(a) Do Begin SetLength(Result, Length(Result) + 1); s := GetCreateTableSQL(DB, a[i]); Result[High(Result)] := s; End; End; Class Function TQuerySqlite.DBNextInteger(DB: TDISQLite3Database; TableName, FieldName: String): Integer; Var qry: TQuerySqlite; Begin Result := 0; qry := TQuerySqlite.Create(Nil); Try If Trim(TableName) = '' Then Exit; If Trim(FieldName) = '' Then Exit; Try qry.SqlSelect := 'Select Max(' + FieldName + ') As MaxValue From ' + TableName; qry.Database := DB; qry.Active := True; If qry.DataSet.bof And qry.DataSet.eof Then Exit; qry.DataSet.First(); Result := qry.DataSet.FieldByName('MaxValue').AsInteger + 1; Except End; Finally FreeAndNil(qry); End; End; Class Function TQuerySqlite.DBDropTable(DB: TDISQLite3Database; TableName: String): Boolean; Begin Result := False; If Trim(TableName) = '' Then Exit; Try DB.Execute('Drop Table ' + TableName); DB.Commit; Result := True; Except End; End; Class Function TQuerySqlite.DBEmptyTable(DB: TDISQLite3Database; TableName: String): Boolean; Var sql: String; Begin Result := False; If Trim(TableName) = '' Then Exit; Try sql := GetCreateTableSQL(DB, TableName); DB.Execute('Drop Table ' + TableName); DB.Commit; DB.Execute(sql); DB.Commit; Result := True; Except End; End; End. //