summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2017-04-29 17:46:30 +0000
committermarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2017-04-29 17:46:30 +0000
commit4f906bc9b6101f9119cb9a16032d6d32e2b867af (patch)
treee26a43e1622fec2189ffa6328122c155095a511b
parenta9e80131b9486fd517cacf3bab92a649baab29ee (diff)
downloadfpc-4f906bc9b6101f9119cb9a16032d6d32e2b867af.tar.gz
* patch from Lacak to merge 34962-34963 manually (can't merge directly
due to blocking revs with unicode related conceptual changes) git-svn-id: http://svn.freepascal.org/svn/fpc/branches/fixes_3_0@36016 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp77
1 files changed, 50 insertions, 27 deletions
diff --git a/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp b/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
index efbbc67201..9c49c92fe2 100644
--- a/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
+++ b/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
@@ -409,13 +409,14 @@ Const
procedure TSQLite3Connection.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TFieldDefs);
var
- i, fi : integer;
- FN, FD, PrimaryKeyFields : string;
- ft1 : TFieldType;
+ st : psqlite3_stmt;
+ i, j, NotNull : integer;
+ FN, FD, PrimaryKeyFields : AnsiString;
+ FT : TFieldType;
size1, size2 : integer;
- st : psqlite3_stmt;
+ CN: PAnsiChar;
- function GetPrimaryKeyFields: string;
+ function GetPrimaryKeyFields: AnsiString;
var IndexDefs: TServerIndexDefs;
i: integer;
begin
@@ -432,7 +433,7 @@ var
Result := '';
end;
- function ExtractPrecisionAndScale(decltype: string; var precision, scale: integer): boolean;
+ function ExtractPrecisionAndScale(decltype: AnsiString; var precision, scale: integer): boolean;
var p: integer;
begin
p:=pos('(', decltype);
@@ -459,34 +460,34 @@ var
begin
PrimaryKeyFields := GetPrimaryKeyFields;
st:=TSQLite3Cursor(cursor).fstatement;
- for i:= 0 to sqlite3_column_count(st) - 1 do
+ 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
+ FN := sqlite3_column_name(st,i);
+ FD := uppercase(sqlite3_column_decltype(st,i));
+ FT := ftUnknown;
+ for j := 1 to FieldMapCount do if pos(FieldMap[j].N,FD)=1 then
begin
- ft1:=FieldMap[fi].t;
+ FT:=FieldMap[j].t;
break;
end;
// Column declared as INTEGER PRIMARY KEY [AUTOINCREMENT] becomes ROWID for given table
// declared data type must be INTEGER (not INT, BIGINT, NUMERIC etc.)
if (FD='INTEGER') and SameText(FN, PrimaryKeyFields) then
- ft1:=ftAutoInc;
+ FT:=ftAutoInc;
// In case of an empty fieldtype (FD='', which is allowed and used in calculated
// columns (aggregates) and by pragma-statements) or an unknown fieldtype,
// use the field's affinity:
- if ft1=ftUnknown then
+ if FT=ftUnknown then
case TStorageType(sqlite3_column_type(st,i)) of
- stInteger: ft1:=ftLargeInt;
- stFloat: ft1:=ftFloat;
- stBlob: ft1:=ftBlob;
- else ft1:=ftString;
+ stInteger: FT:=ftLargeInt;
+ stFloat: FT:=ftFloat;
+ stBlob: FT:=ftBlob;
+ else FT:=ftString;
end;
// handle some specials.
size1:=0;
- case ft1 of
+ size2:=0;
+ case FT of
ftString,
ftFixedChar,
ftFixedWideChar,
@@ -504,13 +505,22 @@ begin
size1 := 0; //sql: if a scale is omitted then scale is 0
ExtractPrecisionAndScale(FD, size2, size1);
if (size2<=18) and (size1=0) then
- ft1:=ftLargeInt
+ FT:=ftLargeInt
else if (size2-size1>MaxBCDPrecision-MaxBCDScale) or (size1>MaxBCDScale) then
- ft1:=ftFmtBCD;
+ FT:=ftFmtBCD;
end;
ftUnknown : DatabaseErrorFmt('Unknown or unsupported data type %s of column %s', [FD, FN]);
end; // Case
- FieldDefs.Add(FieldDefs.MakeNameUnique(FN),ft1,size1,false,i+1);
+ // check if SQLite is compiled with SQLITE_ENABLE_COLUMN_METADATA
+ if Assigned(sqlite3_column_origin_name) then
+ CN := sqlite3_column_origin_name(st,i)
+ else
+ CN := nil;
+ // check only for physical table columns (not computed)
+ // is column declared as NOT NULL ? (table name parameter (3rd) must be not nil)
+ if not (Assigned(CN) and (sqlite3_table_column_metadata(fhandle, sqlite3_column_database_name(st,i), sqlite3_column_table_name(st,i), CN, nil, nil, @NotNull, nil, nil) = SQLITE_OK)) then
+ NotNull := 0;
+ FieldDefs.Add(FieldDefs.MakeNameUnique(FN), FT, size1, NotNull=1, i+1);
end;
end;
@@ -885,8 +895,8 @@ end;
procedure TSQLite3Connection.UpdateIndexDefs(IndexDefs: TIndexDefs; TableName: string);
var
artableinfo, arindexlist, arindexinfo: TArrayStringArray;
- il,ii: integer;
- IndexName: string;
+ i,il,ii: integer;
+ DbName, IndexName: string;
IndexOptions: TIndexOptions;
PKFields, IXFields: TStrings;
@@ -907,14 +917,27 @@ begin
IXFields:=TStringList.Create;
IXFields.Delimiter:=';';
+ //check for multipart unquoted identifier: DatabaseName.TableName
+ if Pos('"',TableName) = 0 then
+ i := Pos('.',TableName)
+ else
+ i := 0;
+ if i>0 then
+ begin
+ DbName := Copy(TableName,1,i);
+ Delete(TableName,1,i);
+ end
+ else
+ DbName := '';
+
//primary key fields; 5th column "pk" is zero for columns that are not part of PK
- artableinfo := stringsquery('PRAGMA table_info('+TableName+');');
+ artableinfo := stringsquery('PRAGMA '+DbName+'table_info('+TableName+');');
for ii:=low(artableinfo) to high(artableinfo) do
if (high(artableinfo[ii]) >= 5) and (artableinfo[ii][5] >= '1') then
PKFields.Add(artableinfo[ii][1]);
//list of all table indexes
- arindexlist:=stringsquery('PRAGMA index_list('+TableName+');');
+ arindexlist:=stringsquery('PRAGMA '+DbName+'index_list('+TableName+');');
for il:=low(arindexlist) to high(arindexlist) do
begin
IndexName:=arindexlist[il][1];