zeoslib  UNKNOWN
 All Files
ZDbcSqLiteMetadata.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { SQLite Database Connectivity Classes }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZDbcSqLiteMetadata;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 uses
59  Types, Classes, SysUtils, ZSysUtils, ZDbcIntfs, ZDbcMetadata,
60  ZCompatibility, ZDbcSQLiteUtils, ZDbcConnection;
61 
62 type
63 
64  // technobot 2008-06-28 - methods moved as is from TZSQLiteDatabaseMetadata:
65  {** Implements SQLite Database Information. }
66  TZSQLiteDatabaseInfo = class(TZAbstractDatabaseInfo)
67 // function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
68 // const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
69  public
70  // database/driver/server info:
71  function GetDatabaseProductName: string; override;
72  function GetDatabaseProductVersion: string; override;
73  function GetDriverName: string; override;
74 // function GetDriverVersion: string; override; -> Same as parent
75  function GetDriverMajorVersion: Integer; override;
76  function GetDriverMinorVersion: Integer; override;
77 // function GetServerVersion: string; -> Not implemented
78 
79  // capabilities (what it can/cannot do):
80 // function AllProceduresAreCallable: Boolean; override; -> Not implemented
81 // function AllTablesAreSelectable: Boolean; override; -> Not implemented
82  function SupportsMixedCaseIdentifiers: Boolean; override;
83  function SupportsMixedCaseQuotedIdentifiers: Boolean; override;
84 // function SupportsAlterTableWithAddColumn: Boolean; override; -> Not implemented
85 // function SupportsAlterTableWithDropColumn: Boolean; override; -> Not implemented
86 // function SupportsColumnAliasing: Boolean; override; -> Not implemented
87 // function SupportsConvert: Boolean; override; -> Not implemented
88 // function SupportsConvertForTypes(FromType: TZSQLType; ToType: TZSQLType):
89 // Boolean; override; -> Not implemented
90 // function SupportsTableCorrelationNames: Boolean; override; -> Not implemented
91 // function SupportsDifferentTableCorrelationNames: Boolean; override; -> Not implemented
92  function SupportsExpressionsInOrderBy: Boolean; override;
93  function SupportsOrderByUnrelated: Boolean; override;
94  function SupportsGroupBy: Boolean; override;
95  function SupportsGroupByUnrelated: Boolean; override;
96  function SupportsGroupByBeyondSelect: Boolean; override;
97 // function SupportsLikeEscapeClause: Boolean; override; -> Not implemented
98 // function SupportsMultipleResultSets: Boolean; override; -> Not implemented
99 // function SupportsMultipleTransactions: Boolean; override; -> Not implemented
100 // function SupportsNonNullableColumns: Boolean; override; -> Not implemented
101 // function SupportsMinimumSQLGrammar: Boolean; override; -> Not implemented
102 // function SupportsCoreSQLGrammar: Boolean; override; -> Not implemented
103 // function SupportsExtendedSQLGrammar: Boolean; override; -> Not implemented
104 // function SupportsANSI92EntryLevelSQL: Boolean; override; -> Not implemented
105 // function SupportsANSI92IntermediateSQL: Boolean; override; -> Not implemented
106 // function SupportsANSI92FullSQL: Boolean; override; -> Not implemented
107  function SupportsIntegrityEnhancementFacility: Boolean; override;
108 // function SupportsOuterJoins: Boolean; override; -> Not implemented
109 // function SupportsFullOuterJoins: Boolean; override; -> Not implemented
110 // function SupportsLimitedOuterJoins: Boolean; override; -> Not implemented
111  function SupportsSchemasInDataManipulation: Boolean; override;
112  function SupportsSchemasInProcedureCalls: Boolean; override;
113  function SupportsSchemasInTableDefinitions: Boolean; override;
114  function SupportsSchemasInIndexDefinitions: Boolean; override;
115  function SupportsSchemasInPrivilegeDefinitions: Boolean; override;
116  function SupportsCatalogsInDataManipulation: Boolean; override;
117  function SupportsCatalogsInProcedureCalls: Boolean; override;
118  function SupportsCatalogsInTableDefinitions: Boolean; override;
119  function SupportsCatalogsInIndexDefinitions: Boolean; override;
120  function SupportsCatalogsInPrivilegeDefinitions: Boolean; override;
121  function SupportsPositionedDelete: Boolean; override;
122  function SupportsPositionedUpdate: Boolean; override;
123  function SupportsSelectForUpdate: Boolean; override;
124  function SupportsStoredProcedures: Boolean; override;
125  function SupportsSubqueriesInComparisons: Boolean; override;
126  function SupportsSubqueriesInExists: Boolean; override;
127  function SupportsSubqueriesInIns: Boolean; override;
128  function SupportsSubqueriesInQuantifieds: Boolean; override;
129  function SupportsCorrelatedSubqueries: Boolean; override;
130  function SupportsUnion: Boolean; override;
131  function SupportsUnionAll: Boolean; override;
132  function SupportsOpenCursorsAcrossCommit: Boolean; override;
133  function SupportsOpenCursorsAcrossRollback: Boolean; override;
134  function SupportsOpenStatementsAcrossCommit: Boolean; override;
135  function SupportsOpenStatementsAcrossRollback: Boolean; override;
136  function SupportsTransactions: Boolean; override;
137  function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
138  Boolean; override;
139  function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
140  function SupportsDataManipulationTransactionsOnly: Boolean; override;
141  function SupportsResultSetType(_Type: TZResultSetType): Boolean; override;
142  function SupportsResultSetConcurrency(_Type: TZResultSetType;
143  Concurrency: TZResultSetConcurrency): Boolean; override;
144 // function SupportsBatchUpdates: Boolean; override; -> Not implemented
145 
146  // maxima:
147  function GetMaxBinaryLiteralLength: Integer; override;
148  function GetMaxCharLiteralLength: Integer; override;
149  function GetMaxColumnNameLength: Integer; override;
150  function GetMaxColumnsInGroupBy: Integer; override;
151  function GetMaxColumnsInIndex: Integer; override;
152  function GetMaxColumnsInOrderBy: Integer; override;
153  function GetMaxColumnsInSelect: Integer; override;
154  function GetMaxColumnsInTable: Integer; override;
155  function GetMaxConnections: Integer; override;
156  function GetMaxCursorNameLength: Integer; override;
157  function GetMaxIndexLength: Integer; override;
158  function GetMaxSchemaNameLength: Integer; override;
159  function GetMaxProcedureNameLength: Integer; override;
160  function GetMaxCatalogNameLength: Integer; override;
161  function GetMaxRowSize: Integer; override;
162  function GetMaxStatementLength: Integer; override;
163  function GetMaxStatements: Integer; override;
164  function GetMaxTableNameLength: Integer; override;
165  function GetMaxTablesInSelect: Integer; override;
166  function GetMaxUserNameLength: Integer; override;
167 
168  // policies (how are various data and operations handled):
169 // function IsReadOnly: Boolean; override; -> Not implemented
170 // function IsCatalogAtStart: Boolean; override; -> Not implemented
171  function DoesMaxRowSizeIncludeBlobs: Boolean; override;
172 // function NullsAreSortedHigh: Boolean; override; -> Not implemented
173 // function NullsAreSortedLow: Boolean; override; -> Not implemented
174 // function NullsAreSortedAtStart: Boolean; override; -> Not implemented
175 // function NullsAreSortedAtEnd: Boolean; override; -> Not implemented
176 // function NullPlusNonNullIsNull: Boolean; override; -> Not implemented
177 // function UsesLocalFiles: Boolean; override; -> Not implemented
178  function UsesLocalFilePerTable: Boolean; override;
179  function StoresUpperCaseIdentifiers: Boolean; override;
180  function StoresLowerCaseIdentifiers: Boolean; override;
181  function StoresMixedCaseIdentifiers: Boolean; override;
182  function StoresUpperCaseQuotedIdentifiers: Boolean; override;
183  function StoresLowerCaseQuotedIdentifiers: Boolean; override;
184  function StoresMixedCaseQuotedIdentifiers: Boolean; override;
185  function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
186  function DataDefinitionCausesTransactionCommit: Boolean; override;
187  function DataDefinitionIgnoredInTransactions: Boolean; override;
188 
189  // interface details (terms, keywords, etc):
190 // function GetIdentifierQuoteString: string; override; -> Not implemented
191  function GetSchemaTerm: string; override;
192  function GetProcedureTerm: string; override;
193  function GetCatalogTerm: string; override;
194  function GetCatalogSeparator: string; override;
195  function GetSQLKeywords: string; override;
196  function GetNumericFunctions: string; override;
197  function GetStringFunctions: string; override;
198  function GetSystemFunctions: string; override;
199  function GetTimeDateFunctions: string; override;
200  function GetSearchStringEscape: string; override;
201  function GetExtraNameCharacters: string; override;
202  end;
203 
204  {** Implements SQLite Database Metadata. }
205  TZSQLiteDatabaseMetadata = class(TZAbstractDatabaseMetadata)
206  protected
207  function DeComposeObjectString(const S: String): String; reintroduce;
208  function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-28
209 
210  function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
211  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
212 // function UncachedGetSchemas: IZResultSet; override; -> not implemented
213 // function UncachedGetCatalogs: IZResultSet; override; -> not implemented
214  function UncachedGetTableTypes: IZResultSet; override;
215  function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
216  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
217 // function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string; -> not implemented
218 // const TableNamePattern: string): IZResultSet; override;
219 // function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string; -> not implemented
220 // const Table: string; const ColumnNamePattern: string): IZResultSet; override;
221  function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
222  const Table: string): IZResultSet; override;
223 // function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
224 // const Table: string): IZResultSet; override;
225 // function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
226 // const Table: string): IZResultSet; override;
227 // function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
228 // const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
229 // const ForeignTable: string): IZResultSet; override;
230  function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
231  Unique: Boolean; Approximate: Boolean): IZResultSet; override;
232 // function UncachedGetSequences(const Catalog: string; const SchemaPattern: string;
233 // const SequenceNamePattern: string): IZResultSet; virtual; -> Not implemented
234 // function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
235 // const ProcedureNamePattern: string): IZResultSet; override;
236 // function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
237 // const ProcedureNamePattern: string; const ColumnNamePattern: string):
238 // IZResultSet; override;
239 // function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
240 // const Table: string): IZResultSet; override;
241  function UncachedGetTypeInfo: IZResultSet; override;
242  function UncachedGetCharacterSets: IZResultSet; override; //EgonHugeist
243  public
244  destructor Destroy; override;
245  end;
246 
247 implementation
248 
249 uses
250  ZDbcUtils;
251 
252 { TZSQLiteDatabaseInfo }
253 
254 //----------------------------------------------------------------------
255 // First, a variety of minor information about the target database.
256 
257 {**
258  What's the name of this database product?
259  @return database product name
260 }
261 function TZSQLiteDatabaseInfo.GetDatabaseProductName: string;
262 begin
263  Result := 'SQLite';
264 end;
265 
266 {**
267  What's the version of this database product?
268  @return database version
269 }
270 function TZSQLiteDatabaseInfo.GetDatabaseProductVersion: string;
271 begin
272  Result := '';
273 end;
274 
275 {**
276  What's the name of this JDBC driver?
277  @return JDBC driver name
278 }
279 function TZSQLiteDatabaseInfo.GetDriverName: string;
280 begin
281  Result := 'Zeos Database Connectivity Driver for SQLite';
282 end;
283 
284 {**
285  What's this JDBC driver's major version number?
286  @return JDBC driver major version
287 }
288 function TZSQLiteDatabaseInfo.GetDriverMajorVersion: Integer;
289 begin
290  Result := 1;
291 end;
292 
293 {**
294  What's this JDBC driver's minor version number?
295  @return JDBC driver minor version number
296 }
297 function TZSQLiteDatabaseInfo.GetDriverMinorVersion: Integer;
298 begin
299  Result := 0;
300 end;
301 
302 {**
303  Does the database use a file for each table?
304  @return true if the database uses a local file for each table
305 }
306 function TZSQLiteDatabaseInfo.UsesLocalFilePerTable: Boolean;
307 begin
308  Result := False;
309 end;
310 
311 {**
312  Does the database treat mixed case unquoted SQL identifiers as
313  case sensitive and as a result store them in mixed case?
314  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return false.
315  @return <code>true</code> if so; <code>false</code> otherwise
316 }
317 function TZSQLiteDatabaseInfo.SupportsMixedCaseIdentifiers: Boolean;
318 begin
319  Result := True;
320 end;
321 
322 {**
323  Does the database treat mixed case unquoted SQL identifiers as
324  case insensitive and store them in upper case?
325  @return <code>true</code> if so; <code>false</code> otherwise
326 }
327 function TZSQLiteDatabaseInfo.StoresUpperCaseIdentifiers: Boolean;
328 begin
329  Result := False;
330 end;
331 
332 {**
333  Does the database treat mixed case unquoted SQL identifiers as
334  case insensitive and store them in lower case?
335  @return <code>true</code> if so; <code>false</code> otherwise
336 }
337 function TZSQLiteDatabaseInfo.StoresLowerCaseIdentifiers: Boolean;
338 begin
339  Result := False;
340 end;
341 
342 {**
343  Does the database treat mixed case unquoted SQL identifiers as
344  case insensitive and store them in mixed case?
345  @return <code>true</code> if so; <code>false</code> otherwise
346 }
347 function TZSQLiteDatabaseInfo.StoresMixedCaseIdentifiers: Boolean;
348 begin
349  Result := True;
350 end;
351 
352 {**
353  Does the database treat mixed case quoted SQL identifiers as
354  case sensitive and as a result store them in mixed case?
355  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
356  @return <code>true</code> if so; <code>false</code> otherwise
357 }
358 function TZSQLiteDatabaseInfo.SupportsMixedCaseQuotedIdentifiers: Boolean;
359 begin
360  Result := True;
361 end;
362 
363 {**
364  Does the database treat mixed case quoted SQL identifiers as
365  case insensitive and store them in upper case?
366  @return <code>true</code> if so; <code>false</code> otherwise
367 }
368 function TZSQLiteDatabaseInfo.StoresUpperCaseQuotedIdentifiers: Boolean;
369 begin
370  Result := False;
371 end;
372 
373 {**
374  Does the database treat mixed case quoted SQL identifiers as
375  case insensitive and store them in lower case?
376  @return <code>true</code> if so; <code>false</code> otherwise
377 }
378 function TZSQLiteDatabaseInfo.StoresLowerCaseQuotedIdentifiers: Boolean;
379 begin
380  Result := False;
381 end;
382 
383 {**
384  Does the database treat mixed case quoted SQL identifiers as
385  case insensitive and store them in mixed case?
386  @return <code>true</code> if so; <code>false</code> otherwise
387 }
388 function TZSQLiteDatabaseInfo.StoresMixedCaseQuotedIdentifiers: Boolean;
389 begin
390  Result := True;
391 end;
392 
393 {**
394  Gets a comma-separated list of all a database's SQL keywords
395  that are NOT also SQL92 keywords.
396  @return the list
397 }
398 function TZSQLiteDatabaseInfo.GetSQLKeywords: string;
399 begin
400  Result := 'ALL,AND,AS,BETWEEN,BY,CASE,CHECK,COLLATE,COMMIT,CONSTRAINT,CREATE,'
401  + 'DEFAULT,DEFERRABLE,DELETE,DISTINCT,DROP,ELSE,EXCEPT,FOREIGN,FROM,GLOB,'
402  + 'GROUP,HAVING,IN,INDEX,INSERT,INTERSECT,INTO,IS,ISNULL,JOIN,LIKE,LIMIT,'
403  + 'NOT,NOTNULL,NULL,ON,OR,ORDER,PRIMARY,REFERENCES,ROLLBACK,SELECT,SET,'
404  + 'TABLE,THEN,TRANSACTION,UNION,UNIQUE,UPDATE,USING,VALUES,WHEN,WHERE,'
405  + 'ABORT,AFTER,ASC,ATTACH,BEFORE,BEGIN,DEFERRED,CASCADE,CLUSTER,CONFLICT,'
406  + 'COPY,CROSS,DATABASE,DELIMITERS,DESC,DETACH,EACH,END,EXPLAIN,FAIL,FOR,'
407  + 'FULL,IGNORE,IMMEDIATE,INITIALLY,INNER,INSTEAD,KEY,LEFT,MATCH,NATURAL,'
408  + 'OF,OFFSET,OUTER,PRAGMA,RAISE,REPLACE,RESTRICT,RIGHT,ROW,STATEMENT,'
409  + 'TEMP,TEMPORARY,TRIGGER,VACUUM,VIEW';
410 end;
411 
412 {**
413  Gets a comma-separated list of math functions. These are the
414  X/Open CLI math function names used in the JDBC function escape
415  clause.
416  @return the list
417 }
418 function TZSQLiteDatabaseInfo.GetNumericFunctions: string;
419 begin
420  Result := 'ABS,MAX,MIN,RANDOM,ROUND';
421 end;
422 
423 {**
424  Gets a comma-separated list of string functions. These are the
425  X/Open CLI string function names used in the JDBC function escape
426  clause.
427  @return the list
428 }
429 function TZSQLiteDatabaseInfo.GetStringFunctions: string;
430 begin
431  Result := 'LENGTH,LIKE,LOWER,SOUNDEX,SUBSTRING,UPPER';
432 end;
433 
434 {**
435  Gets a comma-separated list of system functions. These are the
436  X/Open CLI system function names used in the JDBC function escape
437  clause.
438  @return the list
439 }
440 function TZSQLiteDatabaseInfo.GetSystemFunctions: string;
441 begin
442  Result := 'LAST_INSERT_ROWID,SQLITE_VERSION,TYPEOF';
443 end;
444 
445 {**
446  Gets a comma-separated list of time and date functions.
447  @return the list
448 }
449 function TZSQLiteDatabaseInfo.GetTimeDateFunctions: string;
450 begin
451  Result := '';
452 end;
453 
454 {**
455  Gets the string that can be used to escape wildcard characters.
456  This is the string that can be used to escape '_' or '%' in
457  the string pattern style catalog search parameters.
458 
459  <P>The '_' character represents any single character.
460  <P>The '%' character represents any sequence of zero or
461  more characters.
462 
463  @return the string used to escape wildcard characters
464 }
465 function TZSQLiteDatabaseInfo.GetSearchStringEscape: string;
466 begin
467  Result := '//';
468 end;
469 
470 {**
471  Gets all the "extra" characters that can be used in unquoted
472  identifier names (those beyond a-z, A-Z, 0-9 and _).
473  @return the string containing the extra characters
474 }
475 function TZSQLiteDatabaseInfo.GetExtraNameCharacters: string;
476 begin
477  Result := '';
478 end;
479 
480 //--------------------------------------------------------------------
481 // Functions describing which features are supported.
482 
483 {**
484  Are expressions in "ORDER BY" lists supported?
485  @return <code>true</code> if so; <code>false</code> otherwise
486 }
487 function TZSQLiteDatabaseInfo.SupportsExpressionsInOrderBy: Boolean;
488 begin
489  Result := False;
490 end;
491 
492 {**
493  Can an "ORDER BY" clause use columns not in the SELECT statement?
494  @return <code>true</code> if so; <code>false</code> otherwise
495 }
496 function TZSQLiteDatabaseInfo.SupportsOrderByUnrelated: Boolean;
497 begin
498  Result := False;
499 end;
500 
501 {**
502  Is some form of "GROUP BY" clause supported?
503  @return <code>true</code> if so; <code>false</code> otherwise
504 }
505 function TZSQLiteDatabaseInfo.SupportsGroupBy: Boolean;
506 begin
507  Result := True;
508 end;
509 
510 {**
511  Can a "GROUP BY" clause use columns not in the SELECT?
512  @return <code>true</code> if so; <code>false</code> otherwise
513 }
514 function TZSQLiteDatabaseInfo.SupportsGroupByUnrelated: Boolean;
515 begin
516  Result := True;
517 end;
518 
519 {**
520  Can a "GROUP BY" clause add columns not in the SELECT
521  provided it specifies all the columns in the SELECT?
522  @return <code>true</code> if so; <code>false</code> otherwise
523 }
524 function TZSQLiteDatabaseInfo.SupportsGroupByBeyondSelect: Boolean;
525 begin
526  Result := True;
527 end;
528 
529 {**
530  Is the SQL Integrity Enhancement Facility supported?
531  @return <code>true</code> if so; <code>false</code> otherwise
532 }
533 function TZSQLiteDatabaseInfo.SupportsIntegrityEnhancementFacility: Boolean;
534 begin
535  Result := False;
536 end;
537 
538 {**
539  What's the database vendor's preferred term for "schema"?
540  @return the vendor term
541 }
542 function TZSQLiteDatabaseInfo.GetSchemaTerm: string;
543 begin
544  Result := '';
545 end;
546 
547 {**
548  What's the database vendor's preferred term for "procedure"?
549  @return the vendor term
550 }
551 function TZSQLiteDatabaseInfo.GetProcedureTerm: string;
552 begin
553  Result := '';
554 end;
555 
556 {**
557  What's the database vendor's preferred term for "catalog"?
558  @return the vendor term
559 }
560 function TZSQLiteDatabaseInfo.GetCatalogTerm: string;
561 begin
562  Result := 'database';
563 end;
564 
565 {**
566  What's the separator between catalog and table name?
567  @return the separator string
568 }
569 function TZSQLiteDatabaseInfo.GetCatalogSeparator: string;
570 begin
571  Result := '.';
572 end;
573 
574 {**
575  Can a schema name be used in a data manipulation statement?
576  @return <code>true</code> if so; <code>false</code> otherwise
577 }
578 function TZSQLiteDatabaseInfo.SupportsSchemasInDataManipulation: Boolean;
579 begin
580  Result := True;
581 end;
582 
583 {**
584  Can a schema name be used in a procedure call statement?
585  @return <code>true</code> if so; <code>false</code> otherwise
586 }
587 function TZSQLiteDatabaseInfo.SupportsSchemasInProcedureCalls: Boolean;
588 begin
589  Result := False;
590 end;
591 
592 {**
593  Can a schema name be used in a table definition statement?
594  @return <code>true</code> if so; <code>false</code> otherwise
595 }
596 function TZSQLiteDatabaseInfo.SupportsSchemasInTableDefinitions: Boolean;
597 begin
598  Result := False;
599 end;
600 
601 {**
602  Can a schema name be used in an index definition statement?
603  @return <code>true</code> if so; <code>false</code> otherwise
604 }
605 function TZSQLiteDatabaseInfo.SupportsSchemasInIndexDefinitions: Boolean;
606 begin
607  Result := False;
608 end;
609 
610 {**
611  Can a schema name be used in a privilege definition statement?
612  @return <code>true</code> if so; <code>false</code> otherwise
613 }
614 function TZSQLiteDatabaseInfo.SupportsSchemasInPrivilegeDefinitions: Boolean;
615 begin
616  Result := False;
617 end;
618 
619 {**
620  Can a catalog name be used in a data manipulation statement?
621  @return <code>true</code> if so; <code>false</code> otherwise
622 }
623 function TZSQLiteDatabaseInfo.SupportsCatalogsInDataManipulation: Boolean;
624 begin
625  Result := True;
626 end;
627 
628 {**
629  Can a catalog name be used in a procedure call statement?
630  @return <code>true</code> if so; <code>false</code> otherwise
631 }
632 function TZSQLiteDatabaseInfo.SupportsCatalogsInProcedureCalls: Boolean;
633 begin
634  Result := False;
635 end;
636 
637 {**
638  Can a catalog name be used in a table definition statement?
639  @return <code>true</code> if so; <code>false</code> otherwise
640 }
641 function TZSQLiteDatabaseInfo.SupportsCatalogsInTableDefinitions: Boolean;
642 begin
643  Result := False;
644 end;
645 
646 {**
647  Can a catalog name be used in an index definition statement?
648  @return <code>true</code> if so; <code>false</code> otherwise
649 }
650 function TZSQLiteDatabaseInfo.SupportsCatalogsInIndexDefinitions: Boolean;
651 begin
652  Result := False;
653 end;
654 
655 {**
656  Can a catalog name be used in a privilege definition statement?
657  @return <code>true</code> if so; <code>false</code> otherwise
658 }
659 function TZSQLiteDatabaseInfo.SupportsCatalogsInPrivilegeDefinitions: Boolean;
660 begin
661  Result := True;
662 end;
663 
664 {**
665  Is positioned DELETE supported?
666  @return <code>true</code> if so; <code>false</code> otherwise
667 }
668 function TZSQLiteDatabaseInfo.SupportsPositionedDelete: Boolean;
669 begin
670  Result := False;
671 end;
672 
673 {**
674  Is positioned UPDATE supported?
675  @return <code>true</code> if so; <code>false</code> otherwise
676 }
677 function TZSQLiteDatabaseInfo.SupportsPositionedUpdate: Boolean;
678 begin
679  Result := False;
680 end;
681 
682 {**
683  Is SELECT for UPDATE supported?
684  @return <code>true</code> if so; <code>false</code> otherwise
685 }
686 function TZSQLiteDatabaseInfo.SupportsSelectForUpdate: Boolean;
687 begin
688  Result := False;
689 end;
690 
691 {**
692  Are stored procedure calls using the stored procedure escape
693  syntax supported?
694  @return <code>true</code> if so; <code>false</code> otherwise
695 }
696 function TZSQLiteDatabaseInfo.SupportsStoredProcedures: Boolean;
697 begin
698  Result := False;
699 end;
700 
701 {**
702  Are subqueries in comparison expressions supported?
703  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
704  @return <code>true</code> if so; <code>false</code> otherwise
705 }
706 function TZSQLiteDatabaseInfo.SupportsSubqueriesInComparisons: Boolean;
707 begin
708  Result := True;
709 end;
710 
711 {**
712  Are subqueries in 'exists' expressions supported?
713  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
714  @return <code>true</code> if so; <code>false</code> otherwise
715 }
716 function TZSQLiteDatabaseInfo.SupportsSubqueriesInExists: Boolean;
717 begin
718  Result := True;
719 end;
720 
721 {**
722  Are subqueries in 'in' statements supported?
723  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
724  @return <code>true</code> if so; <code>false</code> otherwise
725 }
726 function TZSQLiteDatabaseInfo.SupportsSubqueriesInIns: Boolean;
727 begin
728  Result := True;
729 end;
730 
731 {**
732  Are subqueries in quantified expressions supported?
733  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
734  @return <code>true</code> if so; <code>false</code> otherwise
735 }
736 function TZSQLiteDatabaseInfo.SupportsSubqueriesInQuantifieds: Boolean;
737 begin
738  Result := True;
739 end;
740 
741 {**
742  Are correlated subqueries supported?
743  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
744  @return <code>true</code> if so; <code>false</code> otherwise
745 }
746 function TZSQLiteDatabaseInfo.SupportsCorrelatedSubqueries: Boolean;
747 begin
748  Result := True;
749 end;
750 
751 {**
752  Is SQL UNION supported?
753  @return <code>true</code> if so; <code>false</code> otherwise
754 }
755 function TZSQLiteDatabaseInfo.SupportsUnion: Boolean;
756 begin
757  Result := True;
758 end;
759 
760 {**
761  Is SQL UNION ALL supported?
762  @return <code>true</code> if so; <code>false</code> otherwise
763 }
764 function TZSQLiteDatabaseInfo.SupportsUnionAll: Boolean;
765 begin
766  Result := True;
767 end;
768 
769 {**
770  Can cursors remain open across commits?
771  @return <code>true</code> if cursors always remain open;
772  <code>false</code> if they might not remain open
773 }
774 function TZSQLiteDatabaseInfo.SupportsOpenCursorsAcrossCommit: Boolean;
775 begin
776  Result := False;
777 end;
778 
779 {**
780  Can cursors remain open across rollbacks?
781  @return <code>true</code> if cursors always remain open;
782  <code>false</code> if they might not remain open
783 }
784 function TZSQLiteDatabaseInfo.SupportsOpenCursorsAcrossRollback: Boolean;
785 begin
786  Result := False;
787 end;
788 
789 {**
790  Can statements remain open across commits?
791  @return <code>true</code> if statements always remain open;
792  <code>false</code> if they might not remain open
793 }
794 function TZSQLiteDatabaseInfo.SupportsOpenStatementsAcrossCommit: Boolean;
795 begin
796  Result := False;
797 end;
798 
799 {**
800  Can statements remain open across rollbacks?
801  @return <code>true</code> if statements always remain open;
802  <code>false</code> if they might not remain open
803 }
804 function TZSQLiteDatabaseInfo.SupportsOpenStatementsAcrossRollback: Boolean;
805 begin
806  Result := False;
807 end;
808 
809 //----------------------------------------------------------------------
810 // The following group of methods exposes various limitations
811 // based on the target database with the current driver.
812 // Unless otherwise specified, a result of zero means there is no
813 // limit, or the limit is not known.
814 
815 {**
816  How many hex characters can you have in an inline binary literal?
817  @return max binary literal length in hex characters;
818  a result of zero means that there is no limit or the limit is not known
819 }
820 function TZSQLiteDatabaseInfo.GetMaxBinaryLiteralLength: Integer;
821 begin
822  Result := 0;
823 end;
824 
825 {**
826  What's the max length for a character literal?
827  @return max literal length;
828  a result of zero means that there is no limit or the limit is not known
829 }
830 function TZSQLiteDatabaseInfo.GetMaxCharLiteralLength: Integer;
831 begin
832  Result := 0;
833 end;
834 
835 {**
836  What's the limit on column name length?
837  @return max column name length;
838  a result of zero means that there is no limit or the limit is not known
839 }
840 function TZSQLiteDatabaseInfo.GetMaxColumnNameLength: Integer;
841 begin
842  Result := 0;
843 end;
844 
845 {**
846  What's the maximum number of columns in a "GROUP BY" clause?
847  @return max number of columns;
848  a result of zero means that there is no limit or the limit is not known
849 }
850 function TZSQLiteDatabaseInfo.GetMaxColumnsInGroupBy: Integer;
851 begin
852  Result := 0;
853 end;
854 
855 {**
856  What's the maximum number of columns allowed in an index?
857  @return max number of columns;
858  a result of zero means that there is no limit or the limit is not known
859 }
860 function TZSQLiteDatabaseInfo.GetMaxColumnsInIndex: Integer;
861 begin
862  Result := 0;
863 end;
864 
865 {**
866  What's the maximum number of columns in an "ORDER BY" clause?
867  @return max number of columns;
868  a result of zero means that there is no limit or the limit is not known
869 }
870 function TZSQLiteDatabaseInfo.GetMaxColumnsInOrderBy: Integer;
871 begin
872  Result := 0;
873 end;
874 
875 {**
876  What's the maximum number of columns in a "SELECT" list?
877  @return max number of columns;
878  a result of zero means that there is no limit or the limit is not known
879 }
880 function TZSQLiteDatabaseInfo.GetMaxColumnsInSelect: Integer;
881 begin
882  Result := 0;
883 end;
884 
885 {**
886  What's the maximum number of columns in a table?
887  @return max number of columns;
888  a result of zero means that there is no limit or the limit is not known
889 }
890 function TZSQLiteDatabaseInfo.GetMaxColumnsInTable: Integer;
891 begin
892  Result := 0;
893 end;
894 
895 {**
896  How many active connections can we have at a time to this database?
897  @return max number of active connections;
898  a result of zero means that there is no limit or the limit is not known
899 }
900 function TZSQLiteDatabaseInfo.GetMaxConnections: Integer;
901 begin
902  Result := 0;
903 end;
904 
905 {**
906  What's the maximum cursor name length?
907  @return max cursor name length in bytes;
908  a result of zero means that there is no limit or the limit is not known
909 }
910 function TZSQLiteDatabaseInfo.GetMaxCursorNameLength: Integer;
911 begin
912  Result := 0;
913 end;
914 
915 {**
916  Retrieves the maximum number of bytes for an index, including all
917  of the parts of the index.
918  @return max index length in bytes, which includes the composite of all
919  the constituent parts of the index;
920  a result of zero means that there is no limit or the limit is not known
921 }
922 function TZSQLiteDatabaseInfo.GetMaxIndexLength: Integer;
923 begin
924  Result := 0;
925 end;
926 
927 {**
928  What's the maximum length allowed for a schema name?
929  @return max name length in bytes;
930  a result of zero means that there is no limit or the limit is not known
931 }
932 function TZSQLiteDatabaseInfo.GetMaxSchemaNameLength: Integer;
933 begin
934  Result := 0;
935 end;
936 
937 {**
938  What's the maximum length of a procedure name?
939  @return max name length in bytes;
940  a result of zero means that there is no limit or the limit is not known
941 }
942 function TZSQLiteDatabaseInfo.GetMaxProcedureNameLength: Integer;
943 begin
944  Result := 0;
945 end;
946 
947 {**
948  What's the maximum length of a catalog name?
949  @return max name length in bytes;
950  a result of zero means that there is no limit or the limit is not known
951 }
952 function TZSQLiteDatabaseInfo.GetMaxCatalogNameLength: Integer;
953 begin
954  Result := 0;
955 end;
956 
957 {**
958  What's the maximum length of a single row?
959  @return max row size in bytes;
960  a result of zero means that there is no limit or the limit is not known
961 }
962 function TZSQLiteDatabaseInfo.GetMaxRowSize: Integer;
963 begin
964  Result := 0;
965 end;
966 
967 {**
968  Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
969  blobs?
970  @return <code>true</code> if so; <code>false</code> otherwise
971 }
972 function TZSQLiteDatabaseInfo.DoesMaxRowSizeIncludeBlobs: Boolean;
973 begin
974  Result := True;
975 end;
976 
977 {**
978  What's the maximum length of an SQL statement?
979  @return max length in bytes;
980  a result of zero means that there is no limit or the limit is not known
981 }
982 function TZSQLiteDatabaseInfo.GetMaxStatementLength: Integer;
983 begin
984  Result := 65535;
985 end;
986 
987 {**
988  How many active statements can we have open at one time to this
989  database?
990  @return the maximum number of statements that can be open at one time;
991  a result of zero means that there is no limit or the limit is not known
992 }
993 function TZSQLiteDatabaseInfo.GetMaxStatements: Integer;
994 begin
995  Result := 0;
996 end;
997 
998 {**
999  What's the maximum length of a table name?
1000  @return max name length in bytes;
1001  a result of zero means that there is no limit or the limit is not known
1002 }
1003 function TZSQLiteDatabaseInfo.GetMaxTableNameLength: Integer;
1004 begin
1005  Result := 0;
1006 end;
1007 
1008 {**
1009  What's the maximum number of tables in a SELECT statement?
1010  @return the maximum number of tables allowed in a SELECT statement;
1011  a result of zero means that there is no limit or the limit is not known
1012 }
1013 function TZSQLiteDatabaseInfo.GetMaxTablesInSelect: Integer;
1014 begin
1015  Result := 0;
1016 end;
1017 
1018 {**
1019  What's the maximum length of a user name?
1020  @return max user name length in bytes;
1021  a result of zero means that there is no limit or the limit is not known
1022 }
1023 function TZSQLiteDatabaseInfo.GetMaxUserNameLength: Integer;
1024 begin
1025  Result := 0;
1026 end;
1027 
1028 //----------------------------------------------------------------------
1029 
1030 {**
1031  What's the database's default transaction isolation level? The
1032  values are defined in <code>java.sql.Connection</code>.
1033  @return the default isolation level
1034  @see Connection
1035 }
1036 function TZSQLiteDatabaseInfo.GetDefaultTransactionIsolation:
1037  TZTransactIsolationLevel;
1038 begin
1039  Result := tiNone;
1040 end;
1041 
1042 {**
1043  Are transactions supported? If not, invoking the method
1044  <code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
1045  @return <code>true</code> if transactions are supported; <code>false</code> otherwise
1046 }
1047 function TZSQLiteDatabaseInfo.SupportsTransactions: Boolean;
1048 begin
1049  Result := True;
1050 end;
1051 
1052 {**
1053  Does this database support the given transaction isolation level?
1054  @param level the values are defined in <code>java.sql.Connection</code>
1055  @return <code>true</code> if so; <code>false</code> otherwise
1056  @see Connection
1057 }
1058 function TZSQLiteDatabaseInfo.SupportsTransactionIsolationLevel(
1059  Level: TZTransactIsolationLevel): Boolean;
1060 begin
1061  Result := True;
1062 end;
1063 
1064 {**
1065  Are both data definition and data manipulation statements
1066  within a transaction supported?
1067  @return <code>true</code> if so; <code>false</code> otherwise
1068 }
1069 function TZSQLiteDatabaseInfo.
1070  SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
1071 begin
1072  Result := True;
1073 end;
1074 
1075 {**
1076  Are only data manipulation statements within a transaction
1077  supported?
1078  @return <code>true</code> if so; <code>false</code> otherwise
1079 }
1080 function TZSQLiteDatabaseInfo.
1081  SupportsDataManipulationTransactionsOnly: Boolean;
1082 begin
1083  Result := True;
1084 end;
1085 
1086 {**
1087  Does a data definition statement within a transaction force the
1088  transaction to commit?
1089  @return <code>true</code> if so; <code>false</code> otherwise
1090 }
1091 function TZSQLiteDatabaseInfo.DataDefinitionCausesTransactionCommit: Boolean;
1092 begin
1093  Result := True;
1094 end;
1095 
1096 {**
1097  Is a data definition statement within a transaction ignored?
1098  @return <code>true</code> if so; <code>false</code> otherwise
1099 }
1100 function TZSQLiteDatabaseInfo.DataDefinitionIgnoredInTransactions: Boolean;
1101 begin
1102  Result := False;
1103 end;
1104 
1105 {**
1106  Does the database support the given result set type?
1107  @param type defined in <code>java.sql.ResultSet</code>
1108  @return <code>true</code> if so; <code>false</code> otherwise
1109 }
1110 function TZSQLiteDatabaseInfo.SupportsResultSetType(
1111  _Type: TZResultSetType): Boolean;
1112 begin
1113  Result := _Type = rtForwardOnly;
1114 end;
1115 
1116 {**
1117  Does the database support the concurrency type in combination
1118  with the given result set type?
1119 
1120  @param type defined in <code>java.sql.ResultSet</code>
1121  @param concurrency type defined in <code>java.sql.ResultSet</code>
1122  @return <code>true</code> if so; <code>false</code> otherwise
1123 }
1124 function TZSQLiteDatabaseInfo.SupportsResultSetConcurrency(
1125  _Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
1126 begin
1127  Result := (_Type = rtForwardOnly) and (Concurrency = rcReadOnly);
1128 end;
1129 
1130 
1131 { TZSQLiteDatabaseMetadata }
1132 
1133 {**
1134  Decomposes a object name, AnsiQuotedStr or NullText
1135  @param S the object string
1136  @return a non-quoted string
1137 }
1138 function TZSQLiteDatabaseMetadata.DecomposeObjectString(const S: String): String;
1139 begin
1140  if S = '' then
1141  Result := S
1142  else
1143  if IC.IsQuoted(S) then
1144  Result := IC.ExtractQuote(S)
1145  else
1146  Result := s;
1147 end;
1148 
1149 {**
1150  Destroys this object and cleanups the memory.
1151 }
1152 destructor TZSQLiteDatabaseMetadata.Destroy;
1153 begin
1154  inherited Destroy;
1155 end;
1156 
1157 {**
1158  Constructs a database information object and returns the interface to it. Used
1159  internally by the constructor.
1160  @return the database information object interface
1161 }
1162 function TZSQLiteDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
1163 begin
1164  Result := TZSQLiteDatabaseInfo.Create(Self);
1165 end;
1166 
1167 {**
1168  Gets a description of tables available in a catalog.
1169 
1170  <P>Only table descriptions matching the catalog, schema, table
1171  name and type criteria are returned. They are ordered by
1172  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1173 
1174  <P>Each table description has the following columns:
1175  <OL>
1176  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1177  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1178  <LI><B>TABLE_NAME</B> String => table name
1179  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1180  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1181  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1182  <LI><B>REMARKS</B> String => explanatory comment on the table
1183  </OL>
1184 
1185  <P><B>Note:</B> Some databases may not return information for
1186  all tables.
1187 
1188  @param catalog a catalog name; "" retrieves those without a
1189  catalog; null means drop catalog name from the selection criteria
1190  @param schemaPattern a schema name pattern; "" retrieves those
1191  without a schema
1192  @param tableNamePattern a table name pattern
1193  @param types a list of table types to include; null returns all types
1194  @return <code>ResultSet</code> - each row is a table description
1195  @see #getSearchStringEscape
1196 }
1197 function TZSQLiteDatabaseMetadata.UncachedGetTables(const Catalog: string;
1198  const SchemaPattern: string; const TableNamePattern: string;
1199  const Types: TStringDynArray): IZResultSet;
1200 var
1201  WhereClause, SQL: string;
1202 
1203  function IncludedType(TypeName: string): Boolean;
1204  var I: Integer;
1205  begin
1206  Result := False;
1207  for I := Low(Types) to High(Types) do
1208  Result := Result or (UpperCase(Types[I]) = TypeName);
1209  Result := Result or (Length(Types) = 0);
1210  end;
1211 
1212 begin
1213  WhereClause := '';
1214  if IncludedType('TABLE') then
1215  WhereClause := 'TYPE=''table''';
1216  if IncludedType('VIEW') then
1217  begin
1218  if WhereClause <> '' then
1219  WhereClause := '(' + WhereClause + ' OR TYPE=''view'')'
1220  else WhereClause := 'TYPE=''view''';
1221  end;
1222 
1223  SQL := 'SELECT ''' + Catalog + ''' AS TABLE_CAT, NULL AS TABLE_SCHEM,'
1224  + ' TBL_NAME AS TABLE_NAME, UPPER(TYPE) AS TABLE_TYPE, NULL AS REMARKS'
1225  + ' FROM ';
1226  if Catalog <> '' then
1227  SQL := SQL + Catalog + '.';
1228  SQL := SQL + 'SQLITE_MASTER WHERE ' + WhereClause
1229  + ' AND TBL_NAME LIKE ''' + ToLikeString(TableNamePattern) + '''';
1230 
1231  Result := CopyToVirtualResultSet(
1232  GetConnection.CreateStatement.ExecuteQuery(SQL),
1233  ConstructVirtualResultSet(TableColumnsDynArray));
1234 end;
1235 
1236 {**
1237  Gets the table types available in this database. The results
1238  are ordered by table type.
1239 
1240  <P>The table type is:
1241  <OL>
1242  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1243  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1244  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1245  </OL>
1246 
1247  @return <code>ResultSet</code> - each row has a single String column that is a
1248  table type
1249 }
1250 function TZSQLiteDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
1251 const
1252  TableTypeCount = 2;
1253  Types: array [1..TableTypeCount] of string = ('TABLE', 'VIEW');
1254 var
1255  I: Integer;
1256 begin
1257  Result:=inherited UncachedGetTableTypes;
1258 
1259  for I := 1 to TableTypeCount do
1260  begin
1261  Result.MoveToInsertRow;
1262  Result.UpdateString(1, Types[I]);
1263  Result.InsertRow;
1264  end;
1265 end;
1266 
1267 {**
1268  Gets a description of table columns available in
1269  the specified catalog.
1270 
1271  <P>Only column descriptions matching the catalog, schema, table
1272  and column name criteria are returned. They are ordered by
1273  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1274 
1275  <P>Each column description has the following columns:
1276  <OL>
1277  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1278  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1279  <LI><B>TABLE_NAME</B> String => table name
1280  <LI><B>COLUMN_NAME</B> String => column name
1281  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1282  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
1283  for a UDT the type name is fully qualified
1284  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1285  types this is the maximum number of characters, for numeric or
1286  decimal types this is precision.
1287  <LI><B>BUFFER_LENGTH</B> is not used.
1288  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1289  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1290  <LI><B>NULLABLE</B> int => is NULL allowed?
1291  <UL>
1292  <LI> columnNoNulls - might not allow NULL values
1293  <LI> columnNullable - definitely allows NULL values
1294  <LI> columnNullableUnknown - nullability unknown
1295  </UL>
1296  <LI><B>REMARKS</B> String => comment describing column (may be null)
1297  <LI><B>COLUMN_DEF</B> String => default value (may be null)
1298  <LI><B>SQL_DATA_TYPE</B> int => unused
1299  <LI><B>SQL_DATETIME_SUB</B> int => unused
1300  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1301  maximum number of bytes in the column
1302  <LI><B>ORDINAL_POSITION</B> int => index of column in table
1303  (starting at 1)
1304  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1305  does not allow NULL values; "YES" means the column might
1306  allow NULL values. An empty string means nobody knows.
1307  </OL>
1308 
1309  @param catalog a catalog name; "" retrieves those without a
1310  catalog; null means drop catalog name from the selection criteria
1311  @param schemaPattern a schema name pattern; "" retrieves those
1312  without a schema
1313  @param tableNamePattern a table name pattern
1314  @param columnNamePattern a column name pattern
1315  @return <code>ResultSet</code> - each row is a column description
1316  @see #getSearchStringEscape
1317 }
1318 function TZSQLiteDatabaseMetadata.UncachedGetColumns(const Catalog: string;
1319  const SchemaPattern: string; const TableNamePattern: string;
1320  const ColumnNamePattern: string): IZResultSet;
1321 var
1322  Temp: string;
1323  Precision, Decimals: Integer;
1324  Temp_scheme: string;
1325  ResSet: IZResultSet;
1326  TempTableNamePattern: String;
1327 begin
1328  Result:=inherited UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
1329 
1330  if SchemaPattern = '' then
1331  Temp_scheme := '' // OR 'main.'
1332  else
1333  Temp_scheme := SchemaPattern +'.';
1334 
1335  TempTableNamePattern := NormalizePatternCase(TableNamePattern);
1336  ResSet := GetConnection.CreateStatement.ExecuteQuery(
1337  Format('PRAGMA %s table_info(''%s'')', [Temp_scheme, TempTableNamePattern]));
1338  if ResSet <> nil then
1339  with ResSet do
1340  begin
1341  while Next do
1342  begin
1343  Result.MoveToInsertRow;
1344  if SchemaPattern <> '' then
1345  Result.UpdateString(1, SchemaPattern)
1346  else Result.UpdateNull(1);
1347  Result.UpdateNull(2);
1348  Result.UpdateString(3, TempTableNamePattern);
1349  Result.UpdateString(4, GetString(2));
1350  Result.UpdateInt(5, Ord(ConvertSQLiteTypeToSQLType(GetString(3),
1351  Precision, Decimals, ConSettings.CPType)));
1352 
1353  { Defines a table name. }
1354  Temp := UpperCase(GetString(3));
1355  if Pos('(', Temp) > 0 then
1356  Temp := Copy(Temp, 1, Pos('(', Temp) - 1);
1357  Result.UpdateString(6, Temp);
1358 
1359  Result.UpdateInt(7, Precision); //Precision will be converted higher up
1360  Result.UpdateNull(8);
1361  Result.UpdateInt(9, Decimals);
1362  Result.UpdateInt(10, 0);
1363 
1364  if GetInt(4) <> 0 then
1365  begin
1366  Result.UpdateInt(11, Ord(ntNoNulls));
1367  Result.UpdateString(18, 'NO');
1368  end
1369  else
1370  begin
1371  Result.UpdateInt(11, Ord(ntNullable));
1372  Result.UpdateString(18, 'YES');
1373  end;
1374 
1375  Result.UpdateNull(12);
1376  if Trim(GetString(5)) <> '' then
1377  Result.UpdateString(13, GetString(5))
1378  // Result.UpdateString(13, '''' + GetString(5) + '''')
1379  else Result.UpdateNull(13);
1380  Result.UpdateNull(14);
1381  Result.UpdateNull(15);
1382  Result.UpdateNull(16);
1383  Result.UpdateInt(17, GetInt(1) + 1);
1384 
1385  Result.UpdateBooleanByName('AUTO_INCREMENT',
1386  (GetInt(6) = 1) and (Temp = 'INTEGER'));
1387  Result.UpdateBooleanByName('CASE_SENSITIVE', False);
1388  Result.UpdateBooleanByName('SEARCHABLE', True);
1389  Result.UpdateBooleanByName('WRITABLE', True);
1390  Result.UpdateBooleanByName('DEFINITELYWRITABLE', True);
1391  Result.UpdateBooleanByName('READONLY', False);
1392 
1393  Result.InsertRow;
1394  end;
1395  Close;
1396  end;
1397 end;
1398 
1399 {**
1400  Gets a description of a table's primary key columns. They
1401  are ordered by COLUMN_NAME.
1402 
1403  <P>Each primary key column description has the following columns:
1404  <OL>
1405  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1406  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1407  <LI><B>TABLE_NAME</B> String => table name
1408  <LI><B>COLUMN_NAME</B> String => column name
1409  <LI><B>KEY_SEQ</B> short => sequence number within primary key
1410  <LI><B>PK_NAME</B> String => primary key name (may be null)
1411  </OL>
1412 
1413  @param catalog a catalog name; "" retrieves those without a
1414  catalog; null means drop catalog name from the selection criteria
1415  @param schema a schema name; "" retrieves those
1416  without a schema
1417  @param table a table name
1418  @return <code>ResultSet</code> - each row is a primary key column description
1419  @exception SQLException if a database access error occurs
1420 }
1421 function TZSQLiteDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
1422  const Schema: string; const Table: string): IZResultSet;
1423 var
1424  Index: Integer;
1425  Temp_scheme: string;
1426 begin
1427  Result:=inherited UncachedGetPrimaryKeys(Catalog, Schema, Table);
1428 
1429  if Schema = '' then
1430  Temp_scheme := '' // OR 'main.'
1431  else
1432  Temp_scheme := Schema +'.';
1433 
1434  with GetConnection.CreateStatement.ExecuteQuery(
1435  Format('PRAGMA %s table_info(''%s'')', [Temp_scheme,Table])) do
1436  begin
1437  Index := 1;
1438  while Next do
1439  begin
1440  if GetInt(6) = 0 then
1441  Continue;
1442 
1443  Result.MoveToInsertRow;
1444  if Schema <> '' then
1445  Result.UpdateString(1, Schema)
1446  else Result.UpdateNull(1);
1447  Result.UpdateNull(2);
1448  Result.UpdateString(3, Table);
1449  Result.UpdateString(4, GetString(2));
1450  Result.UpdateInt(5, Index);
1451  Result.UpdateNull(6);
1452 
1453  Inc(Index);
1454 
1455  Result.InsertRow;
1456  end;
1457  Close;
1458  end;
1459 end;
1460 
1461 {**
1462  Gets a description of all the standard SQL types supported by
1463  this database. They are ordered by DATA_TYPE and then by how
1464  closely the data type maps to the corresponding JDBC SQL type.
1465 
1466  <P>Each type description has the following columns:
1467  <OL>
1468  <LI><B>TYPE_NAME</B> String => Type name
1469  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
1470  <LI><B>PRECISION</B> int => maximum precision
1471  <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
1472  (may be null)
1473  <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
1474  (may be null)
1475  <LI><B>CREATE_PARAMS</B> String => parameters used in creating
1476  the type (may be null)
1477  <LI><B>NULLABLE</B> short => can you use NULL for this type?
1478  <UL>
1479  <LI> typeNoNulls - does not allow NULL values
1480  <LI> typeNullable - allows NULL values
1481  <LI> typeNullableUnknown - nullability unknown
1482  </UL>
1483  <LI><B>CASE_SENSITIVE</B> Boolean=> is it case sensitive?
1484  <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
1485  <UL>
1486  <LI> typePredNone - No support
1487  <LI> typePredChar - Only supported with WHERE .. LIKE
1488  <LI> typePredBasic - Supported except for WHERE .. LIKE
1489  <LI> typeSearchable - Supported for all WHERE ..
1490  </UL>
1491  <LI><B>UNSIGNED_ATTRIBUTE</B> Boolean => is it unsigned?
1492  <LI><B>FIXED_PREC_SCALE</B> Boolean => can it be a money value?
1493  <LI><B>AUTO_INCREMENT</B> Boolean => can it be used for an
1494  auto-increment value?
1495  <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
1496  (may be null)
1497  <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
1498  <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
1499  <LI><B>SQL_DATA_TYPE</B> int => unused
1500  <LI><B>SQL_DATETIME_SUB</B> int => unused
1501  <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
1502  </OL>
1503 
1504  @return <code>ResultSet</code> - each row is an SQL type description
1505 }
1506 function TZSQLiteDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
1507 const
1508  MaxTypeCount = 22;
1509  TypeNames: array[1..MaxTypeCount] of string = (
1510  'BOOLEAN', 'TINYINT', 'SMALLINT', 'MEDIUMINT', 'INTEGER',
1511  'BIGINT', 'REAL', 'FLOAT', 'NUMERIC', 'DECIMAL', 'NUMBER',
1512  'DOUBLE', 'CHAR', 'VARCHAR', 'BINARY', 'VARBINARY', 'DATE',
1513  'TIME', 'DATETIME', 'TIMESTAMP', 'BLOB', 'TEXT');
1514  TypeCodes: array[1..MaxTypeCount] of TZSQLType = (
1515  stBoolean, stByte, stShort, stInteger, stInteger, stLong,
1516  stFloat, stFloat, stDouble, stDouble, stDouble, stDouble,
1517  stString, {$IFDEF UNICODE}stUnicodeString{$ELSE}stString{$ENDIF},
1518  stBytes, stBytes, stDate, stTime, stTimestamp,
1519  stTimestamp, stBinaryStream, {$IFDEF UNICODE}stUnicodeStream{$ELSE}stAsciiStream{$ENDIF});
1520  TypePrecision: array[1..MaxTypeCount] of Integer = (
1521  -1, 2, 4, 9, 9, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1522  -1, -1, -1, -1, -1);
1523 var
1524  I: Integer;
1525 begin
1526  Result:=inherited UncachedGetTypeInfo;
1527 
1528  for I := 1 to MaxTypeCount do
1529  begin
1530  Result.MoveToInsertRow;
1531 
1532  Result.UpdateString(1, TypeNames[I]);
1533  Result.UpdateInt(2, Ord(TypeCodes[I]));
1534  if TypePrecision[I] >= 0 then
1535  Result.UpdateInt(3, TypePrecision[I])
1536  else Result.UpdateNull(3);
1537  if TypeCodes[I] in [stString, stBytes, stDate, stTime,
1538  stTimeStamp, stBinaryStream, stAsciiStream, stUnicodeString] then
1539  begin
1540  Result.UpdateString(4, '''');
1541  Result.UpdateString(5, '''');
1542  end
1543  else
1544  begin
1545  Result.UpdateNull(4);
1546  Result.UpdateNull(5);
1547  end;
1548  Result.UpdateNull(6);
1549  Result.UpdateInt(7, Ord(ntNullable));
1550  Result.UpdateBoolean(8, False);
1551  Result.UpdateBoolean(9, False);
1552  Result.UpdateBoolean(11, False);
1553  Result.UpdateBoolean(12, False);
1554  Result.UpdateBoolean(12, TypeNames[I] = 'INTEGER');
1555  Result.UpdateNull(13);
1556  Result.UpdateNull(14);
1557  Result.UpdateNull(15);
1558  Result.UpdateNull(16);
1559  Result.UpdateNull(17);
1560  Result.UpdateInt(18, 10);
1561 
1562  Result.InsertRow;
1563  end;
1564 end;
1565 
1566 {**
1567  Gets a description of a table's indices and statistics. They are
1568  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
1569 
1570  <P>Each index column description has the following columns:
1571  <OL>
1572  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1573  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1574  <LI><B>TABLE_NAME</B> String => table name
1575  <LI><B>NON_UNIQUE</B> Boolean => Can index values be non-unique?
1576  false when TYPE is tableIndexStatistic
1577  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
1578  null when TYPE is tableIndexStatistic
1579  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
1580  tableIndexStatistic
1581  <LI><B>TYPE</B> short => index type:
1582  <UL>
1583  <LI> tableIndexStatistic - this identifies table statistics that are
1584  returned in conjuction with a table's index descriptions
1585  <LI> tableIndexClustered - this is a clustered index
1586  <LI> tableIndexHashed - this is a hashed index
1587  <LI> tableIndexOther - this is some other style of index
1588  </UL>
1589  <LI><B>ORDINAL_POSITION</B> short => column sequence number
1590  within index; zero when TYPE is tableIndexStatistic
1591  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
1592  tableIndexStatistic
1593  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
1594  "D" => descending, may be null if sort sequence is not supported;
1595  null when TYPE is tableIndexStatistic
1596  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
1597  this is the number of rows in the table; otherwise, it is the
1598  number of unique values in the index.
1599  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
1600  this is the number of pages used for the table, otherwise it
1601  is the number of pages used for the current index.
1602  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
1603  (may be null)
1604  </OL>
1605 
1606  @param catalog a catalog name; "" retrieves those without a
1607  catalog; null means drop catalog name from the selection criteria
1608  @param schema a schema name; "" retrieves those without a schema
1609  @param table a table name
1610  @param unique when true, return only indices for unique values;
1611  when false, return indices regardless of whether unique or not
1612  @param approximate when true, result is allowed to reflect approximate
1613  or out of data values; when false, results are requested to be
1614  accurate
1615  @return <code>ResultSet</code> - each row is an index column description
1616 }
1617 function TZSQLiteDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
1618  const Schema: string; const Table: string; Unique: Boolean;
1619  Approximate: Boolean): IZResultSet;
1620 var
1621  MainResultSet, ResultSet: IZResultSet;
1622  Temp_scheme: string;
1623 begin
1624  Result:=inherited UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
1625 
1626  if Schema = '' then
1627  Temp_scheme := '' // OR 'main.'
1628  else
1629  Temp_scheme := Schema +'.';
1630 
1631  MainResultSet := GetConnection.CreateStatement.ExecuteQuery(
1632  Format('PRAGMA %s index_list(''%s'')', [Temp_scheme, Table]));
1633  if MainResultSet<>nil then
1634  begin
1635  while MainResultSet.Next do
1636  begin
1637  if (Pos(' autoindex ', String(MainResultSet.GetString(2))) = 0)
1638  and ((Unique = False) or (MainResultSet.GetInt(3) = 0)) then
1639  begin
1640  ResultSet := GetConnection.CreateStatement.ExecuteQuery(
1641  Format('PRAGMA %s index_info(''%s'')', [Temp_scheme,MainResultSet.GetString(2)]));
1642  while ResultSet.Next do
1643  begin
1644  Result.MoveToInsertRow;
1645 
1646  if Schema <> '' then
1647  Result.UpdateString(1, Schema)
1648  else Result.UpdateNull(1);
1649  Result.UpdateNull(2);
1650  Result.UpdateString(3, Table);
1651  Result.UpdateBoolean(4, MainResultSet.GetInt(3) = 0);
1652  Result.UpdateNull(5);
1653  Result.UpdateString(6, MainResultSet.GetString(2));
1654  Result.UpdateNull(7);
1655  Result.UpdateInt(8, ResultSet.GetInt(1) + 1);
1656  Result.UpdateString(9, ResultSet.GetString(3));
1657  Result.UpdateString(10, 'A');
1658  Result.UpdateInt(11, 0);
1659  Result.UpdateInt(12, 0);
1660  Result.UpdateNull(13);
1661 
1662  Result.InsertRow;
1663  end;
1664  ResultSet.Close;
1665  end;
1666  end;
1667  MainResultSet.Close;
1668  end;
1669 end;
1670 
1671 {**
1672  Gets the supported CharacterSets:
1673  @return <code>ResultSet</code> - each row is a CharacterSetName and it's ID
1674 }
1675 type
1676  CodePageRec = record
1677  CP: String;
1678  ID: Integer;
1679  end;
1680 
1681 function TZSQLiteDatabaseMetadata.UncachedGetCharacterSets: IZResultSet; //EgonHugeist
1682 const
1683  Encodings: array[0..3] of CodePageRec =(
1684  (CP: 'UTF-8'; ID: 1),
1685  (CP: 'UTF-16le'; ID: 2),
1686  (CP: 'UTF-16be'; ID: 3),
1687  (CP: 'UTF-16'; ID: 4)
1688  );
1689 var
1690  I: Integer;
1691 begin
1692  { TODO -oEgonHugeist : Correct this please if i'm wrong here!!! }
1693 {Text Encodings
1694 
1695  #define SQLITE_UTF8 1
1696  #define SQLITE_UTF16LE 2
1697  #define SQLITE_UTF16BE 3
1698  #define SQLITE_UTF16 4 /* Use native byte order */
1699  #define SQLITE_ANY 5 /* sqlite3_create_function only */
1700  #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
1701 
1702 These constant define integer codes that represent the various text encodings supported by SQLite.}
1703 
1704  Result:=inherited UncachedGetCharacterSets;
1705 
1706  for i := 0 to high(Encodings) do
1707  begin
1708  Result.MoveToInsertRow;
1709  Result.UpdateString(1, Encodings[i].CP); //CHARACTER_SET_NAME
1710  Result.UpdateShort(2, Encodings[i].ID); //CHARACTER_SET_ID
1711  Result.InsertRow;
1712  end;
1713 end;
1714 
1715 end.