123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772 |
- {
- This file is part of the Free Pascal Classes Library (FCL).
- Copyright (c) 2006 by the Free Pascal development team
- SQLite3 connection for SQLDB
- See the File COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
-
- {
- Based on an implementation by Martin Schreiber, part of MSEIDE.
- Reworked all code so it conforms to FCL coding standards.
- }
-
- unit sqlite3conn;
- {$mode objfpc}
- {$h+}
- interface
- uses
- classes, db, bufdataset, sqldb, sqlite3dyn, types;
- const
- sqliteerrormax = 99;
-
- type
- PDateTime = ^TDateTime;
-
- TSqliteOption = (sloTransactions,sloDesignTransactions);
- TSqliteOptions = set of TSqliteOption;
-
- TStringArray = Array of string;
- PStringArray = ^TStringArray;
-
- TArrayStringArray = Array of TStringArray;
- PArrayStringArray = ^TArrayStringArray;
-
- { TSQLite3Connection }
- TSQLite3Connection = class(TSQLConnection)
- private
- fhandle: psqlite3;
- foptions: TSQLiteOptions;
- procedure setoptions(const avalue: tsqliteoptions);
- protected
- function stringquery(const asql: string): TStringArray;
- function stringsquery(const asql: string): TArrayStringArray;
- procedure checkerror(const aerror: integer);
-
- procedure DoInternalConnect; override;
- procedure DoInternalDisconnect; override;
- function GetHandle : pointer; override;
-
- Function AllocateCursorHandle : TSQLCursor; override;
- //aowner used as blob cache
- Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
- Function AllocateTransactionHandle : TSQLHandle; override;
-
- procedure PrepareStatement(cursor: TSQLCursor; ATransaction : TSQLTransaction;
- buf: string; AParams : TParams); override;
- procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
- function Fetch(cursor : TSQLCursor) : boolean; override;
- procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
- procedure UnPrepareStatement(cursor : TSQLCursor); override;
-
- procedure FreeFldBuffers(cursor : TSQLCursor); override;
- function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
- //if bufsize < 0 -> buffer was to small, should be -bufsize
- function GetTransactionHandle(trans : TSQLHandle): pointer; override;
- function Commit(trans : TSQLHandle) : boolean; override;
- function RollBack(trans : TSQLHandle) : boolean; override;
- function StartdbTransaction(trans : TSQLHandle; aParams : string) : boolean; override;
- procedure CommitRetaining(trans : TSQLHandle); override;
- procedure RollBackRetaining(trans : TSQLHandle); override;
- procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); override;
- // New methods
- procedure execsql(const asql: string);
- procedure UpdateIndexDefs(var IndexDefs : TIndexDefs; const TableName : string); // Differs from SQLDB.
- function getprimarykeyfield(const atablename: string; const acursor: tsqlcursor): string;
- function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
- function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; override;
- function StrToStatementType(s : string) : TStatementType; override;
- public
- function GetInsertID: int64;
- procedure GetFieldNames(const TableName : string; List : TStrings); override;
- published
- property Options: TSqliteOptions read FOptions write SetOptions;
- end;
-
- implementation
- uses
- dbconst, sysutils, typinfo, dateutils;
-
- type
- TStorageType = (stNone,stInteger,stFloat,stText,stBlob,stNull);
-
- TSQLite3Cursor = class(tsqlcursor)
- private
- fhandle : psqlite3;
- fstatement: psqlite3_stmt;
- ftail: pchar;
- fstate: integer;
- fparambinding: array of Integer;
- procedure checkerror(const aerror: integer);
- procedure bindparams(AParams : TParams);
- Procedure Prepare(Buf : String; APArams : TParams);
- Procedure UnPrepare;
- Procedure Execute;
- Function Fetch : Boolean;
- public
- RowsAffected : Largeint;
- end;
- procedure freebindstring(astring: pointer); cdecl;
- begin
- StrDispose(AString);
- end;
- procedure TSQLite3Cursor.checkerror(const aerror: integer);
- Var
- S : String;
- begin
- if (aerror<>sqlite_ok) then
- begin
- S:=strpas(sqlite3_errmsg(fhandle));
- DatabaseError(S);
- end;
- end;
- Procedure TSQLite3Cursor.bindparams(AParams : TParams);
- Function PCharStr(Const S : String) : PChar;
-
- begin
- Result:=StrAlloc(Length(S)+1);
- If (Result<>Nil) then
- StrPCopy(Result,S);
- end;
-
- Var
- I : Integer;
- P : TParam;
- pc : pchar;
- str1: string;
- cu1: currency;
- do1: double;
- parms : array of Integer;
-
- begin
- for I:=1 to high(fparambinding)+1 do
- begin
- P:=aparams[fparambinding[I-1]];
- if P.isnull then
- checkerror(sqlite3_bind_null(fstatement,I))
- else
- case P.datatype of
- ftinteger,
- ftboolean,
- ftsmallint: checkerror(sqlite3_bind_int(fstatement,I,p.asinteger));
- ftword: checkerror(sqlite3_bind_int(fstatement,I,P.asword));
- ftlargeint: checkerror(sqlite3_bind_int64(fstatement,I,P.aslargeint));
- ftbcd: begin
- cu1:= P.ascurrency;
- checkerror(sqlite3_bind_int64(fstatement,I,pint64(@cu1)^));
- end;
- ftfloat,
- ftcurrency,
- ftdatetime,
- ftdate,
- fttime: begin
- do1:= P.asfloat;
- checkerror(sqlite3_bind_double(fstatement,I,do1));
- end;
- ftstring: begin
- str1:= p.asstring;
- checkerror(sqlite3_bind_text(fstatement,I,pcharstr(str1), length(str1),@freebindstring));
- end;
- ftblob: begin
- str1:= P.asstring;
- checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1),@freebindstring));
- end;
- else
- databaseerror('Parameter type '+getenumname(typeinfo(tfieldtype),ord(P.datatype))+' not supported.');
- end; { Case }
- end;
- end;
- Procedure TSQLite3Cursor.Prepare(Buf : String; APArams : TParams);
- begin
- if assigned(aparams) and (aparams.count > 0) then
- buf := aparams.parsesql(buf,false,false,false,psinterbase,fparambinding);
- checkerror(sqlite3_prepare(fhandle,pchar(buf),length(buf),@fstatement,@ftail));
- end;
- Procedure TSQLite3Cursor.UnPrepare;
- begin
- sqlite3_finalize(fstatement); // No check.
- end;
- Procedure TSQLite3Cursor.Execute;
- var
- wo1: word;
- begin
- {$ifdef i386}
- wo1:= get8087cw;
- set8087cw(wo1 or $1f); //mask exceptions, Sqlite3 has overflow
- Try // Why do people always forget this ??
- {$endif}
- fstate:= sqlite3_step(fstatement);
- {$ifdef i386}
- finally
- set8087cw(wo1); //restore
- end;
- {$endif}
- if (fstate<=sqliteerrormax) then
- checkerror(sqlite3_reset(fstatement));
- RowsAffected:=sqlite3_changes(fhandle);
- if (fstate=sqlite_row) then
- fstate:= sqliteerrormax; //first row
- end;
- Function TSQLite3Cursor.Fetch : Boolean;
- begin
- if (fstate=sqliteerrormax) then
- fstate:=sqlite_row //first row;
- else if (fstate=sqlite_row) then
- begin
- fstate:=sqlite3_step(fstatement);
- if (fstate<=sqliteerrormax) then
- checkerror(sqlite3_reset(fstatement)); //right error returned??
- end;
- result:=(fstate=sqlite_row);
- end;
- { TSQLite3Connection }
- procedure TSQLite3Connection.LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction);
- var
- int1: integer;
- st: psqlite3_stmt;
- fnum: integer;
- begin
- st:=TSQLite3Cursor(cursor).fstatement;
- fnum:= FieldDef.fieldno - 1;
- int1:= sqlite3_column_bytes(st,fnum);
- ReAllocMem(ABlobBuf^.BlobBuffer^.Buffer,int1);
- if int1 > 0 then
- move(sqlite3_column_text(st,fnum)^,ABlobBuf^.BlobBuffer^.Buffer^,int1);
- ABlobBuf^.BlobBuffer^.Size := int1;
- end;
- function TSQLite3Connection.AllocateTransactionHandle: TSQLHandle;
- begin
- result:= tsqlhandle.create;
- end;
- function TSQLite3Connection.AllocateCursorHandle: TSQLCursor;
- Var
- Res : TSQLite3Cursor;
- begin
- Res:= TSQLite3Cursor.create;
- Res.fhandle:=self.fhandle;
- Result:=Res;
- end;
- procedure TSQLite3Connection.DeAllocateCursorHandle(var cursor: TSQLCursor);
- begin
- freeandnil(cursor);
- end;
- procedure TSQLite3Connection.PrepareStatement(cursor: TSQLCursor;
- ATransaction: TSQLTransaction; buf: string; AParams: TParams);
- begin
- TSQLite3Cursor(cursor).Prepare(Buf,AParams);
- end;
- procedure TSQLite3Connection.UnPrepareStatement(cursor: TSQLCursor);
- begin
- TSQLite3Cursor(cursor).UnPrepare;
- end;
- Type
- TFieldMap = Record
- N : String;
- T : TFieldType;
- end;
-
- Const
- FieldMapCount = 19;
- FieldMap : Array [1..FieldMapCount] of TFieldMap = (
- (n:'INT'; t: ftInteger),
- (n:'LARGEINT'; t:ftlargeInt),
- (n:'WORD'; t: ftWord),
- (n:'SMALLINT'; t: ftSmallint),
- (n:'BOOLEAN'; t: ftBoolean),
- (n:'REAL'; t: ftFloat),
- (n:'FLOAT'; t: ftFloat),
- (n:'DOUBLE'; t: ftFloat),
- (n:'TIMESTAMP'; t: ftDateTime),
- (n:'DATETIME'; t: ftDateTime), // MUST be before date
- (n:'DATE'; t: ftDate),
- (n:'TIME'; t: ftTime),
- (n:'CURRENCY'; t: ftCurrency),
- (n:'VARCHAR'; t: ftString),
- (n:'CHAR'; t: ftString),
- (n:'NUMERIC'; t: ftBCD),
- (n:'DECIMAL'; t: ftBCD),
- (n:'TEXT'; t: ftmemo),
- (n:'BLOB'; t: ftBlob)
- { Template:
- (n:''; t: ft)
- }
- );
- procedure TSQLite3Connection.AddFieldDefs(cursor: TSQLCursor;
- FieldDefs: TfieldDefs);
- var
- i : integer;
- FN,FD : string;
- ft1 : tfieldtype;
- size1 : word;
- ar1 : TStringArray;
- fi : integer;
- st : psqlite3_stmt;
-
- begin
- st:=TSQLite3Cursor(cursor).fstatement;
- for i:= 0 to sqlite3_column_count(st) - 1 do
- begin
- FN:=sqlite3_column_name(st,i);
- FD:=uppercase(sqlite3_column_decltype(st,i));
- ft1:= ftUnknown;
- size1:= 0;
- for fi := 1 to FieldMapCount do if pos(FieldMap[fi].N,FD)=1 then
- begin
- ft1:=FieldMap[fi].t;
- break;
- end;
- // Empty field types are allowed and used in calculated columns (aggregates)
- // and by pragma-statements
- if FD='' then ft1 := ftString;
- // handle some specials.
- size1:=0;
- case ft1 of
- ftString: begin
- fi:=pos('(',FD);
- if (fi>0) then
- begin
- System.Delete(FD,1,fi);
- fi:=pos(')',FD);
- size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255);
- if size1 > dsMaxStringSize then size1 := dsMaxStringSize;
- end
- else size1 := 255;
- end;
- ftBCD: begin
- fi:=pos(',',FD);
- if (fi>0) then
- begin
- System.Delete(FD,1,fi);
- fi:=pos(')',FD);
- size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255);
- end
- else size1 := 4;
- end;
- ftUnknown : DatabaseError('Unknown record type: '+FN);
- end; // Case
- tfielddef.create(fielddefs,FN,ft1,size1,false,i+1);
- end;
- end;
- procedure TSQLite3Connection.Execute(cursor: TSQLCursor; atransaction: tsqltransaction; AParams: TParams);
- var
- SC : TSQLite3Cursor;
-
- begin
- SC:=TSQLite3Cursor(cursor);
- If (AParams<>Nil) and (AParams.count > 0) then
- SC.BindParams(AParams);
- SC.Execute;
- end;
- Function NextWord(Var S : ShortString; Sep : Char) : String;
- Var
- P : Integer;
- begin
- P:=Pos(Sep,S);
- If (P=0) then
- P:=Length(S)+1;
- Result:=Copy(S,1,P-1);
- Delete(S,1,P);
- end;
- Function ParseSQLiteDate(S : ShortString) : TDateTime;
- Var
- Year, Month, Day : Integer;
- begin
- Result:=0;
- If TryStrToInt(NextWord(S,'-'),Year) then
- if TryStrToInt(NextWord(S,'-'),Month) then
- if TryStrToInt(NextWord(S,'-'),Day) then
- Result:=EncodeDate(Year,Month,Day);
- end;
- Function ParseSQLiteTime(S : ShortString) : TDateTime;
- Var
- Hour, Min, Sec : Integer;
- begin
- Result:=0;
- If TryStrToInt(NextWord(S,':'),Hour) then
- if TryStrToInt(NextWord(S,':'),Min) then
- if TryStrToInt(NextWord(S,':'),Sec) then
- Result:=EncodeTime(Hour,Min,Sec,0);
- end;
- Function ParseSQLiteDateTime(S : String) : TDateTime;
- var
- P : Integer;
- DS,TS : ShortString;
- begin
- DS:='';
- TS:='';
- P:=Pos(' ',S);
- If (P<>0) then
- begin
- DS:=Copy(S,1,P-1);
- TS:=S;
- Delete(TS,1,P);
- end
- else
- begin
- If (Pos('-',S)<>0) then
- DS:=S
- else if (Pos(':',S)<>0) then
- TS:=S;
- end;
- Result:=ComposeDateTime(ParseSQLiteDate(DS),ParseSQLiteTime(TS));
- end;
- function TSQLite3Connection.LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
- var
- st1: TStorageType;
- fnum: integer;
- i: integer;
- i64: int64;
- int1,int2: integer;
- str1: string;
- ar1,ar2: TStringArray;
- st : psqlite3_stmt;
-
- begin
- st:=TSQLite3Cursor(cursor).fstatement;
- fnum:= FieldDef.fieldno - 1;
- st1:= TStorageType(sqlite3_column_type(st,fnum));
- CreateBlob:=false;
- result:= st1 <> stnull;
- if Not result then
- Exit;
- case FieldDef.datatype of
- ftInteger : pinteger(buffer)^ := sqlite3_column_int(st,fnum);
- ftSmallInt : psmallint(buffer)^ := sqlite3_column_int(st,fnum);
- ftWord : pword(buffer)^ := sqlite3_column_int(st,fnum);
- ftBoolean : pwordbool(buffer)^ := sqlite3_column_int(st,fnum)<>0;
- ftLargeInt,
- ftBCD : PInt64(buffer)^:= sqlite3_column_int64(st,fnum);
- ftFloat,
- ftCurrency : pdouble(buffer)^:= sqlite3_column_double(st,fnum);
- ftDateTime,
- ftDate,
- ftTime: if st1 = sttext then
- begin
- setlength(str1,sqlite3_column_bytes(st,fnum));
- move(sqlite3_column_text(st,fnum)^,str1[1],length(str1));
- PDateTime(Buffer)^:=ParseSqliteDateTime(str1)
- end
- else
- Pdatetime(buffer)^:= sqlite3_column_double(st,fnum);
- ftString: begin
- int1:= sqlite3_column_bytes(st,fnum);
- if int1>FieldDef.Size then
- int1:=FieldDef.Size;
- if int1 > 0 then
- move(sqlite3_column_text(st,fnum)^,buffer^,int1);
- end;
- ftMemo,
- ftBlob: CreateBlob:=True;
- else { Case }
- result:= false; // unknown
- end; { Case }
- end;
- function TSQLite3Connection.Fetch(cursor: TSQLCursor): boolean;
- begin
- Result:=TSQLite3Cursor(cursor).Fetch;
- end;
- procedure TSQLite3Connection.FreeFldBuffers(cursor: TSQLCursor);
- begin
- //dummy
- end;
- function TSQLite3Connection.GetTransactionHandle(trans: TSQLHandle): pointer;
- begin
- result:= nil;
- end;
- function TSQLite3Connection.Commit(trans: TSQLHandle): boolean;
- begin
- execsql('COMMIT');
- result:= true;
- end;
- function TSQLite3Connection.RollBack(trans: TSQLHandle): boolean;
- begin
- execsql('ROLLBACK');
- result:= true;
- end;
- function TSQLite3Connection.StartdbTransaction(trans: TSQLHandle;
- aParams: string): boolean;
- begin
- execsql('BEGIN');
- result:= true;
- end;
- procedure TSQLite3Connection.CommitRetaining(trans: TSQLHandle);
- begin
- commit(trans);
- execsql('BEGIN');
- end;
- procedure TSQLite3Connection.RollBackRetaining(trans: TSQLHandle);
- begin
- rollback(trans);
- execsql('BEGIN');
- end;
- procedure TSQLite3Connection.DoInternalConnect;
- var
- str1: string;
- begin
- if Length(databasename)=0 then
- DatabaseError(SErrNoDatabaseName,self);
- initialisesqlite;
- str1:= databasename;
- checkerror(sqlite3_open(pchar(str1),@fhandle));
- end;
- procedure TSQLite3Connection.DoInternalDisconnect;
- begin
- if fhandle <> nil then
- begin
- checkerror(sqlite3_close(fhandle));
- fhandle:= nil;
- releasesqlite;
- end;
- end;
- function TSQLite3Connection.GetHandle: pointer;
- begin
- result:= fhandle;
- end;
- procedure TSQLite3Connection.checkerror(const aerror: integer);
- Var
- S : String;
- begin
- if (aerror<>sqlite_ok) then
- begin
- S:=strpas(sqlite3_errmsg(fhandle));
- DatabaseError(S,Self);
- end;
- end;
- procedure TSQLite3Connection.execsql(const asql: string);
- var
- err : pchar;
- str1 : string;
- res : integer;
- begin
- err:= nil;
- Res := sqlite3_exec(fhandle,pchar(asql),nil,nil,@err);
- if err <> nil then
- begin
- str1:= strpas(err);
- sqlite3_free(err);
- end;
- if (res<>sqlite_ok) then
- databaseerror(str1);
- end;
- function execcallback(adata: pointer; ncols: longint; //adata = PStringArray
- avalues: PPchar; anames: PPchar):longint; cdecl;
- var
- P : PStringArray;
- i : integer;
-
- begin
- P:=PStringArray(adata);
- SetLength(P^,ncols);
- for i:= 0 to ncols - 1 do
- P^[i]:= strPas(avalues[i]);
- result:= 0;
- end;
- function TSQLite3Connection.stringquery(const asql: string): TStringArray;
- begin
- SetLength(result,0);
- CheckError(sqlite3_exec(fhandle,pchar(asql),@execcallback,@result,nil));
- end;
- function execscallback(adata: pointer; ncols: longint; //adata = PArrayStringArray
- avalues: PPchar; anames: PPchar):longint; cdecl;
- var
- I,N : integer;
- PP : PArrayStringArray;
- p : PStringArray;
-
- begin
- PP:=PArrayStringArray(adata);
- N:=high(PP^); // Length-1;
- setlength(PP^,N+2); // increase with 1;
- p:= @(PP^[N]); // newly added array, fill with data.
- setlength(p^,ncols);
- for i:= 0 to ncols - 1 do
- p^[i]:= strPas(avalues[i]);
- result:= 0;
- end;
- function TSQLite3Connection.stringsquery(const asql: string): TArrayStringArray;
- begin
- SetLength(result,0);
- checkerror(sqlite3_exec(fhandle,pchar(asql),@execscallback,@result,nil));
- end;
- function TSQLite3Connection.getprimarykeyfield(const atablename: string;
- const acursor: tsqlcursor): string;
- var
- int1,int2: integer;
- ar1: TArrayStringArray;
- str1: string;
-
- begin
- result:= '';
- if atablename <> '' then
- begin
- ar1:= stringsquery('PRAGMA table_info('+atablename+');');
- for int1:= 0 to high(ar1) do
- begin
- if (high(ar1[int1]) >= 5) and (ar1[int1][5] <> '0') then
- begin
- result:= ar1[int1][1];
- break;
- end;
- end;
- end;
- end;
- function TSQLite3Connection.RowsAffected(cursor: TSQLCursor): TRowsCount;
- begin
- if assigned(cursor) then
- Result := (cursor as TSQLite3Cursor).RowsAffected
- else
- Result := -1;
- end;
- function TSQLite3Connection.GetSchemaInfoSQL(SchemaType: TSchemaType;
- SchemaObjectName, SchemaPattern: string): string;
-
- begin
- case SchemaType of
- stTables : result := 'select name as table_name from sqlite_master where type = ''table''';
- stColumns : result := 'pragma table_info(''' + (SchemaObjectName) + ''')';
- else
- DatabaseError(SMetadataUnavailable)
- end; {case}
- end;
- function TSQLite3Connection.StrToStatementType(s: string): TStatementType;
- begin
- S:=Lowercase(s);
- if s = 'pragma' then exit(stSelect);
- result := inherited StrToStatementType(s);
- end;
- procedure TSQLite3Connection.UpdateIndexDefs(var IndexDefs: TIndexDefs;
- const TableName: string);
- var
- str1: string;
-
- begin
- str1:= getprimarykeyfield(tablename,nil);
- if str1 <> '' then
- begin
- indexdefs.add('$PRIMARY_KEY$',str1,[ixPrimary,ixUnique]);
- end;
- end;
- {
- procedure TSQLite3Connection.UpdateIndexDefs(var IndexDefs: TIndexDefs;
- const TableName: string);
- var
- int1,int2: integer;
- ar1: TArrayStringArray;
- str1: string;
- begin
- ar1:= stringsquery('PRAGMA table_info('+tablename+');');
- for int1:= 0 to high(ar1) do begin
- if (high(ar1[int1]) >= 5) and (ar1[int1][5] <> '0') then begin
- indexdefs.add('$PRIMARY_KEY$',ar1[int1][1],[ixPrimary,ixUnique]);
- break;
- end;
- end;
- end;
- }
- function TSQLite3Connection.getinsertid: int64;
- begin
- result:= sqlite3_last_insert_rowid(fhandle);
- end;
- procedure TSQLite3Connection.GetFieldNames(const TableName: string;
- List: TStrings);
- begin
- GetDBInfo(stColumns,TableName,'name',List);
- end;
- procedure TSQLite3Connection.setoptions(const avalue: tsqliteoptions);
- begin
- if avalue <> foptions then
- begin
- checkdisconnected;
- foptions:= avalue;
- end;
- end;
- end.
|