1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309 |
- {$mode objfpc}
- {$h+}
- unit SQLiteDataset;
- {
- Improved class sqLite,copyright(c) 2002-2003 Marcin Krzetowski
- [email protected]
- http://www.a-i.prv.pl
- simple class interface for SQLite. Hacked in by Ben Hochstrasser ([email protected])
- Thanks to Roger Reghin ([email protected]) for his idea to ValueList.
- }
- interface
- uses
- Classes,db,sysutils,Contnrs;
- type
- PRecInfo = ^TRecInfo;
- TRecInfo = record
- Index: Integer;
- Bookmark: Longint;
- BookmarkFlag: TBookmarkFlag;
- end;
- type
- pBinBookMark = ^tBinBookMark;
- tBinBookmark = record
- RecPtr : Int64;
- end;
- type
- TSQLiteExecCallback = function(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer of object; cdecl;
- TSQLiteBusyCallback = function(Sender: TObject; ObjectName: PChar; BusyCount: integer): integer of object; cdecl;
- TOnData = Procedure(Sender: TObject; Columns: Integer; ColumnNames, ColumnValues: String) of object;
- TOnBusy = Procedure(Sender: TObject; ObjectName: String; BusyCount: integer; var Cancel: Boolean) of object;
- TOnQueryComplete = Procedure(Sender: TObject) of object;
- Type
- tSqliteField = class(tObject)
- protected
- FOwner : tObject;
- data : string;
- fFieldKind: tFieldKind;
- fFieldType: tFieldType;
- { tIntegerType : Integer;
- tLongIntegerType : int64;
- tDateTimeType : tDateTime;}
- // procedure SetName(const Value: string);
- procedure SetFieldKind(const Value: tFieldKind);
- procedure SetFieldType(const Value: tFieldType);
- public
- constructor create(aOwner : tObject);
- destructor destroy; override;
- procedure SetData(pt : pChar; NativeFormat : boolean);
- function GetData(Buffer: Pointer; NativeFormat : Boolean) : boolean;
- function GetData(Buffer: Pointer{=True}) : boolean;
- // property FieldName : string read fName write SetName;
- property FieldKind : tFieldKind read fFieldKind write SetFieldKind;
- property FieldType : tFieldType read fFieldType write SetFieldType;
- end;
- tSqliteRows = class (tObject)
- private
- function getItem(index: integer): tSqliteField;
- procedure SetItem(index: integer; const Value: tSqliteField);
- function checkIndex(index : integer) : boolean;
- public
- BookmarkFlag : tBookmarkFlag;
- Bookmark : LongInt;
- DataPointer : Pointer;
- constructor Create(fieldCount : integer);
- destructor destroy; override;
- procedure Push(item : tSqliteField);
- function Pop : tSqliteField;
- property Items[index : integer] : tSqliteField read getItem write SetItem;
- procedure Clear;
- procedure ClearCalcFields;
- function add(pt : Pchar; ptName : pCHar) : boolean;
- protected
- fbuffercount : integer;
- fBuffer : ^tSqliteField;
- internalCount : integer;
- procedure clearBuffer;
- end;
- TSQLite = class(TDataSet)
- private
- maxLengthInit : boolean;
- maxiL : pinteger;
- maxilcount : integer;
- fDoExceptions : boolean;
- fDoSQL : boolean;
- fIsCancel: boolean;
- fSQLite: Pointer;
- fMsg: String;
- fIsOpen: Boolean;
- fBusy: Boolean;
- fError: Integer;
- fVersion: String;
- fEncoding: String;
- fTable: tStrings;
- fLstName: TStringList;
- fLstVal: TStringList;
- // fbuffer : tObjectList;
- fOnData: TOnData;
- fOnBusy: TOnBusy;
- fOnQueryComplete: TOnQueryComplete;
- fBusyTimeout: integer;
- fPMsg: PChar;
- fChangeCount: integer;
- fSQL: tStringlist;
- fonwer : tComponent;
- fDataBaseName : string;
- fDataBase: string;
- fTableName: string;
- factive : boolean;
- procedure SetBusyTimeout(Timeout: integer);
- procedure SetDataBase(DBFileName: String);
- procedure setTableName(const Value: string);
- function getIsCancel: boolean;
- procedure clearBuffer;
- protected
- fCalcFieldsOfs,fRecordSize : integer;
- fBookMarkOfs,fRecordBufferSize : integer;
- fCurrentRecord : int64;
- fRecordCount : int64;
- fCursorOpen : boolean;
- fFieldOffset : tList;
- // procedure internalInsert; override;
- function getActive: boolean;
- // procedure setActive(Value: boolean); override;
- function getRecNo : integer; override;
- function getBookmarkFlag(Buffer : pChar) : tBookMarkFlag; override;
- procedure InitBufferPointers;
- procedure GetBookmarkData(Buffer : pChar; Data : Pointer); override;
- procedure SetBookMarkData(Buffer : pChar; Data : Pointer); override;
- procedure InternalGotoBookmark(ABookMark : Pointer) ; override;
- function FieldDefsStored : boolean;
- procedure ClearCalcFields(Buffer : pChar); override;
- procedure OpenCursor(InfoQuery : Boolean); override;
- function getRecordCount : integer; override;
- procedure SetRecNo (value : integer); override;
- function getRecord(Buffer : pChar; GetMode : tGetMode; DoCheck : Boolean): tGetResult; override;
- procedure InternalInitFieldDefs; override;
- procedure InternalOpen; override;
- procedure InternalClose; override;
- procedure InternalAddRecord(Buffer : Pointer; DoAppend : boolean); override;
- procedure InternalDelete; override;
- procedure InternalFirst; override;
- procedure InternalHandleException; override;
- procedure InternalInitRecord(Buffer : pChar); override;
- procedure InternalLast;override;
- procedure InternalPost;override;
- procedure InternalSetToRecord (Buffer : pChar); override;
- function isCursorOpen : Boolean; override;
- procedure SetBookmarkFlag(Buffer : pChar; value : tBookmarkFlag); override;
- procedure SetFieldData(Field : tField; Buffer : Pointer); override;
- function allocRecordBuffer : pChar; override;
- procedure FreeRecordBuffer(var Buffer : pChar); override;
- function getRecordSize : Word; override;
- function getCanModify : boolean; override;
- public
- fbuffer : tObjectList; //po zakonczeniu debuggowania usunac
- constructor create(Aowner : tComponent); override;
- destructor Destroy; override;
- function getFieldData(Field : tField; Buffer : Pointer) : boolean; override;
- function Query(ASql: String{table= nil}) : Boolean;
- Function Query(ASQL: String; Table: TStrings): boolean;
- function ExecSQL : boolean;
- function ErrorMessage(ErrNo: Integer): string;
- function IsComplete(ASql: String): boolean;
- function LastInsertRow: integer;
- procedure Cancel; override;
- function DatabaseDetails(Table: TStrings): boolean;
- function CreateTable : boolean;
- procedure countMaxiLength(pt: pChar;index : int64);
- procedure InitMaxLength(length : integer);
- published
- property LastErrorMessage: string read fMsg;
- property LastError: Integer read fError;
- property Version: String read fVersion;
- property Encoding: String read fEncoding;
- property OnData: TOnData read fOnData write fOnData;
- property OnBusy: TOnBusy read fOnBusy write fOnBusy;
- property OnQueryComplete: TOnQueryComplete read fOnQueryComplete write fOnQueryComplete;
- property BusyTimeout: Integer read fBusyTimeout write SetBusyTimeout;
- property ChangeCount: Integer read fChangeCount;
- property SQL : tStringlist read fSQL write fSQL;
- // property Fields : tstringlist read fFields;
- property DataBase : string read fDataBase write SetDataBase;
- property TableName : string read fTableName write setTableName;
- property Active : boolean read getActive write setActive;
- property isCancel : boolean read getIsCancel;
- property DoExceptions : boolean read fDoExceptions write fDoExceptions stored true default true;
- end;
- function Pas2SQLStr(const PasString: string): string;
- function SQL2PasStr(const SQLString: string): string;
- function QuoteStr(const s: string; QuoteChar: Char): string;
- function UnQuoteStr(const s: string; QuoteChar: Char): string;
- function QuoteStr(const s: string{; QuoteChar: Char = #39}): string;
- function UnQuoteStr(const s: string{; QuoteChar: Char = #39}): string;
- procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);
- procedure Register;
-
- implementation
- {$ifndef dynload}
- uses sqlite;
- {$else}
- uses dynlibs;
- function GetProcAddress(S : String) : Pointer;
- begin
- end;
- {$endif}
- const
- SQLITE_OK = 0; // Successful result
- SQLITE_ERROR = 1; // SQL error or missing database
- SQLITE_INTERNAL = 2; // An internal logic error in SQLite
- SQLITE_PERM = 3; // Access permission denied
- SQLITE_ABORT = 4; // Callback routine requested an abort
- SQLITE_BUSY = 5; // The database file is locked
- SQLITE_LOCKED = 6; // A table in the database is locked
- SQLITE_NOMEM = 7; // A malloc() failed
- SQLITE_READONLY = 8; // Attempt to write a readonly database
- SQLITE_INTERRUPT = 9; // Operation terminated by sqlite_interrupt()
- SQLITE_IOERR = 10; // Some kind of disk I/O error occurred
- SQLITE_CORRUPT = 11; // The database disk image is malformed
- SQLITE_NOTFOUND = 12; // (Internal Only) Table or record not found
- SQLITE_FULL = 13; // Insertion failed because database is full
- SQLITE_CANTOPEN = 14; // Unable to open the database file
- SQLITE_PROTOCOL = 15; // Database lock protocol error
- SQLITE_EMPTY = 16; // (Internal Only) Database table is empty
- SQLITE_SCHEMA = 17; // The database schema changed
- SQLITE_TOOBIG = 18; // Too much data for one row of a table
- SQLITE_CONSTRAINT = 19; // Abort due to contraint violation
- SQLITE_MISMATCH = 20; // Data type mismatch
- SQLITEDLL: PChar = 'sqlite.dll';
- DblQuote: Char = '"';
- SngQuote: Char = #39;
- Crlf: String = #13#10;
- Tab: Char = #9;
- _DO_EXCEPTIONS = 1; //Handle or not exceptions in dataset
- {$ifdef dynload}
- var
- SQLite_Open: function(dbname: PChar; mode: Integer; var ErrMsg: PChar): Pointer; cdecl;
- SQLite_Close: procedure(db: Pointer); cdecl;
- SQLite_Exec: function(db: Pointer; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl;
- SQLite_Version: function(): PChar; cdecl;
- SQLite_Encoding: function(): PChar; cdecl;
- SQLite_ErrorString: function(ErrNo: Integer): PChar; cdecl;
- SQLite_GetTable: function(db: Pointer; SQLStatement: PChar; var ResultPtr: Pointer; var RowCount: Cardinal; var ColCount: Cardinal; var ErrMsg: PChar): integer; cdecl;
- SQLite_FreeTable: procedure(Table: PChar); cdecl;
- SQLite_FreeMem: procedure(P: PChar); cdecl;
- SQLite_Complete: function(P: PChar): boolean; cdecl;
- SQLite_LastInsertRow: function(db: Pointer): integer; cdecl;
- SQLite_Cancel: procedure(db: Pointer); cdecl;
- SQLite_BusyHandler: procedure(db: Pointer; CallbackPtr: Pointer; Sender: TObject); cdecl;
- SQLite_BusyTimeout: procedure(db: Pointer; TimeOut: integer); cdecl;
- SQLite_Changes: function(db: Pointer): integer; cdecl;
- LibsLoaded: Boolean;
- DLLHandle: THandle;
- {$endif}
- Var
- MsgNoError: String;
- function QuoteStr(const s: string): string;
- begin
- Result := QuoteStr(S,#39);
- end;
- function QuoteStr(const s: string; QuoteChar: Char): string;
- begin
- Result := Concat(QuoteChar, s, QuoteChar);
- end;
- function UnQuoteStr(const s: string): string;
- begin
- Result := UnQuoteStr(s,#39);
- end;
- function UnQuoteStr(const s: string; QuoteChar: Char): string;
- begin
- Result := s;
- if length(Result) > 1 then
- begin
- if Result[1] = QuoteChar then
- Delete(Result, 1, 1);
- if Result[Length(Result)] = QuoteChar then
- Delete(Result, Length(Result), 1);
- end;
- end;
- function Pas2SQLStr(const PasString: string): string;
- var
- n: integer;
- begin
- Result := SQL2PasStr(PasString);
- n := Length(Result);
- while n > 0 do
- begin
- if Result[n] = SngQuote then
- Insert(SngQuote, Result, n);
- dec(n);
- end;
- Result := QuoteStr(Result);
- end;
- function SQL2PasStr(const SQLString: string): string;
- const
- DblSngQuote: String = #39#39;
- var
- p: integer;
- begin
- Result := SQLString;
- p := pos(DblSngQuote, Result);
- while p > 0 do
- begin
- Delete(Result, p, 1);
- p := pos(DblSngQuote, Result);
- end;
- Result := UnQuoteStr(Result);
- end;
- procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);
- var
- n: integer;
- lstName, lstValue: TStringList;
- begin
- if NameValuePairs <> nil then
- begin
- lstName := TStringList.Create;
- lstValue := TStringList.Create;
- lstName.CommaText := ColumnNames;
- lstValue.CommaText := ColumnValues;
- NameValuePairs.Clear;
- if lstName.Count = LstValue.Count then
- if lstName.Count > 0 then
- for n := 0 to lstName.Count - 1 do
- NameValuePairs.Append(Concat(lstName.Strings[n], '=', lstValue.Strings[n]));
- lstValue.Free;
- lstName.Free;
- end;
- end;
- {$ifdef dynload}
- function LoadLibs: Boolean;
- begin
- Result := False;
- DLLHandle := LoadLibrary(SQLITEDLL);
- if DLLHandle <> 0 then
- begin
- @SQLite_Open := GetProcAddress(DLLHandle, 'sqlite_open');
- if not Assigned(@SQLite_Open) then exit;
- @SQLite_Close := GetProcAddress(DLLHandle, 'sqlite_close');
- if not Assigned(@SQLite_Close) then exit;
- @SQLite_Exec := GetProcAddress(DLLHandle, 'sqlite_exec');
- if not Assigned(@SQLite_Exec) then exit;
- @SQLite_Version := GetProcAddress(DLLHandle, 'sqlite_libversion');
- if not Assigned(@SQLite_Version) then exit;
- @SQLite_Encoding := GetProcAddress(DLLHandle, 'sqlite_libencoding');
- if not Assigned(@SQLite_Encoding) then exit;
- @SQLite_ErrorString := GetProcAddress(DLLHandle, 'sqlite_error_string');
- if not Assigned(@SQLite_ErrorString) then exit;
- @SQLite_GetTable := GetProcAddress(DLLHandle, 'sqlite_get_table');
- if not Assigned(@SQLite_GetTable) then exit;
- @SQLite_FreeTable := GetProcAddress(DLLHandle, 'sqlite_free_table');
- if not Assigned(@SQLite_FreeTable) then exit;
- @SQLite_FreeMem := GetProcAddress(DLLHandle, 'sqlite_freemem');
- if not Assigned(@SQLite_FreeMem) then exit;
- @SQLite_Complete := GetProcAddress(DLLHandle, 'sqlite_complete');
- if not Assigned(@SQLite_Complete) then exit;
- @SQLite_LastInsertRow := GetProcAddress(DLLHandle, 'sqlite_last_insert_rowid');
- if not Assigned(@SQLite_LastInsertRow) then exit;
- @SQLite_Cancel := GetProcAddress(DLLHandle, 'sqlite_interrupt');
- if not Assigned(@SQLite_Cancel) then exit;
- @SQLite_BusyTimeout := GetProcAddress(DLLHandle, 'sqlite_busy_timeout');
- if not Assigned(@SQLite_BusyTimeout) then exit;
- @SQLite_BusyHandler := GetProcAddress(DLLHandle, 'sqlite_busy_handler');
- if not Assigned(@SQLite_BusyHandler) then exit;
- @SQLite_Changes := GetProcAddress(DLLHandle, 'sqlite_changes');
- if not Assigned(@SQLite_Changes) then exit;
- Result := True;
- end;
- end;
- {$endif}
- function SystemErrorMsg(ErrNo: Integer): String;
- var
- buf: PChar;
- size: Integer;
- MsgLen: Integer;
- begin
- msglen:=0;
- size := 256;
- GetMem(buf, size);
- {
- If ErrNo = - 1 then
- ErrNo := GetLastError;
- MsgLen := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, ErrNo, 0, buf, size, nil);
- }
- if MsgLen = 0 then
- Result := 'ERROR'
- else
- Result := buf;
- end;
- function SystemErrorMsg: String;
- begin
- SystemErrorMsg(-1);
- end;
- function BusyCallback(Sender: Pointer; ObjectName: PChar; BusyCount: integer): integer; cdecl;
- var
- sObjName: String;
- bCancel: Boolean;
- begin
- Result := -1;
- with TSQLite(Sender) do
- begin
- if Assigned(fOnBusy) then
- begin
- bCancel := False;
- sObjName := ObjectName;
- fOnBusy(Tsqlite(Sender), sObjName, BusyCount, bCancel);
- if bCancel then
- Result := 0;
- end;
- end;
- end;
- function ExecCallback(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer; cdecl;
- var
- PVal, PName: ^PChar;
- n: integer;
- sVal, sName: String;
- begin
- Result := 0;
- with Sender as TSQLite do
- begin
- if (Assigned(fOnData) or Assigned(fTable)) then
- begin
- fLstName.Clear;
- fLstVal.Clear;
- if Columns > 0 then
- begin
- PName := ColumnNames;
- PVal := ColumnValues;
- for n := 0 to Columns - 1 do
- begin
- fLstName.Append(PName^);
- fLstVal.Append(PVal^);
- if Assigned(fTable) then
- begin
- fTable.Append(PVal^);
- end;
- inc(PName);
- inc(PVal);
- end;
- end;
- sVal := fLstVal.CommaText;
- sName := fLstName.CommaText;
- if Assigned(fOnData) then
- fOnData(Sender, Columns, sName, sVal);
- end;
- // InternalOpen;
- end;
- end;
- function ExecCallback2(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer; cdecl;
- var
- PVal, PName: ^PChar;
- n: integer;
- sVal, sName: String;
- t : tSqliteRows;
- p : pointer;
- temp : LongInt;
- begin
- Result := 0;
- with Sender as TSQLite do begin
- if (Assigned(fOnData) or assigned(fBuffer)) then begin
- fLstName.Clear;
- // fLstVal.Clear;
- if Columns > 0 then begin
- PName := ColumnNames;
- PVal := ColumnValues;
- fBuffer.Add(tSqliteRows.Create(Columns));
- temp:=fBuffer.count-1;
- initMaxLength(columns);
- for n := 0 to Columns - 1 do begin
- fLstName.Append(PName^);
- if Assigned(fBuffer) then begin
- p:=fBuffer.Items[temp];
- t:=tSqliteRows(p);
- if t=nil then continue;
- t.Add(PVAL^,PNAME^);
- end;
- countMaxiLength(PVAL^,n);
- inc(PName);
- inc(PVal);
- end;
- // at last we add the bookmark info
- t.Bookmark:=temp;
- end;
- if Assigned(fOnData) then begin
- sVal := fLstVal.CommaText;
- sName := fLstName.CommaText;
- fOnData(Sender, Columns, sName, sVal);
- end;
- end;
- // InternalOpen;
- end;
- end;
- procedure TSQLite.SetDataBase(DBFileName: String);
- var
- afPMsg: PChar;
- begin
- fError := SQLITE_ERROR;
- fIsOpen := False;
- fOnData := nil;
- fOnBusy := nil;
- fOnQueryComplete := nil;
- fChangeCount := 0;
- {$ifdef dynload}
- if LibsLoaded then
- begin
- {$endif}
- fSQLite := SQLite_Open(PChar(DBFileName), 1, @afPMsg);
- SQLite_FreeMem(afPMsg);
- if fSQLite <> nil then
- begin
- {$ifndef fpc}
- fVersion := strpas(SQLite_Version);
- fEncoding := strpas(SQLite_Encoding);
- {$endif}
- fIsOpen := True;
- fError := SQLITE_OK;
- end;
- {$ifdef dynload}
- end;
- {$endif}
- fMsg := ErrorMessage(fError);
- end;
- destructor TSQLite.Destroy;
- begin
- try
- if assigned(fSQl) then begin
- fsql.free;
- fsql:=nil;
- end;
- if fIsOpen then
- SQLite_Close(fSQLite);
- fIsOpen := False;
- if assigned(fLstName) then begin
- fLstName.Free;
- fLstName:=nil;
- end;
- if assigned(fLstVal) then begin
- fLstVal.Free;
- fLstVal:=nil;
- end;
- fSQLite := nil;
- fOnData := nil;
- fOnBusy := nil;
- fOnQueryComplete := nil;
- fLstName := nil;
- fLstVal := nil;
- if assigned(fBuffer) then begin
- clearBuffer;
- fBuffer.Free;
- fBuffer:=nil;
- end;
- except
- end;
- inherited Destroy;
- end;
- function TSQLite.Query(ASql: String): boolean;
- begin
- Result:=Query(ASql,Nil);
- end;
- function TSQLite.Query(ASql: String; Table: TStrings): boolean;
- //var
- // fPMsg: PChar;
- begin
- maxLengthInit:=false;
- fError := SQLITE_ERROR;
- if fIsOpen then
- begin
- fPMsg := nil;
- fBusy := True;
- fTable := Table;
- if fTable <> nil then
- fTable.Clear;
- fError := SQLite_Exec(fSQLite, PChar(ASql), @ExecCallback, Self, @fPMsg);
- SQLite_FreeMem(fPMsg);
- fChangeCount := SQLite_Changes(fSQLite);
- fTable := nil;
- fBusy := False;
- if Assigned(fOnQueryComplete) then
- fOnQueryComplete(Self);
- end;
- fMsg := ErrorMessage(fError);
- Result := not (fError <> SQLITE_OK);//function should return true, if execution of query ends ok..
- if result and not active then
- factive:=true;
- fDoSql:=true;
- end;
- procedure TSQLite.SetBusyTimeout(Timeout: Integer);
- begin
- fBusyTimeout := Timeout;
- if fIsOpen then
- begin
- SQLite_Busy_Timeout(fSQLite, fBusyTimeout);
- if fBusyTimeout > 0 then
- SQLite_Busy_Handler(fSQLite, @BusyCallback, Self)
- else
- SQLite_Busy_Handler(fSQLite, nil, nil);
- end;
- end;
- function TSQLite.LastInsertRow: integer;
- begin
- if fIsOpen then
- Result := SQLite_Last_Insert_Rowid(fSQLite)
- else
- Result := -1;
- end;
- function TSQLite.ErrorMessage(ErrNo: Integer): string;
- begin
- {$ifdef dynload}
- if LibsLoaded then
- begin
- {$endif}
- if ErrNo = 0 then
- Result := MsgNoError
- else
- Result := SQLite_Error_String(ErrNo);
- {$ifdef dynload}
- end else
- Raise exception.Create('Library "sqlite.dll" not found.');
- {$endif}
- end;
- function TSQLite.IsComplete(ASql: String): boolean;
- begin
- Result := SQLite_Complete(PChar(ASql))=0;
- end;
- function TSQLite.DatabaseDetails(Table: TStrings): boolean;
- begin
- Result := Query('SELECT * FROM SQLITE_MASTER;', Table);
- end;
- function TSQLite.ExecSQL: boolean;
- var i : integer;
- begin
- result:=false;
- maxLengthInit:=false;
- fError := SQLITE_ERROR;
- if fIsOpen then
- begin
- fPMsg := nil;
- fBusy := True;
- if fTable <> nil then
- fTable.Clear;
- for i:=0 to fsql.Count-1 do begin
- fError := SQLite_Exec(fSQLite, PChar(fSql[i]), @ExecCallback2, Self, @fPMsg);
- SQLite_FreeMem(fPMsg);
- end;
- fChangeCount := SQLite_Changes(fSQLite);
- fTable := nil;
- fBusy := False;
- if Assigned(fOnQueryComplete) then
- fOnQueryComplete(Self);
- end;
- fMsg := ErrorMessage(fError);
- Result :=not (fError <> SQLITE_OK);
- if result and not active then
- factive:=true;
- fDoSQl:=true;
- end;
- constructor TSQLite.Create(Aowner: tComponent);
- begin
- inherited create(Aowner);
- fLstName := TStringList.Create;
- fLstVal := TStringList.Create;
- fDoSql:=false;
- fsql:=tStringList.Create;
- fOnwer:=owner;
- fBuffer:=tObjectList.Create(true);
- if length(fDataBase)>1 then
- setDataBase(fDataBase);
- end;
- procedure TSQLite.setTableName(const Value: string);
- begin
- if (not active) and (length(value)>0) then begin
- fTableName := Value;
- sql.Clear;
- sql.add('select rowid,* from '+tableName+';');
- end;
- end;
- function TSQLite.getActive: boolean;
- begin
- result:=fActive;
- end;
- {
- procedure TSQLite.setActive(Value: boolean);
- begin
- if value then
- begin
- //switch for active=true;
- if active then
- active:=false;
- end
- else
- begin
- fDoSQL:=value;
- end;
- inherited setActive(value);
- end;
- }
- function TSQLite.getRecNo: integer;
- begin
- result:=self.fCurrentRecord;
- end;
- procedure TSQLite.Cancel;
- begin
- inherited;
- fIsCancel := False;
- if fBusy and fIsOpen then
- begin
- do_SQLite_interrupt(fSQLite);
- fBusy := false;
- fIsCancel := True;
- end;
- end;
- function TSQLite.getIsCancel: boolean;
- begin
- end;
- function TSQLite.getBookmarkFlag(Buffer: pChar): tBookMarkFlag;
- begin
- result:= pRecInfo(Buffer)^.BookmarkFlag;
- end;
- procedure TSQLite.InitBufferPointers;
- begin
- fCalcFieldsOfs :=fRecordSize;
- //fRecInfoOfs :=fCalcFieldsOfs + CalcFieldsSize;
- //fBookMarkOfs := fRecInfoOfs+SizeOf(tRecInfo);
- fRecordBufferSize :=fBookmarkOfs + BookmarkSize;
- end;
- procedure TSQLite.GetBookmarkData(Buffer: pChar; Data: Pointer);
- begin
- Move(Buffer[fBookMarkOfs],Data^,SizeOf(tBinBookMark));
- //implementacja jest watpliwa
- end;
- procedure TSQLite.SetBookMarkData(Buffer: pChar; Data: Pointer);
- begin
- Move(Data^,Buffer[fBookMarkOfs],SizeOf(tbinBookMark));
- end;
- procedure TSQLite.InternalGotoBookmark(ABookMark: Pointer);
- begin
- with pBinBookMark(ABookMark)^ do begin
- fCurrentRecord :=RecPtr;
- end;
- end;
- function TSQLite.FieldDefsStored: boolean;
- begin
- end;
- procedure TSQLite.ClearCalcFields(Buffer: pChar);
- var p : pointer;
- t : tSQliteRows;
- begin
- inherited;
- p:=buffer;
- if p<>nil then begin
- try
- t:=tSQliteRows(p);
- t.clearCalcFields;
- except
- end;
- end;
- end;
- function TSQLite.getRecordCount: integer;
- begin
- result :=fRecordCount;
- end;
- procedure TSQLite.OpenCursor(InfoQuery: Boolean);
- begin
- inherited;
- end;
- procedure TSQLite.SetRecNo(value: integer);
- begin
- inherited;
- end;
- function TSQLite.CreateTable: boolean;
- begin
- end;
- function TSQLite.getRecord(Buffer: pChar; GetMode: tGetMode;
- DoCheck: Boolean): tGetResult;
- begin
- if fRecordCount<1 then
- result:=grEof
- else begin
- result:=grOk;
- Case GetMode of
- gmNext :
- if fCurrentRecord>= (fRecordCount-1) then
- result:=grEof
- else
- Inc(fCurrentRecord);
- gmPrior :
- if (fCurrentRecord <=0) then
- result:=grBof
- else
- Dec(fCurrentRecord);
- gmCurrent :
- if (fCurrentRecord >= fRecordCount) or (fCurrentRecord <0) then
- result:=grError;
- end;
- end;
- if result=grOk then begin
- self.fRecordBufferSize:=sizeOf(fBuffer[fCurrentRecord]);
- self.fRecordSize:=self.fRecordBufferSize;
- // Buffer:=fBuffer.List[fcurrentRecord];
- //read data from psyh buffer sqlite..;)
- GetCalcFields(Buffer);
- { with fBuffer.Items[fCurrentRecord] as tSqliteRows do begin
- BookmarkFlag := bfCurrent;
- end;}
- with PRecInfo(Buffer)^ do
- begin
- Index := fCurrentRecord;
- BookmarkFlag := bfCurrent;
- Bookmark := Integer (fCurrentRecord);
- end;
-
- end;
- if result=grError then begin
- if DoCheck and DoExceptions then
- raise edataBaseError.Create('Invalid Record');
- end;
- end;
- procedure TSQLite.InternalInitFieldDefs;
- var i : integer;
- begin
- FieldDefs.Clear;
- for i:=0 to fLstname.Count-1 do begin
- FieldDefs.Add(fLstName[i],ftString,MaxiL[i],false);
- end;
- end;
- procedure TSQLite.InternalOpen;
- begin
- if fBUffer<>nil then begin
- clearBuffer;
- end;
- if (length(tableName)>0) and (fSQL.Count<1) then begin
- fsql.add('select rowid,* from '+fTableName);
- end;
- if not fDoSQL then
- fActive:=execSQL;
- InternalInitFieldDefs;
- {
- if ((fLstName.count-1)>0) and (fBuffer<>nil) then
- fRecordCount:=(fBuffer.Count-1) div (fLstName.Count-1)
- else
- fRecordCount:=0;
- }
- if (fBuffer<>nil) then
- fRecordCount:=(fBuffer.Count-1)
- else
- fRecordCount:=0;
- if DefaultFields then
- CreateFields;
- BindFields(true);
- FisOpen:=true;
- FRecordSize := sizeof (TRecInfo);
- FCurrentRecord := -1;
- BookmarkSize := sizeOf (Integer);
- end;
- procedure TSQLite.InternalClose;
- begin
- clearBuffer;
- end;
- function TSQLite.allocRecordBuffer: pChar;
- var p : pointer;
- begin
- //now is time to calculate currentRecordSize...
- GetMem(Result,GetRecordSize);
- FillChar(Result^,GetRecordSize,0);
- end;
- procedure TSQLite.FreeRecordBuffer(var Buffer: pChar);
- begin
- //FreeMem(Buffer,sizeOf(Buffer));
- FreeMem(Buffer,GetRecordSize);
- end;
- function TSQLite.getRecordSize: Word;
- begin
- Result:=sizeof(TRecInfo);
- end;
- procedure TSQLite.InternalAddRecord(Buffer: Pointer; DoAppend: boolean);
- begin
- end;
- procedure TSQLite.InternalDelete;
- begin
- end;
- procedure TSQLite.InternalFirst;
- begin
- self.fCurrentRecord:=0;
- end;
- procedure TSQLite.InternalHandleException;
- begin
- {
- if _DO_EXCEPTIONS=1 then
- Application.HandleException(Self)
- }
- end;
- procedure TSQLite.InternalInitRecord(Buffer: pChar);
- begin
- end;
- procedure TSQLite.InternalLast;
- begin
- fCurrentRecord:=fRecordCount;
- end;
- procedure TSQLite.InternalPost;
- begin
- end;
- procedure TSQLite.InternalSetToRecord(Buffer: pChar);
- begin
- end;
- function TSQLite.isCursorOpen: Boolean;
- begin
- end;
- procedure TSQLite.SetFieldData(Field: tField; Buffer: Pointer);
- // var aa : string;
- begin
- // Does NOthing ??
- // aa:=Field.NewValue;
- // inherited;
- end;
- procedure TSQLite.SetBookmarkFlag(Buffer: pChar; value: tBookmarkFlag);
- begin
- // inherited;
- end;
- function TSQLite.getFieldData(Field: tField; Buffer: Pointer): boolean;
- var i,k : integer;
- p : tSqliteField;
- r : tSqliteRows;
- pt : pointer;
- begin
- result:=false;
- k:=fieldDefs.Count-1;
- self.fLstName.Count;
- r:=fBuffer[PRecInfo(ActiveBuffer)^.Index] as tSqliteRows;
- if r=nil then exit;
- for i:=0 to k do begin
- if lowercase(fLstName[i])=lowercase(field.FieldName) then begin
- p:=r.items[i];
- if p = nil then break;
- p.GetData(Buffer,true);
- result:=true;
- break;
- end;
- end;
- end;
- { tSqliteRows }
- procedure tSqliteRows.Push(item: tSqliteField);
- begin
- if internalcount<fBuffercount then begin
- fBuffer[internalCount]:=item;
- inc(internalCount);
- end;
- end;
- constructor tSqliteRows.Create(fieldCount: integer);
- begin
- inherited create;
- if fieldCount<=0 then
- fieldCount:=1;
- fbuffercount:=fieldcount+1;
- getmem(fBuffer,fbuffercount*sizeof(pointer));
- end;
- destructor tSqliteRows.destroy;
- begin
- clearBuffer;
- inherited;
- end;
- function tSqliteRows.Pop: tSqliteField;
- begin
- result:=nil;
- if (internalCount>0) and (internalCount<fBuffercount) then begin
- result:=fBuffer[internalCount];
- Dec(internalCount);
- end;
- end;
- function tSqliteRows.getItem(index: integer): tSqliteField;
- begin
- result:=nil;
- if checkIndex(index) then
- result:=fBuffer[Index];
- end;
- procedure tSqliteRows.SetItem(index: integer; const Value: tSqliteField);
- begin
- if checkIndex(index) then
- fBuffer[index]:=Value;
- end;
- function tSqliteRows.checkIndex(index : integer): boolean;
- begin
- result:=false;
- if (index>=0) and (index<internalCount) then
- result:=true;
- end;
- procedure tSqliteRows.clearBuffer;
- var i : integer;
- begin
- if internalcount>0 then begin
- for i:=0 to internalCount do begin
- if fBuffer[i]<>nil then begin
- fBuffer[i].Free;
- fBuffer[i]:=nil;
- try
- except
- continue;
- end;
- end;
- end;
- fbuffercount:=0;
- FreeMem(fBuffer);
- end;
- end;
- procedure tSqliteRows.Clear;
- begin
- clearBuffer;
- internalCount:=0;
- end;
- procedure tSqliteRows.ClearCalcFields;
- begin
- end;
- function tSqliteRows.Add(pt: pChar;ptName : pChar):boolean;
- var tmp : int64;
- begin
- Push(tSqliteField.Create(nil));
- tmp:=internalCount-1;
- items[tmp].FieldKind:=fkData;
- items[tmp].SetFieldType(ftString);
- items[tmp].SetData(pt,true);
- end;
- procedure tSqlite.countMaxiLength(pt: pChar; index : int64);
- begin
- if length(pt)>maxil[index] then
- maxiL[index]:=length(pt);
- end;
- { tSqliteField }
- constructor tSqliteField.create(aOwner: tObject);
- begin
- inherited create;
- fOwner:=aOwner;
- end;
- destructor tSqliteField.destroy;
- begin
- inherited;
- end;
- function tSqliteField.GetData(Buffer: Pointer) : boolean;
- begin
- Result:=GetData(Buffer,True);
- end ;
- function tSqliteField.GetData(Buffer: Pointer;
- NativeFormat: Boolean): boolean;
- var
- l,tIntegerType : integer;
- tDateTimeType : tDateTime;
- begin
- try
- result:=false;
- if not nativeFormat then begin
- Move(data,Buffer^,sizeOf(data));
- result:=true;
- end else begin
- case self.fieldType of
- ftInteger : begin
- tIntegerType:=StrToInt(data);
- Move(tIntegerType,Buffer^,sizeOf(data));
- end;
- ftDateTime : begin
- tDateTimeType:=StrToDate(data);
- Move(tDateTimeType,Buffer^,sizeOf(data));
- end;
- ftString : begin
- // L:=length(data);
- // Move(data,Buffer^,l);
- StrCopy (Buffer, pchar(data));
- end;
- else
- Move(data,Buffer^,sizeOf(data));
- end;
- result:=true;
- end;
- except
- Buffer:=nil;
- end;
- end;
- procedure tSqliteField.SetData(pt: pChar; NativeFormat: boolean);
- begin
- data:=pt;
- end;
- procedure tSqliteField.SetFieldKind(const Value: tFieldKind);
- begin
- fFieldKind := Value;
- end;
- procedure tSqliteField.SetFieldType(const Value: tFieldType);
- begin
- fFieldType := Value;
- end;
- {
- procedure tSqliteField.SetName(const Value: string);
- begin
- fName := Value;
- end;
- }
- function TSQLite.getCanModify: boolean;
- begin
- result:=false;
- exit;//temporary
- if length(fTableName)>0 then
- result:=true;
- end;
- procedure TSQLite.InitMaxLength(length: integer);
- begin
- if not maxLengthInit and (length>0) then begin
- maxLengthInit:=true;
- maxilcount:=length;
- getmem(maxiL,maxilcount*sizeof(integer));
- end;
- end;
- procedure TSQLite.clearBuffer;
- begin
- if assigned(fBuffer) then begin
- if fBuffer.count>0 then begin
- fBuffer.pack;
- fBuffer.clear;
- end;
- end;
- if assigned(fLstVal) then begin
- fLstVal.Clear;
- end;
- if assigned(fLstName) then begin
- fLstName.Clear;
- end;
- end;
- {
- procedure TSQLite.internalInsert;
- begin
- inherited;
- if not getCanModify then exit;
- end;
- }
- procedure Register;
- begin
- RegisterComponents('MK', [tSqlite]);
- end;
- initialization
- {$ifdef dynload}
- LibsLoaded := LoadLibs;
- {$endif}
- {$ifdef fpc}
- MsgNoError := SystemErrorMsg(0);
- {$else}
- MsgNoError := 'The operation completed successfully';
- {$endif}
- finalization
- {$ifdef dynload}
- if DLLHandle <> 0 then
- FreeLibrary(DLLHandle);
- {$endif}
- end.
|