unit uDASQLiteDriver; {----------------------------------------------------------------------------} { Data Abstract Library - Driver Library { { compiler: Delphi 6 and up, Kylix 3 and up { platform: Win32, Linux { { (c)opyright RemObjects Software. all rights reserved. { { Using this code requires a valid license of the Data Abstract { which can be obtained at http://www.remobjects.com. {----------------------------------------------------------------------------} {$IFDEF MSWINDOWS} {$I ..\DataAbstract.inc} {$ENDIF MSWINDOWS} {$IFDEF LINUX} {$I ../DataAbstract.inc} {$ENDIF LINUX} {$R DataAbstract_SQLiteDriver_Glyphs.res} interface uses Windows, Classes, DB, uDAEngine, uDAInterfaces, uROClasses, uDAUtils, ASGSQLite3, uDASQLiteInterfaces; type { TDASQLiteDriver } TDASQLiteDriver = class(TDADriverReference) end; { TDAESQLiteDriver } TDAESQLiteDriver = class(uDASQLiteInterfaces.TDASQLiteDriver, IDADriver40) protected function GetConnectionClass: TDAEConnectionClass; override; // IDADriver function GetDriverID: string; override; function GetDescription: string; override; procedure GetAuxParams(const AuxDriver: string; out List: IROStrings); override; function GetAvailableDriverOptions: TDAAvailableDriverOptions; override; // IDADriver40 function GetProviderDefaultCustomParameters(Provider: string): string; safecall; public end; // for access to protected methods TDAASQLite3DB = class(TASQLite3DB) private public function GetLastInsertRow: integer; end; { TSQLiteConnection } TSQLiteConnection = class(TDAConnectionWrapper) private fConnection: TDAASQLite3DB; protected function GetConnected: Boolean; override; procedure SetConnected(Value: Boolean); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property Connection: TDAASQLite3DB read fConnection; end; { TDAESQLiteConnection } TDAESQLiteConnection = class(TDASQLiteConnection) private FtransactionFlag: Boolean; fConnection: TSQLiteConnection; protected // TDAEConnection function CreateCustomConnection: TCustomConnection; override; function GetDatasetClass: TDAEDatasetClass; override; procedure DoApplyConnectionString(aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection); override; function DoBeginTransaction: integer; override; procedure DoCommitTransaction; override; procedure DoRollbackTransaction; override; function DoGetInTransaction: boolean; override; function DoGetLastAutoInc(const GeneratorName: string): integer; override; procedure DoGetForeignKeys(out ForeignKeys: TDADriverForeignKeyCollection); override; procedure DoGetTableFields(const aTableName: string; out Fields: TDAFieldCollection); override; function IdentifierNeedsQuoting(const iIdentifier: string): boolean; override; safecall; public constructor Create(aDriver: TDAEDriver; aName: string = ''); override; end; { TDAESQLiteQuery } TDAESQLiteQuery = class(TDAEDataset) private protected function CreateDataset(aConnection: TDAEConnection): TDataset; override; procedure DoPrepare(Value: boolean); override; safecall; function DoExecute: integer; override; function DoGetSQL: string; override; procedure DoSetSQL(const Value: string); override; end; procedure Register; function GetDriverObject: IDADriver; stdcall; implementation uses SysUtils, uDADriverManager, uDARes, Variants, uROBinaryHelpers, uDASQL92Interfaces; var _driver: TDAEDriver = nil; procedure Register; begin RegisterComponents(DAPalettePageName, [TDASQLiteDriver]); end; {$IFDEF DataAbstract_SchemaModelerOnly} {$INCLUDE ..\DataAbstract_SchemaModelerOnly.inc} {$ENDIF DataAbstract_SchemaModelerOnly} function GetDriverObject: IDADriver; begin if (_driver = nil) then _driver := TDAESQLiteDriver.Create(nil); result := _driver; end; { TSQLiteConnection } constructor TSQLiteConnection.Create(AOwner: TComponent); begin inherited; fConnection := TDAASQLite3DB.Create(nil); end; destructor TSQLiteConnection.Destroy; begin inherited; fConnection.Free; end; function TSQLiteConnection.GetConnected: Boolean; begin result := fConnection.Connected; end; procedure TSQLiteConnection.SetConnected(Value: Boolean); begin fConnection.Connected := Value; end; { TDAESQLiteConnection } procedure TDAESQLiteConnection.DoApplyConnectionString( aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection); var sName, sValue: string; i: integer; begin inherited; with aConnStrParser do begin TSQLiteConnection(aConnectionObject).Connection.Database := Database; for i := 0 to (AuxParamsCount - 1) do begin sName := AuxParamNames[i]; sValue := AuxParams[sName]; if AnsiSameText(sName, 'TransactionType') then begin if AnsiSameText(sValue, 'DEFAULT') or AnsiSameText(sValue, 'DEFERRED') or AnsiSameText(sValue, 'IMMEDIATE') or AnsiSameText(sValue, 'EXCLUSIVE') then fConnection.fConnection.TransactionType := AnsiUpperCase(sValue); end else if AnsiSameText(sName, 'DriverDll') then begin fConnection.fConnection.DriverDll := sValue end else if AnsiSameText(sName, 'CharacterEncoding') then begin if AnsiSameText(sValue, 'STANDARD') or AnsiSameText(sValue, 'UTF8') then fConnection.fConnection.CharacterEncoding := AnsiUpperCase(sValue); end; end; end; end; function TDAESQLiteConnection.DoBeginTransaction: integer; begin result := -1; fConnection.Connection.StartTransaction; FtransactionFlag := True; end; procedure TDAESQLiteConnection.DoCommitTransaction; begin fConnection.Connection.Commit; FtransactionFlag := False; end; function TDAESQLiteConnection.CreateCustomConnection: TCustomConnection; begin fConnection := TSQLiteConnection.Create(nil); result := fConnection; end; function TDAESQLiteConnection.GetDatasetClass: TDAEDatasetClass; begin result := TDAESQLiteQuery; end; procedure TDAESQLiteConnection.DoRollbackTransaction; begin FtransactionFlag := False; fConnection.Connection.RollBack; end; function TDAESQLiteConnection.DoGetInTransaction: boolean; begin Result := FtransactionFlag; end; procedure TDAESQLiteConnection.DoGetTableFields(const aTableName: string; out Fields: TDAFieldCollection); var List: TList; i: integer; fld: TDAField; begin inherited DoGetTableFields(QuoteIdentifierIfNeeded(aTableName), Fields); List := TList.Create; try fConnection.Connection.GetTableInfo(aTableName, List); for i := 0 to List.Count - 1 do with TASQLite3Field(List[i]) do begin fld := Fields.FieldByName(FieldName); fld.Required := FieldNN <> 0; fld.InPrimaryKey := FieldPK <> 0; if fld.InPrimaryKey then fld.Required := True; fld.DefaultValue := FieldDefault; end; finally List.Free; end; end; function TDAESQLiteConnection.IdentifierNeedsQuoting( const iIdentifier: string): boolean; begin Result := inherited IdentifierNeedsQuoting(iIdentifier) or SQL92_IdentifierNeedsQuoting(iIdentifier); end; constructor TDAESQLiteConnection.Create(aDriver: TDAEDriver; aName: string); begin inherited; FtransactionFlag := False; end; function TDAESQLiteConnection.DoGetLastAutoInc( const GeneratorName: string): integer; begin Result := fConnection.Connection.GetLastInsertRow; end; procedure TDAESQLiteConnection.DoGetForeignKeys( out ForeignKeys: TDADriverForeignKeyCollection); begin inherited; // SQL Features That SQLite Does Not Implement end; { TDAESQLiteDriver } function TDAESQLiteDriver.GetAvailableDriverOptions: TDAAvailableDriverOptions; begin result := [doDatabaseName, doCustom]; end; function TDAESQLiteDriver.GetConnectionClass: TDAEConnectionClass; begin result := TDAESQLiteConnection; end; function TDAESQLiteDriver.GetDescription: string; begin result := 'SQLite Driver'; end; function TDAESQLiteDriver.GetDriverID: string; begin result := 'SQLite'; end; procedure TDAESQLiteDriver.GetAuxParams(const AuxDriver: string; out List: IROStrings); begin inherited; List.Add('TransactionType=(DEFAULT,DEFERRED,IMMEDIATE,EXCLUSIVE)'); List.Add('DriverDll=SQLite3.dll'); List.Add('CharacterEncoding=(STANDARD,UTF8)'); end; function TDAESQLiteDriver.GetProviderDefaultCustomParameters( Provider: string): string; begin Result := ''; end; { TDAESQLiteQuery } function TDAESQLiteQuery.CreateDataset(aConnection: TDAEConnection): TDataset; begin result := TASQLite3Query.Create(nil); TASQLite3Query(result).Connection := TDAESQLiteConnection(aConnection).fConnection.Connection; end; function TDAESQLiteQuery.DoExecute: integer; begin Result := -1; inherited DoExecute; end; function TDAESQLiteQuery.DoGetSQL: string; begin result := TASQLite3Query(Dataset).SQL.Text; end; procedure TDAESQLiteQuery.DoPrepare(Value: boolean); begin // nothing end; procedure TDAESQLiteQuery.DoSetSQL(const Value: string); begin TASQLite3Query(Dataset).SQL.Text := Value; end; exports GetDriverObject name func_GetDriverObject; { TDAASQLite3DB } function TDAASQLite3DB.GetLastInsertRow: integer; begin result := SQLite3_LastInsertRow(DBHandle) end; initialization _driver := nil; RegisterDriverProc(GetDriverObject); finalization UnregisterDriverProc(GetDriverObject); FreeAndNIL(_driver); end.