zeoslib  UNKNOWN
 All Files
ZDbcDbLibMetadata.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { MsSql Database metadata information }
5 { }
6 { Originally written by Janos Fegyverneki }
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 ZDbcDbLibMetadata;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 uses
59  Types, Classes, SysUtils, ZSysUtils, ZDbcIntfs, ZDbcMetadata, ZURL,
60  ZCompatibility, ZDbcConnection, ZSelectSchema;
61 
62 type
63 
64  // technobot 2008-06-25 - methods moved as is from TZDbLibBaseDatabaseMetadata:
65  {** Implements MsSql Database Information. }
66  TZDbLibDatabaseInfo = class(TZAbstractDatabaseInfo)
67  public
68 
69  // database/driver/server info:
70  function GetDatabaseProductName: string; override;
71  function GetDatabaseProductVersion: string; override;
72  function GetDriverName: string; override;
73 // function GetDriverVersion: string; override; -> Same as parent
74  function GetDriverMajorVersion: Integer; override;
75  function GetDriverMinorVersion: Integer; override;
76 // function GetServerVersion: string; -> Not implemented
77 
78  // capabilities (what it can/cannot do):
79 // function AllProceduresAreCallable: Boolean; override; -> Not implemented
80 // function AllTablesAreSelectable: Boolean; override; -> Not implemented
81  function SupportsMixedCaseIdentifiers: Boolean; override;
82  function SupportsMixedCaseQuotedIdentifiers: Boolean; override;
83 // function SupportsAlterTableWithAddColumn: Boolean; override; -> Not implemented
84 // function SupportsAlterTableWithDropColumn: Boolean; override; -> Not implemented
85 // function SupportsColumnAliasing: Boolean; override; -> Not implemented
86 // function SupportsConvert: Boolean; override; -> Not implemented
87 // function SupportsConvertForTypes(FromType: TZSQLType; ToType: TZSQLType):
88 // Boolean; override; -> Not implemented
89 // function SupportsTableCorrelationNames: Boolean; override; -> Not implemented
90 // function SupportsDifferentTableCorrelationNames: Boolean; override; -> Not implemented
91  function SupportsExpressionsInOrderBy: Boolean; override;
92  function SupportsOrderByUnrelated: Boolean; override;
93  function SupportsGroupBy: Boolean; override;
94  function SupportsGroupByUnrelated: Boolean; override;
95  function SupportsGroupByBeyondSelect: Boolean; override;
96 // function SupportsLikeEscapeClause: Boolean; override; -> Not implemented
97 // function SupportsMultipleResultSets: Boolean; override; -> Not implemented
98 // function SupportsMultipleTransactions: Boolean; override; -> Not implemented
99 // function SupportsNonNullableColumns: Boolean; override; -> Not implemented
100 // function SupportsMinimumSQLGrammar: Boolean; override; -> Not implemented
101 // function SupportsCoreSQLGrammar: Boolean; override; -> Not implemented
102 // function SupportsExtendedSQLGrammar: Boolean; override; -> Not implemented
103 // function SupportsANSI92EntryLevelSQL: Boolean; override; -> Not implemented
104 // function SupportsANSI92IntermediateSQL: Boolean; override; -> Not implemented
105 // function SupportsANSI92FullSQL: Boolean; override; -> Not implemented
106  function SupportsIntegrityEnhancementFacility: Boolean; override;
107 // function SupportsOuterJoins: Boolean; override; -> Not implemented
108 // function SupportsFullOuterJoins: Boolean; override; -> Not implemented
109 // function SupportsLimitedOuterJoins: Boolean; override; -> Not implemented
110  function SupportsSchemasInDataManipulation: Boolean; override;
111  function SupportsSchemasInProcedureCalls: Boolean; override;
112  function SupportsSchemasInTableDefinitions: Boolean; override;
113  function SupportsSchemasInIndexDefinitions: Boolean; override;
114  function SupportsSchemasInPrivilegeDefinitions: Boolean; override;
115  function SupportsCatalogsInDataManipulation: Boolean; override;
116  function SupportsCatalogsInProcedureCalls: Boolean; override;
117  function SupportsCatalogsInTableDefinitions: Boolean; override;
118  function SupportsCatalogsInIndexDefinitions: Boolean; override;
119  function SupportsCatalogsInPrivilegeDefinitions: Boolean; override;
120  function SupportsPositionedDelete: Boolean; override;
121  function SupportsPositionedUpdate: Boolean; override;
122  function SupportsSelectForUpdate: Boolean; override;
123  function SupportsStoredProcedures: Boolean; override;
124  function SupportsSubqueriesInComparisons: Boolean; override;
125  function SupportsSubqueriesInExists: Boolean; override;
126  function SupportsSubqueriesInIns: Boolean; override;
127  function SupportsSubqueriesInQuantifieds: Boolean; override;
128  function SupportsCorrelatedSubqueries: Boolean; override;
129  function SupportsUnion: Boolean; override;
130  function SupportsUnionAll: Boolean; override;
131  function SupportsOpenCursorsAcrossCommit: Boolean; override;
132  function SupportsOpenCursorsAcrossRollback: Boolean; override;
133  function SupportsOpenStatementsAcrossCommit: Boolean; override;
134  function SupportsOpenStatementsAcrossRollback: Boolean; override;
135  function SupportsTransactions: Boolean; override;
136  function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
137  Boolean; override;
138  function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
139  function SupportsDataManipulationTransactionsOnly: Boolean; override;
140  function SupportsResultSetType(_Type: TZResultSetType): Boolean; override;
141  function SupportsResultSetConcurrency(_Type: TZResultSetType;
142  Concurrency: TZResultSetConcurrency): Boolean; override;
143 // function SupportsBatchUpdates: Boolean; override; -> Not implemented
144 
145  // maxima:
146  function GetMaxBinaryLiteralLength: Integer; override;
147  function GetMaxCharLiteralLength: Integer; override;
148  function GetMaxColumnNameLength: Integer; override;
149  function GetMaxColumnsInGroupBy: Integer; override;
150  function GetMaxColumnsInIndex: Integer; override;
151  function GetMaxColumnsInOrderBy: Integer; override;
152  function GetMaxColumnsInSelect: Integer; override;
153  function GetMaxColumnsInTable: Integer; override;
154  function GetMaxConnections: Integer; override;
155  function GetMaxCursorNameLength: Integer; override;
156  function GetMaxIndexLength: Integer; override;
157  function GetMaxSchemaNameLength: Integer; override;
158  function GetMaxProcedureNameLength: Integer; override;
159  function GetMaxCatalogNameLength: Integer; override;
160  function GetMaxRowSize: Integer; override;
161  function GetMaxStatementLength: Integer; override;
162  function GetMaxStatements: Integer; override;
163  function GetMaxTableNameLength: Integer; override;
164  function GetMaxTablesInSelect: Integer; override;
165  function GetMaxUserNameLength: Integer; override;
166 
167  // policies (how are various data and operations handled):
168 // function IsReadOnly: Boolean; override; -> Not implemented
169 // function IsCatalogAtStart: Boolean; override; -> Not implemented
170  function DoesMaxRowSizeIncludeBlobs: Boolean; override;
171 // function NullsAreSortedHigh: Boolean; override; -> Not implemented
172 // function NullsAreSortedLow: Boolean; override; -> Not implemented
173 // function NullsAreSortedAtStart: Boolean; override; -> Not implemented
174 // function NullsAreSortedAtEnd: Boolean; override; -> Not implemented
175 // function NullPlusNonNullIsNull: Boolean; override; -> Not implemented
176 // function UsesLocalFiles: Boolean; override; -> Not implemented
177  function UsesLocalFilePerTable: Boolean; override;
178  function StoresUpperCaseIdentifiers: Boolean; override;
179  function StoresLowerCaseIdentifiers: Boolean; override;
180  function StoresMixedCaseIdentifiers: Boolean; override;
181  function StoresUpperCaseQuotedIdentifiers: Boolean; override;
182  function StoresLowerCaseQuotedIdentifiers: Boolean; override;
183  function StoresMixedCaseQuotedIdentifiers: Boolean; override;
184  function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
185  function DataDefinitionCausesTransactionCommit: Boolean; override;
186  function DataDefinitionIgnoredInTransactions: Boolean; override;
187 
188  // interface details (terms, keywords, etc):
189  function GetSchemaTerm: string; override;
190  function GetProcedureTerm: string; override;
191  function GetCatalogTerm: string; override;
192  function GetCatalogSeparator: string; override;
193  function GetSQLKeywords: string; override;
194  function GetNumericFunctions: string; override;
195  function GetStringFunctions: string; override;
196  function GetSystemFunctions: string; override;
197  function GetTimeDateFunctions: string; override;
198  function GetSearchStringEscape: string; override;
199  function GetExtraNameCharacters: string; override;
200  end;
201 
202  TZMsSqlDatabaseInfo = class(TZDbLibDatabaseInfo)
203  // database/driver/server info:
204  function GetDatabaseProductName: string; override;
205  function GetDatabaseProductVersion: string; override;
206  function GetDriverName: string; override;
207  end;
208 
209  TZSybaseDatabaseInfo = class(TZDbLibDatabaseInfo)
210  // database/driver/server info:
211  function GetDatabaseProductName: string; override;
212  function GetDatabaseProductVersion: string; override;
213  function GetDriverName: string; override;
214  end;
215 
216  {** Implements DbLib Database Metadata. }
217  TZDbLibBaseDatabaseMetadata = class(TZAbstractDatabaseMetadata)
218  protected
219  function GetSP_Prefix(const Catalog, Schema: String): String;
220  function ComposeObjectString(const S: String; Const NullText: String = 'null';
221  QuoteChar: Char = #39): String;
222  function DecomposeObjectString(const S: String): String; override;
223  function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-25
224 
225  function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
226  const Table: string): IZResultSet; override;
227  function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
228  const Table: string): IZResultSet; override;
229  end;
230 
231  {** Implements MsSql Database Metadata. }
232  TZMsSqlDatabaseMetadata = class(TZDbLibBaseDatabaseMetadata)
233  protected
234  function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-25
235 
236  function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
237  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
238  function UncachedGetSchemas: IZResultSet; override;
239  function UncachedGetCatalogs: IZResultSet; override;
240  function UncachedGetTableTypes: IZResultSet; override;
241  function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
242  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
243  function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
244  const TableNamePattern: string): IZResultSet; override;
245  function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
246  const Table: string; const ColumnNamePattern: string): IZResultSet; override;
247  function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
248  const Table: string): IZResultSet; override;
249  function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
250  const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
251  const ForeignTable: string): IZResultSet; override;
252  function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
253  Unique: Boolean; Approximate: Boolean): IZResultSet; override;
254  function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
255  const ProcedureNamePattern: string): IZResultSet; override;
256  function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
257  const ProcedureNamePattern: string; const ColumnNamePattern: string):
258  IZResultSet; override;
259  function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
260  const Table: string): IZResultSet; override;
261  function UncachedGetTypeInfo: IZResultSet; override;
262  end;
263 
264  {** Implements Sybase Database Metadata. }
265  TZSybaseDatabaseMetadata = class(TZDbLibBaseDatabaseMetadata)
266  protected
267  function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-25
268 
269  function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
270  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
271  function UncachedGetSchemas: IZResultSet; override;
272  function UncachedGetCatalogs: IZResultSet; override;
273  function UncachedGetTableTypes: IZResultSet; override;
274  function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
275  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
276  function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
277  const TableNamePattern: string): IZResultSet; override;
278  function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
279  const Table: string; const ColumnNamePattern: string): IZResultSet; override;
280  function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
281  const Table: string): IZResultSet; override;
282  function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
283  const Table: string): IZResultSet; override;
284  function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
285  const Table: string): IZResultSet; override;
286  function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
287  const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
288  const ForeignTable: string): IZResultSet; override;
289  function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
290  Unique: Boolean; Approximate: Boolean): IZResultSet; override;
291  function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
292  const ProcedureNamePattern: string): IZResultSet; override;
293  function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
294  const ProcedureNamePattern: string; const ColumnNamePattern: string):
295  IZResultSet; override;
296  function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
297  const Table: string): IZResultSet; override;
298  function UncachedGetTypeInfo: IZResultSet; override;
299  function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
300  const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
301  end;
302 
303 implementation
304 
305 uses ZDbcUtils, ZDbcDbLibUtils;
306 
307 { TZDbLibDatabaseInfo }
308 
309 {**
310 //----------------------------------------------------------------------
311 // First, a variety of minor information about the target database.
312 
313 {**
314  What's the name of this database product?
315  @return database product name
316 }
317 function TZDbLibDatabaseInfo.GetDatabaseProductName: string;
318 begin
319  Result := '';
320 end;
321 
322 {**
323  What's the version of this database product?
324  @return database version
325 }
326 function TZDbLibDatabaseInfo.GetDatabaseProductVersion: string;
327 begin
328  Result := '';
329 end;
330 
331 {**
332  What's the name of this JDBC driver?
333  @return JDBC driver name
334 }
335 function TZDbLibDatabaseInfo.GetDriverName: string;
336 begin
337  Result := 'Zeos Abstract Database Connectivity Driver for DbLib Server';
338 end;
339 
340 {**
341  What's this JDBC driver's major version number?
342  @return JDBC driver major version
343 }
344 function TZDbLibDatabaseInfo.GetDriverMajorVersion: Integer;
345 begin
346  Result := 1;
347 end;
348 
349 {**
350  What's this JDBC driver's minor version number?
351  @return JDBC driver minor version number
352 }
353 function TZDbLibDatabaseInfo.GetDriverMinorVersion: Integer;
354 begin
355  Result := 0;
356 end;
357 
358 {**
359  Does the database use a file for each table?
360  @return true if the database uses a local file for each table
361 }
362 function TZDbLibDatabaseInfo.UsesLocalFilePerTable: Boolean;
363 begin
364  Result := False;
365 end;
366 
367 {**
368  Does the database treat mixed case unquoted SQL identifiers as
369  case sensitive and as a result store them in mixed case?
370  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will
371  always return false.
372  @return <code>true</code> if so; <code>false</code> otherwise
373 }
374 function TZDbLibDatabaseInfo.SupportsMixedCaseIdentifiers: Boolean;
375 begin
376  Result := False;
377 end;
378 
379 {**
380  Does the database treat mixed case unquoted SQL identifiers as
381  case insensitive and store them in upper case?
382  @return <code>true</code> if so; <code>false</code> otherwise
383 }
384 function TZDbLibDatabaseInfo.StoresUpperCaseIdentifiers: Boolean;
385 begin
386  Result := True;
387 end;
388 
389 {**
390  Does the database treat mixed case unquoted SQL identifiers as
391  case insensitive and store them in lower case?
392  @return <code>true</code> if so; <code>false</code> otherwise
393 }
394 function TZDbLibDatabaseInfo.StoresLowerCaseIdentifiers: Boolean;
395 begin
396  Result := True;
397 end;
398 
399 {**
400  Does the database treat mixed case unquoted SQL identifiers as
401  case insensitive and store them in mixed case?
402  @return <code>true</code> if so; <code>false</code> otherwise
403 }
404 function TZDbLibDatabaseInfo.StoresMixedCaseIdentifiers: Boolean;
405 begin
406  Result := True;
407 end;
408 
409 {**
410  Does the database treat mixed case quoted SQL identifiers as
411  case sensitive and as a result store them in mixed case?
412  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
413  @return <code>true</code> if so; <code>false</code> otherwise
414 }
415 function TZDbLibDatabaseInfo.SupportsMixedCaseQuotedIdentifiers: Boolean;
416 begin
417  Result := True;
418 end;
419 
420 {**
421  Does the database treat mixed case quoted SQL identifiers as
422  case insensitive and store them in upper case?
423  @return <code>true</code> if so; <code>false</code> otherwise
424 }
425 function TZDbLibDatabaseInfo.StoresUpperCaseQuotedIdentifiers: Boolean;
426 begin
427  Result := True;
428 end;
429 
430 {**
431  Does the database treat mixed case quoted SQL identifiers as
432  case insensitive and store them in lower case?
433  @return <code>true</code> if so; <code>false</code> otherwise
434 }
435 function TZDbLibDatabaseInfo.StoresLowerCaseQuotedIdentifiers: Boolean;
436 begin
437  Result := True;
438 end;
439 
440 {**
441  Does the database treat mixed case quoted SQL identifiers as
442  case insensitive and store them in mixed case?
443  @return <code>true</code> if so; <code>false</code> otherwise
444 }
445 function TZDbLibDatabaseInfo.StoresMixedCaseQuotedIdentifiers: Boolean;
446 begin
447  Result := True;
448 end;
449 
450 {**
451  Gets a comma-separated list of all a database's SQL keywords
452  that are NOT also SQL92 keywords.
453  @return the list
454 }
455 function TZDbLibDatabaseInfo.GetSQLKeywords: string;
456 begin
457  { TODO -ofjanos -cAPI : SQL Keywords that are not SQL92 compliant }
458  Result := '';
459 end;
460 
461 {**
462  Gets a comma-separated list of math functions. These are the
463  X/Open CLI math function names used in the JDBC function escape
464  clause.
465  @return the list
466 }
467 function TZDbLibDatabaseInfo.GetNumericFunctions: string;
468 begin
469  Result := 'ABS,ACOS,ASIN,ATAN,ATN2,CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,'+
470  'PI,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQUARE,SQRT,TAN';
471 end;
472 
473 {**
474  Gets a comma-separated list of string functions. These are the
475  X/Open CLI string function names used in the JDBC function escape
476  clause.
477  @return the list
478 }
479 function TZDbLibDatabaseInfo.GetStringFunctions: string;
480 begin
481  Result := 'ASCII,CHAR,CHARINDEX,DIFFERENCE,LEFT,LEN,LOWER,LTRIM,NCHAR,PATINDEX,'+
482  'REPLACE,QUOTENAME,REPLICATE,REVERSE,RIGHT,RTRIM,SOUNDEX,SPACE,STR,'+
483  'STUFF,SUBSTRING,UNICODE,UPPER';
484 end;
485 
486 {**
487  Gets a comma-separated list of system functions. These are the
488  X/Open CLI system function names used in the JDBC function escape
489  clause.
490  @return the list
491 }
492 function TZDbLibDatabaseInfo.GetSystemFunctions: string;
493 begin
494  Result := 'APP_NAME,CASE,CAST,CONVERT,COALESCE,CURRENT_TIMESTAMP,CURRENT_USER,'+
495  'DATALENGTH,@@ERROR,FORMATMESSAGE,GETANSINULL,HOST_ID,HOST_NAME,'+
496  'IDENT_INCR,IDENT_SEED,@@IDENTITY,IDENTITY,ISDATE,ISNULL,ISNUMERIC,'+
497  'NEWID,NULLIF,PARSENAME,PERMISSIONS,@@ROWCOUNT,SESSION_USER,STATS_DATE,'+
498  'SYSTEM_USER,@@TRANCOUNT,USER_NAME';
499 end;
500 
501 {**
502  Gets a comma-separated list of time and date functions.
503  @return the list
504 }
505 function TZDbLibDatabaseInfo.GetTimeDateFunctions: string;
506 begin
507  Result := 'DATEADD,DATEDIFF,DATENAME,DATEPART,DAY,GETDATE,MONTH,YEAR';
508 end;
509 
510 {**
511  Gets the string that can be used to escape wildcard characters.
512  This is the string that can be used to escape '_' or '%' in
513  the string pattern style catalog search parameters.
514 
515  <P>The '_' character represents any single character.
516  <P>The '%' character represents any sequence of zero or
517  more characters.
518 
519  @return the string used to escape wildcard characters
520 }
521 function TZDbLibDatabaseInfo.GetSearchStringEscape: string;
522 begin
523 { TODO -ofjanos -cgeneral :
524 In sql server this must be specified as the parameter of like.
525 example: WHERE ColumnA LIKE '%5/%%' ESCAPE '/' }
526  Result := '/';
527 end;
528 
529 {**
530  Gets all the "extra" characters that can be used in unquoted
531  identifier names (those beyond a-z, A-Z, 0-9 and _).
532  @return the string containing the extra characters
533 }
534 function TZDbLibDatabaseInfo.GetExtraNameCharacters: string;
535 begin
536  Result := '@$#';
537 end;
538 
539 //--------------------------------------------------------------------
540 // Functions describing which features are supported.
541 
542 {**
543  Are expressions in "ORDER BY" lists supported?
544  @return <code>true</code> if so; <code>false</code> otherwise
545 }
546 function TZDbLibDatabaseInfo.SupportsExpressionsInOrderBy: Boolean;
547 begin
548  Result := True;
549 end;
550 
551 {**
552  Can an "ORDER BY" clause use columns not in the SELECT statement?
553  @return <code>true</code> if so; <code>false</code> otherwise
554 }
555 function TZDbLibDatabaseInfo.SupportsOrderByUnrelated: Boolean;
556 begin
557  Result := True;
558 end;
559 
560 {**
561  Is some form of "GROUP BY" clause supported?
562  @return <code>true</code> if so; <code>false</code> otherwise
563 }
564 function TZDbLibDatabaseInfo.SupportsGroupBy: Boolean;
565 begin
566  Result := True;
567 end;
568 
569 {**
570  Can a "GROUP BY" clause use columns not in the SELECT?
571  @return <code>true</code> if so; <code>false</code> otherwise
572 }
573 function TZDbLibDatabaseInfo.SupportsGroupByUnrelated: Boolean;
574 begin
575  Result := True;
576 end;
577 
578 {**
579  Can a "GROUP BY" clause add columns not in the SELECT
580  provided it specifies all the columns in the SELECT?
581  @return <code>true</code> if so; <code>false</code> otherwise
582 }
583 function TZDbLibDatabaseInfo.SupportsGroupByBeyondSelect: Boolean;
584 begin
585  Result := True;
586 end;
587 
588 {**
589  Is the SQL Integrity Enhancement Facility supported?
590  @return <code>true</code> if so; <code>false</code> otherwise
591 }
592 function TZDbLibDatabaseInfo.SupportsIntegrityEnhancementFacility: Boolean;
593 begin
594  Result := False;
595 end;
596 
597 {**
598  What's the database vendor's preferred term for "schema"?
599  @return the vendor term
600 }
601 function TZDbLibDatabaseInfo.GetSchemaTerm: string;
602 begin
603  Result := 'owner';
604 end;
605 
606 {**
607  What's the database vendor's preferred term for "procedure"?
608  @return the vendor term
609 }
610 function TZDbLibDatabaseInfo.GetProcedureTerm: string;
611 begin
612  Result := 'procedure';
613 end;
614 
615 {**
616  What's the database vendor's preferred term for "catalog"?
617  @return the vendor term
618 }
619 function TZDbLibDatabaseInfo.GetCatalogTerm: string;
620 begin
621  Result := 'database';
622 end;
623 
624 {**
625  What's the separator between catalog and table name?
626  @return the separator string
627 }
628 function TZDbLibDatabaseInfo.GetCatalogSeparator: string;
629 begin
630  Result := '.';
631 end;
632 
633 {**
634  Can a schema name be used in a data manipulation statement?
635  @return <code>true</code> if so; <code>false</code> otherwise
636 }
637 function TZDbLibDatabaseInfo.SupportsSchemasInDataManipulation: Boolean;
638 begin
639  Result := True;
640 end;
641 
642 {**
643  Can a schema name be used in a procedure call statement?
644  @return <code>true</code> if so; <code>false</code> otherwise
645 }
646 function TZDbLibDatabaseInfo.SupportsSchemasInProcedureCalls: Boolean;
647 begin
648  Result := True;
649 end;
650 
651 {**
652  Can a schema name be used in a table definition statement?
653  @return <code>true</code> if so; <code>false</code> otherwise
654 }
655 function TZDbLibDatabaseInfo.SupportsSchemasInTableDefinitions: Boolean;
656 begin
657  Result := True;
658 end;
659 
660 {**
661  Can a schema name be used in an index definition statement?
662  @return <code>true</code> if so; <code>false</code> otherwise
663 }
664 function TZDbLibDatabaseInfo.SupportsSchemasInIndexDefinitions: Boolean;
665 begin
666  Result := True;
667 end;
668 
669 {**
670  Can a schema name be used in a privilege definition statement?
671  @return <code>true</code> if so; <code>false</code> otherwise
672 }
673 function TZDbLibDatabaseInfo.SupportsSchemasInPrivilegeDefinitions: Boolean;
674 begin
675  Result := True;
676 end;
677 
678 {**
679  Can a catalog name be used in a data manipulation statement?
680  @return <code>true</code> if so; <code>false</code> otherwise
681 }
682 function TZDbLibDatabaseInfo.SupportsCatalogsInDataManipulation: Boolean;
683 begin
684  Result := True;
685 end;
686 
687 {**
688  Can a catalog name be used in a procedure call statement?
689  @return <code>true</code> if so; <code>false</code> otherwise
690 }
691 function TZDbLibDatabaseInfo.SupportsCatalogsInProcedureCalls: Boolean;
692 begin
693  Result := True;
694 end;
695 
696 {**
697  Can a catalog name be used in a table definition statement?
698  @return <code>true</code> if so; <code>false</code> otherwise
699 }
700 function TZDbLibDatabaseInfo.SupportsCatalogsInTableDefinitions: Boolean;
701 begin
702  Result := True;
703 end;
704 
705 {**
706  Can a catalog name be used in an index definition statement?
707  @return <code>true</code> if so; <code>false</code> otherwise
708 }
709 function TZDbLibDatabaseInfo.SupportsCatalogsInIndexDefinitions: Boolean;
710 begin
711  Result := True;
712 end;
713 
714 {**
715  Can a catalog name be used in a privilege definition statement?
716  @return <code>true</code> if so; <code>false</code> otherwise
717 }
718 function TZDbLibDatabaseInfo.SupportsCatalogsInPrivilegeDefinitions: Boolean;
719 begin
720  Result := True;
721 end;
722 
723 {**
724  Is positioned DELETE supported?
725  @return <code>true</code> if so; <code>false</code> otherwise
726 }
727 function TZDbLibDatabaseInfo.SupportsPositionedDelete: Boolean;
728 begin
729 //CURRENT OF
730 //Specifies that the DELETE is done at the current position of the specified cursor.
731  Result := True;
732 end;
733 
734 {**
735  Is positioned UPDATE supported?
736  @return <code>true</code> if so; <code>false</code> otherwise
737 }
738 function TZDbLibDatabaseInfo.SupportsPositionedUpdate: Boolean;
739 begin
740  Result := True;
741 end;
742 
743 {**
744  Is SELECT for UPDATE supported?
745  @return <code>true</code> if so; <code>false</code> otherwise
746 }
747 function TZDbLibDatabaseInfo.SupportsSelectForUpdate: Boolean;
748 begin
749  Result := True;
750 end;
751 
752 {**
753  Are stored procedure calls using the stored procedure escape
754  syntax supported?
755  @return <code>true</code> if so; <code>false</code> otherwise
756 }
757 function TZDbLibDatabaseInfo.SupportsStoredProcedures: Boolean;
758 begin
759  Result := True;
760 end;
761 
762 {**
763  Are subqueries in comparison expressions supported?
764  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
765  @return <code>true</code> if so; <code>false</code> otherwise
766 }
767 function TZDbLibDatabaseInfo.SupportsSubqueriesInComparisons: Boolean;
768 begin
769  Result := True;
770 end;
771 
772 {**
773  Are subqueries in 'exists' expressions supported?
774  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
775  @return <code>true</code> if so; <code>false</code> otherwise
776 }
777 function TZDbLibDatabaseInfo.SupportsSubqueriesInExists: Boolean;
778 begin
779  Result := True;
780 end;
781 
782 {**
783  Are subqueries in 'in' statements supported?
784  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
785  @return <code>true</code> if so; <code>false</code> otherwise
786 }
787 function TZDbLibDatabaseInfo.SupportsSubqueriesInIns: Boolean;
788 begin
789  Result := True;
790 end;
791 
792 {**
793  Are subqueries in quantified expressions supported?
794  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
795  @return <code>true</code> if so; <code>false</code> otherwise
796 }
797 function TZDbLibDatabaseInfo.SupportsSubqueriesInQuantifieds: Boolean;
798 begin
799  Result := True;
800 end;
801 
802 {**
803  Are correlated subqueries supported?
804  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
805  @return <code>true</code> if so; <code>false</code> otherwise
806 }
807 function TZDbLibDatabaseInfo.SupportsCorrelatedSubqueries: Boolean;
808 begin
809  Result := True;
810 end;
811 
812 {**
813  Is SQL UNION supported?
814  @return <code>true</code> if so; <code>false</code> otherwise
815 }
816 function TZDbLibDatabaseInfo.SupportsUnion: Boolean;
817 begin
818  Result := True;
819 end;
820 
821 {**
822  Is SQL UNION ALL supported?
823  @return <code>true</code> if so; <code>false</code> otherwise
824 }
825 function TZDbLibDatabaseInfo.SupportsUnionAll: Boolean;
826 begin
827  Result := True;
828 end;
829 
830 {**
831  Can cursors remain open across commits?
832  @return <code>true</code> if cursors always remain open;
833  <code>false</code> if they might not remain open
834 }
835 function TZDbLibDatabaseInfo.SupportsOpenCursorsAcrossCommit: Boolean;
836 begin
837  Result := True;
838 end;
839 
840 {**
841  Can cursors remain open across rollbacks?
842  @return <code>true</code> if cursors always remain open;
843  <code>false</code> if they might not remain open
844 }
845 function TZDbLibDatabaseInfo.SupportsOpenCursorsAcrossRollback: Boolean;
846 begin
847  Result := True;
848 end;
849 
850 {**
851  Can statements remain open across commits?
852  @return <code>true</code> if statements always remain open;
853  <code>false</code> if they might not remain open
854 }
855 function TZDbLibDatabaseInfo.SupportsOpenStatementsAcrossCommit: Boolean;
856 begin
857  Result := False;
858 end;
859 
860 {**
861  Can statements remain open across rollbacks?
862  @return <code>true</code> if statements always remain open;
863  <code>false</code> if they might not remain open
864 }
865 function TZDbLibDatabaseInfo.SupportsOpenStatementsAcrossRollback: Boolean;
866 begin
867  Result := False;
868 end;
869 
870 //----------------------------------------------------------------------
871 // The following group of methods exposes various limitations
872 // based on the target database with the current driver.
873 // Unless otherwise specified, a result of zero means there is no
874 // limit, or the limit is not known.
875 
876 {**
877  How many hex characters can you have in an inline binary literal?
878  @return max binary literal length in hex characters;
879  a result of zero means that there is no limit or the limit is not known
880 }
881 function TZDbLibDatabaseInfo.GetMaxBinaryLiteralLength: Integer;
882 begin
883  Result := 16000;
884 end;
885 
886 {**
887  What's the max length for a character literal?
888  @return max literal length;
889  a result of zero means that there is no limit or the limit is not known
890 }
891 function TZDbLibDatabaseInfo.GetMaxCharLiteralLength: Integer;
892 begin
893  Result := 8000;
894 end;
895 
896 {**
897  What's the limit on column name length?
898  @return max column name length;
899  a result of zero means that there is no limit or the limit is not known
900 }
901 function TZDbLibDatabaseInfo.GetMaxColumnNameLength: Integer;
902 begin
903  Result := 128;
904 end;
905 
906 {**
907  What's the maximum number of columns in a "GROUP BY" clause?
908  @return max number of columns;
909  a result of zero means that there is no limit or the limit is not known
910 }
911 function TZDbLibDatabaseInfo.GetMaxColumnsInGroupBy: Integer;
912 begin
913  Result := 0;
914 end;
915 
916 {**
917  What's the maximum number of columns allowed in an index?
918  @return max number of columns;
919  a result of zero means that there is no limit or the limit is not known
920 }
921 function TZDbLibDatabaseInfo.GetMaxColumnsInIndex: Integer;
922 begin
923  Result := 16;
924 end;
925 
926 {**
927  What's the maximum number of columns in an "ORDER BY" clause?
928  @return max number of columns;
929  a result of zero means that there is no limit or the limit is not known
930 }
931 function TZDbLibDatabaseInfo.GetMaxColumnsInOrderBy: Integer;
932 begin
933  Result := 0;
934 end;
935 
936 {**
937  What's the maximum number of columns in a "SELECT" list?
938  @return max number of columns;
939  a result of zero means that there is no limit or the limit is not known
940 }
941 function TZDbLibDatabaseInfo.GetMaxColumnsInSelect: Integer;
942 begin
943  Result := 4096;
944 end;
945 
946 {**
947  What's the maximum number of columns in a table?
948  @return max number of columns;
949  a result of zero means that there is no limit or the limit is not known
950 }
951 function TZDbLibDatabaseInfo.GetMaxColumnsInTable: Integer;
952 begin
953  Result := 1024;
954 end;
955 
956 {**
957  How many active connections can we have at a time to this database?
958  @return max number of active connections;
959  a result of zero means that there is no limit or the limit is not known
960 }
961 function TZDbLibDatabaseInfo.GetMaxConnections: Integer;
962 begin
963  Result := 0;
964 end;
965 
966 {**
967  What's the maximum cursor name length?
968  @return max cursor name length in bytes;
969  a result of zero means that there is no limit or the limit is not known
970 }
971 function TZDbLibDatabaseInfo.GetMaxCursorNameLength: Integer;
972 begin
973  Result := 128;
974 end;
975 
976 {**
977  Retrieves the maximum number of bytes for an index, including all
978  of the parts of the index.
979  @return max index length in bytes, which includes the composite of all
980  the constituent parts of the index;
981  a result of zero means that there is no limit or the limit is not known
982 }
983 function TZDbLibDatabaseInfo.GetMaxIndexLength: Integer;
984 begin
985  Result := 900;
986 end;
987 
988 {**
989  What's the maximum length allowed for a schema name?
990  @return max name length in bytes;
991  a result of zero means that there is no limit or the limit is not known
992 }
993 function TZDbLibDatabaseInfo.GetMaxSchemaNameLength: Integer;
994 begin
995  Result := 128;
996 end;
997 
998 {**
999  What's the maximum length of a procedure 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 TZDbLibDatabaseInfo.GetMaxProcedureNameLength: Integer;
1004 begin
1005  Result := 128;
1006 end;
1007 
1008 {**
1009  What's the maximum length of a catalog name?
1010  @return max name length in bytes;
1011  a result of zero means that there is no limit or the limit is not known
1012 }
1013 function TZDbLibDatabaseInfo.GetMaxCatalogNameLength: Integer;
1014 begin
1015  Result := 128;
1016 end;
1017 
1018 {**
1019  What's the maximum length of a single row?
1020  @return max row size in bytes;
1021  a result of zero means that there is no limit or the limit is not known
1022 }
1023 function TZDbLibDatabaseInfo.GetMaxRowSize: Integer;
1024 begin
1025  Result := 8060;
1026 end;
1027 
1028 {**
1029  Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
1030  blobs?
1031  @return <code>true</code> if so; <code>false</code> otherwise
1032 }
1033 function TZDbLibDatabaseInfo.DoesMaxRowSizeIncludeBlobs: Boolean;
1034 begin
1035  Result := False;
1036 end;
1037 
1038 {**
1039  What's the maximum length of an SQL statement?
1040  @return max length in bytes;
1041  a result of zero means that there is no limit or the limit is not known
1042 }
1043 function TZDbLibDatabaseInfo.GetMaxStatementLength: Integer;
1044 begin
1045  Result := 0;
1046 end;
1047 
1048 {**
1049  How many active statements can we have open at one time to this
1050  database?
1051  @return the maximum number of statements that can be open at one time;
1052  a result of zero means that there is no limit or the limit is not known
1053 }
1054 function TZDbLibDatabaseInfo.GetMaxStatements: Integer;
1055 begin
1056  Result := 0;
1057 end;
1058 
1059 {**
1060  What's the maximum length of a table name?
1061  @return max name length in bytes;
1062  a result of zero means that there is no limit or the limit is not known
1063 }
1064 function TZDbLibDatabaseInfo.GetMaxTableNameLength: Integer;
1065 begin
1066  Result := 128;
1067 end;
1068 
1069 {**
1070  What's the maximum number of tables in a SELECT statement?
1071  @return the maximum number of tables allowed in a SELECT statement;
1072  a result of zero means that there is no limit or the limit is not known
1073 }
1074 function TZDbLibDatabaseInfo.GetMaxTablesInSelect: Integer;
1075 begin
1076  Result := 256;
1077 end;
1078 
1079 {**
1080  What's the maximum length of a user name?
1081  @return max user name length in bytes;
1082  a result of zero means that there is no limit or the limit is not known
1083 }
1084 function TZDbLibDatabaseInfo.GetMaxUserNameLength: Integer;
1085 begin
1086  Result := 128;
1087 end;
1088 
1089 //----------------------------------------------------------------------
1090 
1091 {**
1092  What's the database's default transaction isolation level? The
1093  values are defined in <code>java.sql.Connection</code>.
1094  @return the default isolation level
1095  @see Connection
1096 }
1097 function TZDbLibDatabaseInfo.GetDefaultTransactionIsolation:
1098  TZTransactIsolationLevel;
1099 begin
1100  Result := tiReadCommitted;
1101 end;
1102 
1103 {**
1104  Are transactions supported? If not, invoking the method
1105  <code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
1106  @return <code>true</code> if transactions are supported; <code>false</code> otherwise
1107 }
1108 function TZDbLibDatabaseInfo.SupportsTransactions: Boolean;
1109 begin
1110  Result := True;
1111 end;
1112 
1113 {**
1114  Does this database support the given transaction isolation level?
1115  @param level the values are defined in <code>java.sql.Connection</code>
1116  @return <code>true</code> if so; <code>false</code> otherwise
1117  @see Connection
1118 }
1119 function TZDbLibDatabaseInfo.SupportsTransactionIsolationLevel(
1120  Level: TZTransactIsolationLevel): Boolean;
1121 begin
1122  Result := True;
1123 end;
1124 
1125 {**
1126  Are both data definition and data manipulation statements
1127  within a transaction supported?
1128  @return <code>true</code> if so; <code>false</code> otherwise
1129 }
1130 function TZDbLibDatabaseInfo.
1131  SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
1132 begin
1133  Result := True;
1134 end;
1135 
1136 {**
1137  Are only data manipulation statements within a transaction
1138  supported?
1139  @return <code>true</code> if so; <code>false</code> otherwise
1140 }
1141 function TZDbLibDatabaseInfo.
1142  SupportsDataManipulationTransactionsOnly: Boolean;
1143 begin
1144  Result := False;
1145 end;
1146 
1147 {**
1148  Does a data definition statement within a transaction force the
1149  transaction to commit?
1150  @return <code>true</code> if so; <code>false</code> otherwise
1151 }
1152 function TZDbLibDatabaseInfo.DataDefinitionCausesTransactionCommit: Boolean;
1153 begin
1154  Result := False;
1155 end;
1156 
1157 {**
1158  Is a data definition statement within a transaction ignored?
1159  @return <code>true</code> if so; <code>false</code> otherwise
1160 }
1161 function TZDbLibDatabaseInfo.DataDefinitionIgnoredInTransactions: Boolean;
1162 begin
1163  Result := False;
1164 end;
1165 
1166 {**
1167  Does the database support the given result set type?
1168  @param type defined in <code>java.sql.ResultSet</code>
1169  @return <code>true</code> if so; <code>false</code> otherwise
1170 }
1171 function TZDbLibDatabaseInfo.SupportsResultSetType(
1172  _Type: TZResultSetType): Boolean;
1173 begin
1174  Result := True;
1175 end;
1176 
1177 {**
1178  Does the database support the concurrency type in combination
1179  with the given result set type?
1180 
1181  @param type defined in <code>java.sql.ResultSet</code>
1182  @param concurrency type defined in <code>java.sql.ResultSet</code>
1183  @return <code>true</code> if so; <code>false</code> otherwise
1184 }
1185 function TZDbLibDatabaseInfo.SupportsResultSetConcurrency(
1186  _Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
1187 begin
1188  Result := True;
1189 end;
1190 
1191 
1192 { TZDbLibBaseDatabaseMetadata }
1193 
1194 function TZDbLibBaseDatabaseMetadata.GetSP_Prefix(const Catalog, Schema: String): String;
1195 begin
1196  if (UpperCase(Catalog) = 'INFORMATION_SCHEMA') or
1197  (UpperCase(Schema) = 'INFORMATION_SCHEMA') then
1198  Result := ''
1199  else
1200  Result := Catalog+'.'+Schema+'.';
1201 end;
1202 
1203 {**
1204  Composes a object name, AnsiQuotedStr or NullText
1205  @param S the object string
1206  @param NullText the "NULL"-Text default: 'null'
1207  @param QuoteChar the QuoteChar default: '
1208  @return 'null' if S is '' or S if s is already Quoted or AnsiQuotedStr(S, #39)
1209 }
1210 function TZDbLibBaseDatabaseMetadata.ComposeObjectString(const S: String;
1211  Const NullText: String = 'null'; QuoteChar: Char = #39): String;
1212 begin
1213  if S = '' then
1214  Result := NullText
1215  else
1216  if IC.IsQuoted(s) then
1217  Result := S
1218  else
1219  Result := AnsiQuotedStr(S, QuoteChar);
1220 end;
1221 
1222 {**
1223  Decomposes a object name, AnsiQuotedStr or NullText
1224  @param S the object string
1225  @return 'null' if S is '' or S if s is already Quoted or AnsiQuotedStr(S, #39)
1226 }
1227 function TZDbLibBaseDatabaseMetadata.DecomposeObjectString(const S: String): String;
1228 begin
1229  if S = '' then
1230  Result := 'null'
1231  else
1232  begin
1233  if IC.IsQuoted(s) then
1234  Result := IC.ExtractQuote(s)
1235  else
1236  Result := S;
1237  Result := AnsiQuotedStr(Result, #39);
1238  end;
1239 end;
1240 {**
1241  Constructs a database information object and returns the interface to it. Used
1242  internally by the constructor.
1243  @return the database information object interface
1244 }
1245 function TZDbLibBaseDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
1246 begin
1247  Result := TZDbLibDatabaseInfo.Create(Self);
1248 end;
1249 
1250 {**
1251  Gets a description of the primary key columns that are
1252  referenced by a table's foreign key columns (the primary keys
1253  imported by a table). They are ordered by PKTABLE_CAT,
1254  PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
1255 
1256  <P>Each primary key column description has the following columns:
1257  <OL>
1258  <LI><B>PKTABLE_CAT</B> String => primary key table catalog
1259  being imported (may be null)
1260  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
1261  being imported (may be null)
1262  <LI><B>PKTABLE_NAME</B> String => primary key table name
1263  being imported
1264  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
1265  being imported
1266  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
1267  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
1268  <LI><B>FKTABLE_NAME</B> String => foreign key table name
1269  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
1270  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
1271  <LI><B>UPDATE_RULE</B> short => What happens to
1272  foreign key when primary is updated:
1273  <UL>
1274  <LI> importedNoAction - do not allow update of primary
1275  key if it has been imported
1276  <LI> importedKeyCascade - change imported key to agree
1277  with primary key update
1278  <LI> importedKeySetNull - change imported key to NULL if
1279  its primary key has been updated
1280  <LI> importedKeySetDefault - change imported key to default values
1281  if its primary key has been updated
1282  <LI> importedKeyRestrict - same as importedKeyNoAction
1283  (for ODBC 2.x compatibility)
1284  </UL>
1285  <LI><B>DELETE_RULE</B> short => What happens to
1286  the foreign key when primary is deleted.
1287  <UL>
1288  <LI> importedKeyNoAction - do not allow delete of primary
1289  key if it has been imported
1290  <LI> importedKeyCascade - delete rows that import a deleted key
1291  <LI> importedKeySetNull - change imported key to NULL if
1292  its primary key has been deleted
1293  <LI> importedKeyRestrict - same as importedKeyNoAction
1294  (for ODBC 2.x compatibility)
1295  <LI> importedKeySetDefault - change imported key to default if
1296  its primary key has been deleted
1297  </UL>
1298  <LI><B>FK_NAME</B> String => foreign key name (may be null)
1299  <LI><B>PK_NAME</B> String => primary key name (may be null)
1300  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
1301  constraints be deferred until commit
1302  <UL>
1303  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
1304  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
1305  <LI> importedKeyNotDeferrable - see SQL92 for definition
1306  </UL>
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 schema a schema name; "" retrieves those
1312  without a schema
1313  @param table a table name
1314  @return <code>ResultSet</code> - each row is a primary key column description
1315  @see #getExportedKeys
1316 }
1317 function TZDbLibBaseDatabaseMetadata.UncachedGetImportedKeys(const Catalog: string;
1318  const Schema: string; const Table: string): IZResultSet;
1319 begin
1320  Result := UncachedGetCrossReference('', '', '', Catalog, Schema, Table);
1321 end;
1322 
1323 {**
1324  Gets a description of the foreign key columns that reference a
1325  table's primary key columns (the foreign keys exported by a
1326  table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
1327  FKTABLE_NAME, and KEY_SEQ.
1328 
1329  <P>Each foreign key column description has the following columns:
1330  <OL>
1331  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
1332  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
1333  <LI><B>PKTABLE_NAME</B> String => primary key table name
1334  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
1335  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
1336  being exported (may be null)
1337  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
1338  being exported (may be null)
1339  <LI><B>FKTABLE_NAME</B> String => foreign key table name
1340  being exported
1341  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
1342  being exported
1343  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
1344  <LI><B>UPDATE_RULE</B> short => What happens to
1345  foreign key when primary is updated:
1346  <UL>
1347  <LI> importedNoAction - do not allow update of primary
1348  key if it has been imported
1349  <LI> importedKeyCascade - change imported key to agree
1350  with primary key update
1351  <LI> importedKeySetNull - change imported key to NULL if
1352  its primary key has been updated
1353  <LI> importedKeySetDefault - change imported key to default values
1354  if its primary key has been updated
1355  <LI> importedKeyRestrict - same as importedKeyNoAction
1356  (for ODBC 2.x compatibility)
1357  </UL>
1358  <LI><B>DELETE_RULE</B> short => What happens to
1359  the foreign key when primary is deleted.
1360  <UL>
1361  <LI> importedKeyNoAction - do not allow delete of primary
1362  key if it has been imported
1363  <LI> importedKeyCascade - delete rows that import a deleted key
1364  <LI> importedKeySetNull - change imported key to NULL if
1365  its primary key has been deleted
1366  <LI> importedKeyRestrict - same as importedKeyNoAction
1367  (for ODBC 2.x compatibility)
1368  <LI> importedKeySetDefault - change imported key to default if
1369  its primary key has been deleted
1370  </UL>
1371  <LI><B>FK_NAME</B> String => foreign key name (may be null)
1372  <LI><B>PK_NAME</B> String => primary key name (may be null)
1373  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
1374  constraints be deferred until commit
1375  <UL>
1376  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
1377  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
1378  <LI> importedKeyNotDeferrable - see SQL92 for definition
1379  </UL>
1380  </OL>
1381 
1382  @param catalog a catalog name; "" retrieves those without a
1383  catalog; null means drop catalog name from the selection criteria
1384  @param schema a schema name; "" retrieves those
1385  without a schema
1386  @param table a table name
1387  @return <code>ResultSet</code> - each row is a foreign key column description
1388  @see #getImportedKeys
1389 }
1390 function TZDbLibBaseDatabaseMetadata.UncachedGetExportedKeys(const Catalog: string;
1391  const Schema: string; const Table: string): IZResultSet;
1392 begin
1393  Result := UncachedGetCrossReference(Catalog, Schema, Table, '', '', '');
1394 end;
1395 
1396 {**
1397  What's the name of this database product?
1398  @return database product name
1399 }
1400 function TZMsSqlDatabaseInfo.GetDatabaseProductName: string;
1401 begin
1402  Result := 'MS SQL';
1403 end;
1404 
1405 {**
1406  What's the version of this database product?
1407  @return database version
1408 }
1409 function TZMsSqlDatabaseInfo.GetDatabaseProductVersion: string;
1410 begin
1411  Result := '7+';
1412 end;
1413 
1414 {**
1415  What's the name of this JDBC driver?
1416  @return JDBC driver name
1417 }
1418 function TZMsSqlDatabaseInfo.GetDriverName: string;
1419 begin
1420  Result := 'Zeos Database Connectivity Driver for Microsoft SQL Server';
1421 end;
1422 
1423 {**
1424  What's the name of this database product?
1425  @return database product name
1426 }
1427 function TZSybaseDatabaseInfo.GetDatabaseProductName: string;
1428 begin
1429  Result := 'Sybase';
1430 end;
1431 
1432 {**
1433  What's the version of this database product?
1434  @return database version
1435 }
1436 function TZSybaseDatabaseInfo.GetDatabaseProductVersion: string;
1437 begin
1438  Result := '12+';
1439 end;
1440 
1441 {**
1442  What's the name of this JDBC driver?
1443  @return JDBC driver name
1444 }
1445 function TZSybaseDatabaseInfo.GetDriverName: string;
1446 begin
1447  Result := 'Zeos Database Connectivity Driver for Sybase ASE Server';
1448 end;
1449 
1450 { TZMsSqlDatabaseMetadata }
1451 
1452 {**
1453  Constructs a database information object and returns the interface to it. Used
1454  internally by the constructor.
1455  @return the database information object interface
1456 }
1457 function TZMsSqlDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
1458 begin
1459  Result := TZMsSqlDatabaseInfo.Create(Self);
1460 end;
1461 
1462 {**
1463  Gets a description of the stored procedures available in a
1464  catalog.
1465 
1466  <P>Only procedure descriptions matching the schema and
1467  procedure name criteria are returned. They are ordered by
1468  PROCEDURE_SCHEM, and PROCEDURE_NAME.
1469 
1470  <P>Each procedure description has the the following columns:
1471  <OL>
1472  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1473  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1474  <LI><B>PROCEDURE_NAME</B> String => procedure name
1475  <LI> reserved for future use
1476  <LI> reserved for future use
1477  <LI> reserved for future use
1478  <LI><B>REMARKS</B> String => explanatory comment on the procedure
1479  <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
1480  <UL>
1481  <LI> procedureResultUnknown - May return a result
1482  <LI> procedureNoResult - Does not return a result
1483  <LI> procedureReturnsResult - Returns a result
1484  </UL>
1485  </OL>
1486 
1487  @param catalog a catalog name; "" retrieves those without a
1488  catalog; null means drop catalog name from the selection criteria
1489  @param schemaPattern a schema name pattern; "" retrieves those
1490  without a schema
1491  @param procedureNamePattern a procedure name pattern
1492  @return <code>ResultSet</code> - each row is a procedure description
1493  @see #getSearchStringEscape
1494 }
1495 function TZMsSqlDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
1496  const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
1497 begin
1498  Result:=inherited UncachedGetProcedures(Catalog, SchemaPattern, ProcedureNamePattern);
1499 
1500  with GetStatement.ExecuteQuery('exec '+Catalog+'.'+SchemaPattern+'.'+'sp_stored_procedures '+
1501  ComposeObjectString(ProcedureNamePattern)+', '+ComposeObjectString(SchemaPattern)+', '+ComposeObjectString(Catalog)) do
1502  begin
1503  while Next do
1504  begin
1505  Result.MoveToInsertRow;
1506  Result.UpdateStringByName('PROCEDURE_CAT',
1507  GetStringByName('PROCEDURE_QUALIFIER'));
1508  Result.UpdateStringByName('PROCEDURE_SCHEM',
1509  GetStringByName('PROCEDURE_OWNER'));
1510  Result.UpdateStringByName('PROCEDURE_NAME',
1511  GetStringByName('PROCEDURE_NAME'));
1512  Result.UpdateStringByName('REMARKS',
1513  GetStringByName('REMARKS'));
1514  Result.UpdateShortByName('PROCEDURE_TYPE', 0);
1515  Result.InsertRow;
1516  end;
1517  Close;
1518  end;
1519  Result.BeforeFirst;
1520 end;
1521 
1522 {**
1523  Gets a description of a catalog's stored procedure parameters
1524  and result columns.
1525 
1526  <P>Only descriptions matching the schema, procedure and
1527  parameter name criteria are returned. They are ordered by
1528  PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
1529  if any, is first. Next are the parameter descriptions in call
1530  order. The column descriptions follow in column number order.
1531 
1532  <P>Each row in the <code>ResultSet</code> is a parameter description or
1533  column description with the following fields:
1534  <OL>
1535  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1536  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1537  <LI><B>PROCEDURE_NAME</B> String => procedure name
1538  <LI><B>COLUMN_NAME</B> String => column/parameter name
1539  <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
1540  <UL>
1541  <LI> procedureColumnUnknown - nobody knows
1542  <LI> procedureColumnIn - IN parameter
1543  <LI> procedureColumnInOut - INOUT parameter
1544  <LI> procedureColumnOut - OUT parameter
1545  <LI> procedureColumnReturn - procedure return value
1546  <LI> procedureColumnResult - result column in <code>ResultSet</code>
1547  </UL>
1548  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1549  <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
1550  type name is fully qualified
1551  <LI><B>PRECISION</B> int => precision
1552  <LI><B>LENGTH</B> int => length in bytes of data
1553  <LI><B>SCALE</B> short => scale
1554  <LI><B>RADIX</B> short => radix
1555  <LI><B>NULLABLE</B> short => can it contain NULL?
1556  <UL>
1557  <LI> procedureNoNulls - does not allow NULL values
1558  <LI> procedureNullable - allows NULL values
1559  <LI> procedureNullableUnknown - nullability unknown
1560  </UL>
1561  <LI><B>REMARKS</B> String => comment describing parameter/column
1562  </OL>
1563 
1564  <P><B>Note:</B> Some databases may not return the column
1565  descriptions for a procedure. Additional columns beyond
1566  REMARKS can be defined by the database.
1567 
1568  @param catalog a catalog name; "" retrieves those without a
1569  catalog; null means drop catalog name from the selection criteria
1570  @param schemaPattern a schema name pattern; "" retrieves those
1571  without a schema
1572  @param procedureNamePattern a procedure name pattern
1573  @param columnNamePattern a column name pattern
1574  @return <code>ResultSet</code> - each row describes a stored procedure parameter or
1575  column
1576  @see #getSearchStringEscape
1577 }
1578 function TZMsSqlDatabaseMetadata.UncachedGetProcedureColumns(const Catalog: string;
1579  const SchemaPattern: string; const ProcedureNamePattern: string;
1580  const ColumnNamePattern: string): IZResultSet;
1581 begin
1582  Result:=inherited UncachedGetProcedureColumns(Catalog, SchemaPattern,
1583  ProcedureNamePattern, ColumnNamePattern);
1584 
1585  with GetStatement.ExecuteQuery('exec '+Catalog+'.'+SchemaPattern+'.'+
1586  'sp_sproc_columns '+ComposeObjectString(ProcedureNamePattern)+', '+
1587  ComposeObjectString(SchemaPattern)+', '+ComposeObjectString(Catalog)+', '+
1588  ComposeObjectString(ColumnNamePattern)) do
1589  begin
1590  while Next do
1591  begin
1592  Result.MoveToInsertRow;
1593  Result.UpdateStringByName('PROCEDURE_CAT',
1594  GetStringByName('PROCEDURE_QUALIFIER'));
1595  Result.UpdateStringByName('PROCEDURE_SCHEM',
1596  GetStringByName('PROCEDURE_OWNER'));
1597  Result.UpdateStringByName('PROCEDURE_NAME',
1598  GetStringByName('PROCEDURE_NAME'));
1599  Result.UpdateStringByName('COLUMN_NAME',
1600  GetStringByName('COLUMN_NAME'));
1601  case GetShortByName('COLUMN_TYPE') of
1602  1: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctIn));
1603  2: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
1604  3: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
1605  4: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
1606  5: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctReturn));
1607  else
1608  Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
1609  end;
1610  Result.UpdateShortByName('DATA_TYPE',
1611  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
1612  Result.UpdateStringByName('TYPE_NAME', GetStringByName('TYPE_NAME'));
1613  Result.UpdateIntByName('PRECISION', GetIntByName('PRECISION'));
1614  Result.UpdateIntByName('LENGTH', GetIntByName('LENGTH'));
1615  Result.UpdateShortByName('SCALE', GetShortByName('SCALE'));
1616  Result.UpdateShortByName('RADIX', GetShortByName('RADIX'));
1617  Result.UpdateShortByName('NULLABLE', 2);
1618  if GetStringByName('IS_NULLABLE') = 'NO' then
1619  Result.UpdateShortByName('NULLABLE', 0);
1620  if GetStringByName('IS_NULLABLE') = 'YES' then
1621  Result.UpdateShortByName('NULLABLE', 1);
1622  Result.UpdateStringByName('REMARKS', GetStringByName('REMARKS'));
1623  Result.InsertRow;
1624  end;
1625  Close;
1626  end;
1627  Result.BeforeFirst;
1628 end;
1629 
1630 {**
1631  Gets a description of tables available in a catalog.
1632 
1633  <P>Only table descriptions matching the catalog, schema, table
1634  name and type criteria are returned. They are ordered by
1635  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1636 
1637  <P>Each table description has the following columns:
1638  <OL>
1639  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1640  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1641  <LI><B>TABLE_NAME</B> String => table name
1642  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1643  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1644  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1645  <LI><B>REMARKS</B> String => explanatory comment on the table
1646  </OL>
1647 
1648  <P><B>Note:</B> Some databases may not return information for
1649  all tables.
1650 
1651  @param catalog a catalog name; "" retrieves those without a
1652  catalog; null means drop catalog name from the selection criteria
1653  @param schemaPattern a schema name pattern; "" retrieves those
1654  without a schema
1655  @param tableNamePattern a table name pattern
1656  @param types a list of table types to include; null returns all types
1657  @return <code>ResultSet</code> - each row is a table description
1658  @see #getSearchStringEscape
1659 }
1660 function TZMsSqlDatabaseMetadata.UncachedGetTables(const Catalog: string;
1661  const SchemaPattern: string; const TableNamePattern: string;
1662  const Types: TStringDynArray): IZResultSet;
1663 var
1664  I: Integer;
1665  TableTypes: string;
1666 begin
1667  Result:=inherited UncachedGetTables(Catalog, SchemaPattern, TableNamePattern, Types);
1668 
1669  TableTypes := '';
1670  for I := 0 to Length(Types) - 1 do
1671  begin
1672  if Length(TableTypes) > 0 then
1673  TableTypes := TableTypes + ',';
1674  TableTypes := TableTypes + AnsiQuotedStr(Types[I], '''');
1675  end;
1676  if TableTypes = '' then
1677  TableTypes := 'null'
1678  else TableTypes := AnsiQuotedStr(TableTypes, '"');
1679 
1680  with GetStatement.ExecuteQuery(
1681  Format('exec sp_tables %s, %s, %s, %s',
1682  [ComposeObjectString(TableNamePattern), ComposeObjectString(SchemaPattern), ComposeObjectString(Catalog), TableTypes])) do
1683  begin
1684  while Next do
1685  begin
1686  Result.MoveToInsertRow;
1687  Result.UpdateStringByName('TABLE_CAT',
1688  GetStringByName('TABLE_QUALIFIER'));
1689  Result.UpdateStringByName('TABLE_SCHEM', GetStringByName('TABLE_OWNER'));
1690  Result.UpdateStringByName('TABLE_NAME', GetStringByName('TABLE_NAME'));
1691  Result.UpdateStringByName('TABLE_TYPE', GetStringByName('TABLE_TYPE'));
1692  Result.UpdateStringByName('REMARKS', GetStringByName('REMARKS'));
1693  Result.InsertRow;
1694  end;
1695  Close;
1696  end;
1697  Result.BeforeFirst;
1698 end;
1699 
1700 {**
1701  Gets the schema names available in this database. The results
1702  are ordered by schema name.
1703 
1704  <P>The schema column is:
1705  <OL>
1706  <LI><B>TABLE_SCHEM</B> String => schema name
1707  </OL>
1708 
1709  @return <code>ResultSet</code> - each row has a single String column that is a
1710  schema name
1711 }
1712 function TZMsSqlDatabaseMetadata.UncachedGetSchemas: IZResultSet;
1713 begin
1714  Result:=inherited UncachedGetSchemas;
1715 
1716  with GetStatement.ExecuteQuery(
1717  'select name as TABLE_OWNER from sysusers where islogin = 1') do
1718  begin
1719  while Next do
1720  begin
1721  Result.MoveToInsertRow;
1722  Result.UpdateStringByName('TABLE_SCHEM',
1723  GetStringByName('TABLE_OWNER'));
1724  Result.InsertRow;
1725  end;
1726  Close;
1727  end;
1728  Result.BeforeFirst;
1729 end;
1730 
1731 {**
1732  Gets the catalog names available in this database. The results
1733  are ordered by catalog name.
1734 
1735  <P>The catalog column is:
1736  <OL>
1737  <LI><B>TABLE_CAT</B> String => catalog name
1738  </OL>
1739 
1740  @return <code>ResultSet</code> - each row has a single String column that is a
1741  catalog name
1742 }
1743 function TZMsSqlDatabaseMetadata.UncachedGetCatalogs: IZResultSet;
1744 begin
1745  Result:=inherited UncachedGetCatalogs;
1746 
1747  with GetStatement.ExecuteQuery('exec sp_databases') do
1748  begin
1749  while Next do
1750  begin
1751  Result.MoveToInsertRow;
1752  Result.UpdateStringByName('TABLE_CAT',
1753  GetStringByName('DATABASE_NAME'));
1754  Result.InsertRow;
1755  end;
1756  Close;
1757  end;
1758  Result.BeforeFirst;
1759 end;
1760 
1761 {**
1762  Gets the table types available in this database. The results
1763  are ordered by table type.
1764 
1765  <P>The table type is:
1766  <OL>
1767  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1768  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1769  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1770  </OL>
1771 
1772  @return <code>ResultSet</code> - each row has a single String column that is a
1773  table type
1774 }
1775 function TZMsSqlDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
1776 const
1777  TableTypes: array[0..2] of string = ('SYSTEM TABLE', 'TABLE', 'VIEW');
1778 var
1779  I: Integer;
1780 begin
1781  Result:=inherited UncachedGetTableTypes;
1782 
1783  for I := 0 to 2 do
1784  begin
1785  Result.MoveToInsertRow;
1786  Result.UpdateStringByName('TABLE_TYPE', TableTypes[I]);
1787  Result.InsertRow;
1788  end;
1789  Result.BeforeFirst;
1790 end;
1791 
1792 {**
1793  Gets a description of table columns available in
1794  the specified catalog.
1795 
1796  <P>Only column descriptions matching the catalog, schema, table
1797  and column name criteria are returned. They are ordered by
1798  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1799 
1800  <P>Each column description has the following columns:
1801  <OL>
1802  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1803  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1804  <LI><B>TABLE_NAME</B> String => table name
1805  <LI><B>COLUMN_NAME</B> String => column name
1806  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1807  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
1808  for a UDT the type name is fully qualified
1809  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1810  types this is the maximum number of characters, for numeric or
1811  decimal types this is precision.
1812  <LI><B>BUFFER_LENGTH</B> is not used.
1813  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1814  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1815  <LI><B>NULLABLE</B> int => is NULL allowed?
1816  <UL>
1817  <LI> columnNoNulls - might not allow NULL values
1818  <LI> columnNullable - definitely allows NULL values
1819  <LI> columnNullableUnknown - nullability unknown
1820  </UL>
1821  <LI><B>REMARKS</B> String => comment describing column (may be null)
1822  <LI><B>COLUMN_DEF</B> String => default value (may be null)
1823  <LI><B>SQL_DATA_TYPE</B> int => unused
1824  <LI><B>SQL_DATETIME_SUB</B> int => unused
1825  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1826  maximum number of bytes in the column
1827  <LI><B>ORDINAL_POSITION</B> int => index of column in table
1828  (starting at 1)
1829  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1830  does not allow NULL values; "YES" means the column might
1831  allow NULL values. An empty string means nobody knows.
1832  </OL>
1833 
1834  @param catalog a catalog name; "" retrieves those without a
1835  catalog; null means drop catalog name from the selection criteria
1836  @param schemaPattern a schema name pattern; "" retrieves those
1837  without a schema
1838  @param tableNamePattern a table name pattern
1839  @param columnNamePattern a column name pattern
1840  @return <code>ResultSet</code> - each row is a column description
1841  @see #getSearchStringEscape
1842 }
1843 function TZMsSqlDatabaseMetadata.UncachedGetColumns(const Catalog: string;
1844  const SchemaPattern: string; const TableNamePattern: string;
1845  const ColumnNamePattern: string): IZResultSet;
1846 var
1847  SQLType: TZSQLType;
1848  TableName: String;
1849 begin
1850  Result:=inherited UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
1851 
1852  with GetStatement.ExecuteQuery('exec '+GetSP_Prefix(Catalog, SchemaPattern)+'sp_columns '+
1853  ComposeObjectString(TableNamePattern)+', '+
1854  ComposeObjectString(SchemaPattern)+', '+
1855  ComposeObjectString(Catalog)+', '+
1856  ComposeObjectString(ColumnNamePattern)) do
1857  begin
1858  while Next do
1859  begin
1860  Result.MoveToInsertRow;
1861  Result.UpdateStringByName('TABLE_CAT', GetStringByName('TABLE_QUALIFIER'));
1862  Result.UpdateStringByName('TABLE_SCHEM', GetStringByName('TABLE_OWNER'));
1863  Result.UpdateStringByName('TABLE_NAME',
1864  GetStringByName('TABLE_NAME'));
1865  Result.UpdateStringByName('COLUMN_NAME',
1866  GetStringByName('COLUMN_NAME'));
1867  //The value in the resultset will be used
1868  SQLType := ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType);
1869  if SQLType = stUnknown then
1870  Result.UpdateNullByName('DATA_TYPE')
1871  else
1872  Result.UpdateShortByName('DATA_TYPE', Ord(SQLType));
1873  if ( SQLType = stBytes) and (UpperCase(GetStringByName('TYPE_NAME')) = 'UNIQUEIDENTIFIER') then
1874  Result.UpdateShortByName('DATA_TYPE', Ord(stGUID));
1875  Result.UpdateStringByName('TYPE_NAME', GetStringByName('TYPE_NAME'));
1876  Result.UpdateIntByName('COLUMN_SIZE', GetIntByName('LENGTH'));
1877  Result.UpdateIntByName('BUFFER_LENGTH', GetIntByName('LENGTH'));
1878  Result.UpdateIntByName('DECIMAL_DIGITS', GetIntByName('SCALE'));
1879  Result.UpdateIntByName('NUM_PREC_RADIX', GetShortByName('RADIX'));
1880  Result.UpdateIntByName('NULLABLE', 2);
1881  if GetStringByName('IS_NULLABLE') = 'NO' then
1882  Result.UpdateShortByName('NULLABLE', 0);
1883  if GetStringByName('IS_NULLABLE') = 'YES' then
1884  Result.UpdateShortByName('NULLABLE', 1);
1885  Result.UpdateStringByName('REMARKS', GetStringByName('REMARKS'));
1886  Result.UpdateStringByName('COLUMN_DEF', GetStringByName('COLUMN_DEF'));
1887  Result.UpdateShortByName('SQL_DATA_TYPE', GetShortByName('SQL_DATA_TYPE'));
1888  Result.UpdateShortByName('SQL_DATETIME_SUB', GetShortByName('SQL_DATETIME_SUB'));
1889  Result.UpdateIntByName('CHAR_OCTET_LENGTH', GetIntByName('CHAR_OCTET_LENGTH'));
1890  Result.UpdateIntByName('ORDINAL_POSITION', GetIntByName('ORDINAL_POSITION'));
1891  Result.UpdateStringByName('IS_NULLABLE',
1892  GetStringByName('IS_NULLABLE'));
1893 
1894  Result.UpdateBooleanByName('SEARCHABLE',
1895  not (GetShortByName('SS_DATA_TYPE') in [34, 35]));
1896 
1897  Result.InsertRow;
1898  end;
1899  Close;
1900  end;
1901 
1902  TableName := Result.GetStringByName('TABLE_NAME');
1903 
1904  Result.BeforeFirst;
1905  with GetStatement.ExecuteQuery('select c.colid, c.name, c.type, c.prec, '+
1906  'c.scale, c.colstat, c.status, c.iscomputed from syscolumns c inner join'
1907  + ' sysobjects o on (o.id = c.id) where o.name COLLATE Latin1_General_CS_AS = '+
1908  DeComposeObjectString(TableName)+' and c.number=0 order by colid') do
1909  // hint http://blog.sqlauthority.com/2007/04/30/case-sensitive-sql-query-search/ for the collation setting to get a case sensitive behavior
1910  begin
1911  while Next do
1912  begin
1913  Result.Next;
1914  Result.UpdateBooleanByName('AUTO_INCREMENT',
1915  (GetShortByName('status') and $80) <> 0);
1916  Result.UpdateNullByName('CASE_SENSITIVE');
1917  Result.UpdateBooleanByName('SEARCHABLE',
1918  Result.GetBooleanByName('SEARCHABLE')
1919  and (GetIntByName('iscomputed') = 0));
1920  Result.UpdateBooleanByName('WRITABLE',
1921  ((GetShortByName('status') and $80) = 0)
1922  (*and (GetShortByName('type') <> 37)*) // <<<< *DEBUG WARUM?
1923  and (GetIntByName('iscomputed') = 0));
1924  Result.UpdateBooleanByName('DEFINITELYWRITABLE',
1925  Result.GetBooleanByName('WRITABLE'));
1926  Result.UpdateBooleanByName('READONLY',
1927  not Result.GetBooleanByName('WRITABLE'));
1928  if Result.GetBooleanByName('AUTO_INCREMENT') then
1929  begin
1930  Result.UpdateShortByName('NULLABLE', 1);
1931  Result.UpdateStringByName('IS_NULLABLE', 'YES');
1932  end;
1933  Result.UpdateRow;
1934  end;
1935  Close;
1936  end;
1937  Result.BeforeFirst;
1938 end;
1939 
1940 {**
1941  Gets a description of the access rights for a table's columns.
1942 
1943  <P>Only privileges matching the column name criteria are
1944  returned. They are ordered by COLUMN_NAME and PRIVILEGE.
1945 
1946  <P>Each privilige description has the following columns:
1947  <OL>
1948  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1949  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1950  <LI><B>TABLE_NAME</B> String => table name
1951  <LI><B>COLUMN_NAME</B> String => column name
1952  <LI><B>GRANTOR</B> => grantor of access (may be null)
1953  <LI><B>GRANTEE</B> String => grantee of access
1954  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1955  INSERT, UPDATE, REFRENCES, ...)
1956  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1957  to grant to others; "NO" if not; null if unknown
1958  </OL>
1959 
1960  @param catalog a catalog name; "" retrieves those without a
1961  catalog; null means drop catalog name from the selection criteria
1962  @param schema a schema name; "" retrieves those without a schema
1963  @param table a table name
1964  @param columnNamePattern a column name pattern
1965  @return <code>ResultSet</code> - each row is a column privilege description
1966  @see #getSearchStringEscape
1967 }
1968 function TZMsSqlDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
1969  const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
1970 begin
1971  Result:=inherited UncachedGetColumnPrivileges(Catalog, Schema, Table, ColumnNamePattern);
1972 
1973  with GetStatement.ExecuteQuery('exec '+GetSP_Prefix(Catalog, Schema)+'sp_column_privileges '+
1974  ComposeObjectString(Table)+', '+ComposeObjectString(Schema)+', '+
1975  ComposeObjectString(Catalog)+', '+ComposeObjectString(ColumnNamePattern)) do
1976  begin
1977  while Next do
1978  begin
1979  Result.MoveToInsertRow;
1980  Result.UpdateStringByName('TABLE_CAT',
1981  GetStringByName('TABLE_QUALIFIER'));
1982  Result.UpdateStringByName('TABLE_SCHEM',
1983  GetStringByName('TABLE_OWNER'));
1984  Result.UpdateStringByName('TABLE_NAME',
1985  GetStringByName('TABLE_NAME'));
1986  Result.UpdateStringByName('COLUMN_NAME',
1987  GetStringByName('COLUMN_NAME'));
1988  Result.UpdateStringByName('GRANTOR',
1989  GetStringByName('GRANTOR'));
1990  Result.UpdateStringByName('GRANTEE',
1991  GetStringByName('GRANTEE'));
1992  Result.UpdateStringByName('PRIVILEGE',
1993  GetStringByName('PRIVILEGE'));
1994  Result.UpdateStringByName('IS_GRANTABLE',
1995  GetStringByName('IS_GRANTABLE'));
1996  Result.InsertRow;
1997  end;
1998  Close;
1999  end;
2000  Result.BeforeFirst;
2001 end;
2002 
2003 {**
2004  Gets a description of the access rights for each table available
2005  in a catalog. Note that a table privilege applies to one or
2006  more columns in the table. It would be wrong to assume that
2007  this priviledge applies to all columns (this may be true for
2008  some systems but is not true for all.)
2009 
2010  <P>Only privileges matching the schema and table name
2011  criteria are returned. They are ordered by TABLE_SCHEM,
2012  TABLE_NAME, and PRIVILEGE.
2013 
2014  <P>Each privilige description has the following columns:
2015  <OL>
2016  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2017  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2018  <LI><B>TABLE_NAME</B> String => table name
2019  <LI><B>GRANTOR</B> => grantor of access (may be null)
2020  <LI><B>GRANTEE</B> String => grantee of access
2021  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2022  INSERT, UPDATE, REFRENCES, ...)
2023  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2024  to grant to others; "NO" if not; null if unknown
2025  </OL>
2026 
2027  @param catalog a catalog name; "" retrieves those without a
2028  catalog; null means drop catalog name from the selection criteria
2029  @param schemaPattern a schema name pattern; "" retrieves those
2030  without a schema
2031  @param tableNamePattern a table name pattern
2032  @return <code>ResultSet</code> - each row is a table privilege description
2033  @see #getSearchStringEscape
2034 }
2035 function TZMsSqlDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
2036  const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
2037 begin
2038  Result:=inherited UncachedGetTablePrivileges(Catalog, SchemaPattern, TableNamePattern);
2039 
2040  with GetStatement.ExecuteQuery(
2041  Format('exec sp_table_privileges %s, %s, %s',
2042  [ComposeObjectString(TableNamePattern), ComposeObjectString(SchemaPattern), ComposeObjectString(Catalog)])) do
2043  begin
2044  while Next do
2045  begin
2046  Result.MoveToInsertRow;
2047  Result.UpdateStringByName('TABLE_CAT',
2048  GetStringByName('TABLE_QUALIFIER'));
2049  Result.UpdateStringByName('TABLE_SCHEM',
2050  GetStringByName('TABLE_OWNER'));
2051  Result.UpdateStringByName('TABLE_NAME',
2052  GetStringByName('TABLE_NAME'));
2053  Result.UpdateStringByName('GRANTOR',
2054  GetStringByName('GRANTOR'));
2055  Result.UpdateStringByName('GRANTEE',
2056  GetStringByName('GRANTEE'));
2057  Result.UpdateStringByName('PRIVILEGE',
2058  GetStringByName('PRIVILEGE'));
2059  Result.UpdateStringByName('IS_GRANTABLE',
2060  GetStringByName('IS_GRANTABLE'));
2061  Result.InsertRow;
2062  end;
2063  Close;
2064  end;
2065  Result.BeforeFirst;
2066 end;
2067 
2068 {**
2069  Gets a description of a table's columns that are automatically
2070  updated when any value in a row is updated. They are
2071  unordered.
2072 
2073  <P>Each column description has the following columns:
2074  <OL>
2075  <LI><B>SCOPE</B> short => is not used
2076  <LI><B>COLUMN_NAME</B> String => column name
2077  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2078  <LI><B>TYPE_NAME</B> String => Data source dependent type name
2079  <LI><B>COLUMN_SIZE</B> int => precision
2080  <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
2081  <LI><B>DECIMAL_DIGITS</B> short => scale
2082  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2083  like an Oracle ROWID
2084  <UL>
2085  <LI> versionColumnUnknown - may or may not be pseudo column
2086  <LI> versionColumnNotPseudo - is NOT a pseudo column
2087  <LI> versionColumnPseudo - is a pseudo column
2088  </UL>
2089  </OL>
2090 
2091  @param catalog a catalog name; "" retrieves those without a
2092  catalog; null means drop catalog name from the selection criteria
2093  @param schema a schema name; "" retrieves those without a schema
2094  @param table a table name
2095  @return <code>ResultSet</code> - each row is a column description
2096  @exception SQLException if a database access error occurs
2097 }
2098 function TZMsSqlDatabaseMetadata.UncachedGetVersionColumns(const Catalog: string;
2099  const Schema: string; const Table: string): IZResultSet;
2100 var
2101  MSCol_Type: string;
2102 begin
2103  Result:=inherited UncachedGetVersionColumns(Catalog, Schema, Table);
2104 
2105  MSCol_Type := '''V''';
2106 
2107  with GetStatement.ExecuteQuery(
2108  Format('exec sp_special_columns %s, %s, %s, %s',
2109  [ComposeObjectString(Table), ComposeObjectString(Schema), ComposeObjectString(Catalog), MSCol_Type])) do
2110  begin
2111  while Next do
2112  begin
2113  Result.MoveToInsertRow;
2114  Result.UpdateShortByName('SCOPE',
2115  GetShortByName('SCOPE'));
2116  Result.UpdateStringByName('COLUMN_NAME',
2117  GetStringByName('COLUMN_NAME'));
2118  Result.UpdateShortByName('DATA_TYPE',
2119  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
2120  Result.UpdateStringByName('TYPE_NAME',
2121  GetStringByName('TYPE_NAME'));
2122  Result.UpdateIntByName('COLUMN_SIZE',
2123  GetIntByName('LENGTH'));
2124  Result.UpdateIntByName('BUFFER_LENGTH',
2125  GetIntByName('LENGTH'));
2126  Result.UpdateIntByName('DECIMAL_DIGITS',
2127  GetIntByName('SCALE'));
2128  Result.UpdateShortByName('PSEUDO_COLUMN',
2129  GetShortByName('PSEUDO_COLUMN'));
2130  Result.InsertRow;
2131  end;
2132  Close;
2133  end;
2134  Result.BeforeFirst;
2135 end;
2136 
2137 {**
2138  Gets a description of a table's primary key columns. They
2139  are ordered by COLUMN_NAME.
2140 
2141  <P>Each primary key column description has the following columns:
2142  <OL>
2143  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2144  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2145  <LI><B>TABLE_NAME</B> String => table name
2146  <LI><B>COLUMN_NAME</B> String => column name
2147  <LI><B>KEY_SEQ</B> short => sequence number within primary key
2148  <LI><B>PK_NAME</B> String => primary key name (may be null)
2149  </OL>
2150 
2151  @param catalog a catalog name; "" retrieves those without a
2152  catalog; null means drop catalog name from the selection criteria
2153  @param schema a schema name; "" retrieves those
2154  without a schema
2155  @param table a table name
2156  @return <code>ResultSet</code> - each row is a primary key column description
2157  @exception SQLException if a database access error occurs
2158 }
2159 function TZMsSqlDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
2160  const Schema: string; const Table: string): IZResultSet;
2161 begin
2162  Result:=inherited UncachedGetPrimaryKeys(Catalog, Schema, Table);
2163 
2164  with GetStatement.ExecuteQuery(
2165  Format('exec sp_pkeys %s, %s, %s',
2166  [ComposeObjectString(Table), ComposeObjectString(Schema), ComposeObjectString(Catalog)])) do
2167  begin
2168  while Next do
2169  begin
2170  Result.MoveToInsertRow;
2171  Result.UpdateStringByName('TABLE_CAT',
2172  GetStringByName('TABLE_QUALIFIER'));
2173  Result.UpdateStringByName('TABLE_SCHEM',
2174  GetStringByName('TABLE_OWNER'));
2175  Result.UpdateStringByName('TABLE_NAME',
2176  GetStringByName('TABLE_NAME'));
2177  Result.UpdateStringByName('COLUMN_NAME',
2178  GetStringByName('COLUMN_NAME'));
2179  Result.UpdateShortByName('KEY_SEQ',
2180  GetShortByName('KEY_SEQ'));
2181  Result.UpdateStringByName('PK_NAME',
2182  GetStringByName('PK_NAME'));
2183  Result.InsertRow;
2184  end;
2185  Close;
2186  end;
2187  Result.BeforeFirst;
2188 end;
2189 
2190 {**
2191  Gets a description of the foreign key columns in the foreign key
2192  table that reference the primary key columns of the primary key
2193  table (describe how one table imports another's key.) This
2194  should normally return a single foreign key/primary key pair
2195  (most tables only import a foreign key from a table once.) They
2196  are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
2197  KEY_SEQ.
2198 
2199  <P>Each foreign key column description has the following columns:
2200  <OL>
2201  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
2202  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
2203  <LI><B>PKTABLE_NAME</B> String => primary key table name
2204  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2205  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2206  being exported (may be null)
2207  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2208  being exported (may be null)
2209  <LI><B>FKTABLE_NAME</B> String => foreign key table name
2210  being exported
2211  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2212  being exported
2213  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2214  <LI><B>UPDATE_RULE</B> short => What happens to
2215  foreign key when primary is updated:
2216  <UL>
2217  <LI> importedNoAction - do not allow update of primary
2218  key if it has been imported
2219  <LI> importedKeyCascade - change imported key to agree
2220  with primary key update
2221  <LI> importedKeySetNull - change imported key to NULL if
2222  its primary key has been updated
2223  <LI> importedKeySetDefault - change imported key to default values
2224  if its primary key has been updated
2225  <LI> importedKeyRestrict - same as importedKeyNoAction
2226  (for ODBC 2.x compatibility)
2227  </UL>
2228  <LI><B>DELETE_RULE</B> short => What happens to
2229  the foreign key when primary is deleted.
2230  <UL>
2231  <LI> importedKeyNoAction - do not allow delete of primary
2232  key if it has been imported
2233  <LI> importedKeyCascade - delete rows that import a deleted key
2234  <LI> importedKeySetNull - change imported key to NULL if
2235  its primary key has been deleted
2236  <LI> importedKeyRestrict - same as importedKeyNoAction
2237  (for ODBC 2.x compatibility)
2238  <LI> importedKeySetDefault - change imported key to default if
2239  its primary key has been deleted
2240  </UL>
2241  <LI><B>FK_NAME</B> String => foreign key name (may be null)
2242  <LI><B>PK_NAME</B> String => primary key name (may be null)
2243  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
2244  constraints be deferred until commit
2245  <UL>
2246  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
2247  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
2248  <LI> importedKeyNotDeferrable - see SQL92 for definition
2249  </UL>
2250  </OL>
2251 
2252  @param primaryCatalog a catalog name; "" retrieves those without a
2253  catalog; null means drop catalog name from the selection criteria
2254  @param primarySchema a schema name; "" retrieves those
2255  without a schema
2256  @param primaryTable the table name that exports the key
2257  @param foreignCatalog a catalog name; "" retrieves those without a
2258  catalog; null means drop catalog name from the selection criteria
2259  @param foreignSchema a schema name; "" retrieves those
2260  without a schema
2261  @param foreignTable the table name that imports the key
2262  @return <code>ResultSet</code> - each row is a foreign key column description
2263  @see #getImportedKeys
2264 }
2265 function TZMsSqlDatabaseMetadata.UncachedGetCrossReference(const PrimaryCatalog: string;
2266  const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
2267  const ForeignSchema: string; const ForeignTable: string): IZResultSet;
2268 var KeySeq: Integer;
2269 begin
2270  Result:=inherited UncachedGetCrossReference(PrimaryCatalog, PrimarySchema, PrimaryTable,
2271  ForeignCatalog, ForeignSchema, ForeignTable);
2272  KeySeq := 0;
2273  with GetStatement.ExecuteQuery(
2274  Format('exec sp_fkeys %s, %s, %s, %s, %s, %s',
2275  [ComposeObjectString(PrimaryTable), ComposeObjectString(PrimarySchema), ComposeObjectString(PrimaryCatalog),
2276  ComposeObjectString(ForeignTable), ComposeObjectString(ForeignSchema), ComposeObjectString(ForeignCatalog)])) do
2277  begin
2278  while Next do
2279  begin
2280  Inc(KeySeq);
2281  Result.MoveToInsertRow;
2282  Result.UpdateStringByName('PKTABLE_CAT',
2283  GetStringByName('PKTABLE_QUALIFIER'));
2284  Result.UpdateStringByName('PKTABLE_SCHEM',
2285  GetStringByName('PKTABLE_OWNER'));
2286  Result.UpdateStringByName('PKTABLE_NAME',
2287  GetStringByName('PKTABLE_NAME'));
2288  Result.UpdateStringByName('PKCOLUMN_NAME',
2289  GetStringByName('PKCOLUMN_NAME'));
2290  Result.UpdateStringByName('FKTABLE_CAT',
2291  GetStringByName('FKTABLE_QUALIFIER'));
2292  Result.UpdateStringByName('FKTABLE_SCHEM',
2293  GetStringByName('FKTABLE_OWNER'));
2294  Result.UpdateStringByName('FKTABLE_NAME',
2295  GetStringByName('FKTABLE_NAME'));
2296  Result.UpdateStringByName('FKCOLUMN_NAME',
2297  GetStringByName('FKCOLUMN_NAME'));
2298  Result.UpdateShortByName('KEY_SEQ', KeySeq);
2299  Result.UpdateShortByName('UPDATE_RULE',
2300  GetShortByName('UPDATE_RULE'));
2301  Result.UpdateShortByName('DELETE_RULE',
2302  GetShortByName('DELETE_RULE'));
2303  Result.UpdateStringByName('FK_NAME',
2304  GetStringByName('FK_NAME'));
2305  Result.UpdateStringByName('PK_NAME',
2306  GetStringByName('PK_NAME'));
2307  Result.UpdateIntByName('DEFERRABILITY', 0);
2308  Result.InsertRow;
2309  end;
2310  Close;
2311  end;
2312  Result.BeforeFirst;
2313 end;
2314 
2315 {**
2316  Gets a description of all the standard SQL types supported by
2317  this database. They are ordered by DATA_TYPE and then by how
2318  closely the data type maps to the corresponding JDBC SQL type.
2319 
2320  <P>Each type description has the following columns:
2321  <OL>
2322  <LI><B>TYPE_NAME</B> String => Type name
2323  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2324  <LI><B>PRECISION</B> int => maximum precision
2325  <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
2326  (may be null)
2327  <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
2328  (may be null)
2329  <LI><B>CREATE_PARAMS</B> String => parameters used in creating
2330  the type (may be null)
2331  <LI><B>NULLABLE</B> short => can you use NULL for this type?
2332  <UL>
2333  <LI> typeNoNulls - does not allow NULL values
2334  <LI> typeNullable - allows NULL values
2335  <LI> typeNullableUnknown - nullability unknown
2336  </UL>
2337  <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
2338  <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
2339  <UL>
2340  <LI> typePredNone - No support
2341  <LI> typePredChar - Only supported with WHERE .. LIKE
2342  <LI> typePredBasic - Supported except for WHERE .. LIKE
2343  <LI> typeSearchable - Supported for all WHERE ..
2344  </UL>
2345  <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
2346  <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
2347  <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
2348  auto-increment value?
2349  <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
2350  (may be null)
2351  <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
2352  <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
2353  <LI><B>SQL_DATA_TYPE</B> int => unused
2354  <LI><B>SQL_DATETIME_SUB</B> int => unused
2355  <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
2356  </OL>
2357 
2358  @return <code>ResultSet</code> - each row is an SQL type description
2359 }
2360 function TZMsSqlDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
2361 begin
2362  Result:=inherited UncachedGetTypeInfo;
2363 
2364  with GetStatement.ExecuteQuery('exec sp_datatype_info') do
2365  begin
2366  while Next do
2367  begin
2368  Result.MoveToInsertRow;
2369  Result.UpdateStringByName('TYPE_NAME',
2370  GetStringByName('TYPE_NAME'));
2371  Result.UpdateShortByName('DATA_TYPE',
2372  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
2373  Result.UpdateIntByName('PRECISION',
2374  GetIntByName('PRECISION'));
2375  Result.UpdateStringByName('LITERAL_PREFIX',
2376  GetStringByName('LITERAL_PREFIX'));
2377  Result.UpdateStringByName('LITERAL_SUFFIX',
2378  GetStringByName('LITERAL_SUFFIX'));
2379  Result.UpdateStringByName('CREATE_PARAMS',
2380  GetStringByName('CREATE_PARAMS'));
2381  Result.UpdateShortByName('NULLABLE',
2382  GetShortByName('NULLABLE'));
2383  Result.UpdateBooleanByName('CASE_SENSITIVE',
2384  GetShortByName('CASE_SENSITIVE') = 1);
2385  Result.UpdateShortByName('SEARCHABLE',
2386  GetShortByName('SEARCHABLE'));
2387  Result.UpdateBooleanByName('UNSIGNED_ATTRIBUTE',
2388  GetShortByName('UNSIGNED_ATTRIBUTE') = 1);
2389  Result.UpdateBooleanByName('FIXED_PREC_SCALE',
2390  GetShortByName('MONEY') = 1);
2391  Result.UpdateBooleanByName('AUTO_INCREMENT',
2392  GetShortByName('AUTO_INCREMENT') = 1);
2393  Result.UpdateStringByName('LOCAL_TYPE_NAME',
2394  GetStringByName('LOCAL_TYPE_NAME'));
2395  Result.UpdateShortByName('MINIMUM_SCALE',
2396  GetShortByName('MINIMUM_SCALE'));
2397  Result.UpdateShortByName('MAXIMUM_SCALE',
2398  GetShortByName('MAXIMUM_SCALE'));
2399  Result.UpdateShortByName('SQL_DATA_TYPE',
2400  GetShortByName('SQL_DATA_TYPE'));
2401  Result.UpdateShortByName('SQL_DATETIME_SUB',
2402  GetShortByName('SQL_DATETIME_SUB'));
2403  Result.UpdateShortByName('NUM_PREC_RADIX',
2404  GetShortByName('NUM_PREC_RADIX'));
2405  Result.InsertRow;
2406  end;
2407  Close;
2408  end;
2409  Result.BeforeFirst;
2410 end;
2411 
2412 {**
2413  Gets a description of a table's indices and statistics. They are
2414  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
2415 
2416  <P>Each index column description has the following columns:
2417  <OL>
2418  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2419  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2420  <LI><B>TABLE_NAME</B> String => table name
2421  <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
2422  false when TYPE is tableIndexStatistic
2423  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
2424  null when TYPE is tableIndexStatistic
2425  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
2426  tableIndexStatistic
2427  <LI><B>TYPE</B> short => index type:
2428  <UL>
2429  <LI> tableIndexStatistic - this identifies table statistics that are
2430  returned in conjuction with a table's index descriptions
2431  <LI> tableIndexClustered - this is a clustered index
2432  <LI> tableIndexHashed - this is a hashed index
2433  <LI> tableIndexOther - this is some other style of index
2434  </UL>
2435  <LI><B>ORDINAL_POSITION</B> short => column sequence number
2436  within index; zero when TYPE is tableIndexStatistic
2437  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
2438  tableIndexStatistic
2439  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
2440  "D" => descending, may be null if sort sequence is not supported;
2441  null when TYPE is tableIndexStatistic
2442  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
2443  this is the number of rows in the table; otherwise, it is the
2444  number of unique values in the index.
2445  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
2446  this is the number of pages used for the table, otherwise it
2447  is the number of pages used for the current index.
2448  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
2449  (may be null)
2450  </OL>
2451 
2452  @param catalog a catalog name; "" retrieves those without a
2453  catalog; null means drop catalog name from the selection criteria
2454  @param schema a schema name; "" retrieves those without a schema
2455  @param table a table name
2456  @param unique when true, return only indices for unique values;
2457  when false, return indices regardless of whether unique or not
2458  @param approximate when true, result is allowed to reflect approximate
2459  or out of data values; when false, results are requested to be
2460  accurate
2461  @return <code>ResultSet</code> - each row is an index column description
2462 }
2463 function TZMsSqlDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
2464  const Schema: string; const Table: string; Unique: Boolean;
2465  Approximate: Boolean): IZResultSet;
2466 var
2467  Is_Unique, Accuracy: string;
2468 begin
2469  Result:=inherited UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
2470 
2471  if Unique then
2472  Is_Unique := '''Y'''
2473  else Is_Unique := '''N''';
2474  if Approximate then
2475  Accuracy := '''Q'''
2476  else Accuracy := '''E''';
2477 
2478  with GetStatement.ExecuteQuery(
2479  Format('exec sp_statistics %s, %s, %s, ''%%'', %s, %s',
2480  [ComposeObjectString(Table), ComposeObjectString(Schema), ComposeObjectString(Catalog), Is_Unique, Accuracy])) do
2481  begin
2482  while Next do
2483  begin
2484  Result.MoveToInsertRow;
2485  Result.UpdateStringByName('TABLE_CAT',
2486  GetStringByName('TABLE_QUALIFIER'));
2487  Result.UpdateStringByName('TABLE_SCHEM',
2488  GetStringByName('TABLE_OWNER'));
2489  Result.UpdateStringByName('TABLE_NAME',
2490  GetStringByName('TABLE_NAME'));
2491  Result.UpdateBooleanByName('NON_UNIQUE',
2492  GetShortByName('NON_UNIQUE') = 1);
2493  Result.UpdateStringByName('INDEX_QUALIFIER',
2494  GetStringByName('INDEX_QUALIFIER'));
2495  Result.UpdateStringByName('INDEX_NAME',
2496  GetStringByName('INDEX_NAME'));
2497  Result.UpdateShortByName('TYPE',
2498  GetShortByName('TYPE'));
2499  Result.UpdateShortByName('ORDINAL_POSITION',
2500  GetShortByName('SEQ_IN_INDEX'));
2501  Result.UpdateStringByName('COLUMN_NAME',
2502  GetStringByName('COLUMN_NAME'));
2503  Result.UpdateStringByName('ASC_OR_DESC',
2504  GetStringByName('COLLATION'));
2505  Result.UpdateIntByName('CARDINALITY',
2506  GetIntByName('CARDINALITY'));
2507  Result.UpdateIntByName('PAGES',
2508  GetIntByName('PAGES'));
2509  Result.UpdateStringByName('FILTER_CONDITION',
2510  GetStringByName('FILTER_CONDITION'));
2511  Result.InsertRow;
2512  end;
2513  Close;
2514  end;
2515  Result.BeforeFirst;
2516 end;
2517 
2518 { TZSybaseDatabaseMetadata }
2519 
2520 {**
2521  Constructs a database information object and returns the interface to it. Used
2522  internally by the constructor.
2523  @return the database information object interface
2524 }
2525 function TZSybaseDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
2526 begin
2527  Result := TZSybaseDatabaseInfo.Create(Self);
2528 end;
2529 
2530 {**
2531  Gets a description of the stored procedures available in a
2532  catalog.
2533 
2534  <P>Only procedure descriptions matching the schema and
2535  procedure name criteria are returned. They are ordered by
2536  PROCEDURE_SCHEM, and PROCEDURE_NAME.
2537 
2538  <P>Each procedure description has the the following columns:
2539  <OL>
2540  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2541  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2542  <LI><B>PROCEDURE_NAME</B> String => procedure name
2543  <LI> reserved for future use
2544  <LI> reserved for future use
2545  <LI> reserved for future use
2546  <LI><B>REMARKS</B> String => explanatory comment on the procedure
2547  <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
2548  <UL>
2549  <LI> procedureResultUnknown - May return a result
2550  <LI> procedureNoResult - Does not return a result
2551  <LI> procedureReturnsResult - Returns a result
2552  </UL>
2553  </OL>
2554 
2555  @param catalog a catalog name; "" retrieves those without a
2556  catalog; null means drop catalog name from the selection criteria
2557  @param schemaPattern a schema name pattern; "" retrieves those
2558  without a schema
2559  @param procedureNamePattern a procedure name pattern
2560  @return <code>ResultSet</code> - each row is a procedure description
2561  @see #getSearchStringEscape
2562 }
2563 function TZSybaseDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
2564  const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
2565 begin
2566  Result:=inherited UncachedGetProcedures(Catalog, SchemaPattern, ProcedureNamePattern);
2567 
2568  with GetStatement.ExecuteQuery(
2569  Format('exec sp_jdbc_stored_procedures %s, %s, %s',
2570  [ComposeObjectString(Catalog), ComposeObjectString(SchemaPattern), ComposeObjectString(ProcedureNamePattern)])) do
2571  begin
2572  while Next do
2573  begin
2574  Result.MoveToInsertRow;
2575  Result.UpdateStringByName('PROCEDURE_CAT',
2576  GetStringByName('PROCEDURE_CAT'));
2577  Result.UpdateStringByName('PROCEDURE_SCHEM',
2578  GetStringByName('PROCEDURE_SCHEM'));
2579  Result.UpdateStringByName('PROCEDURE_NAME',
2580  GetStringByName('PROCEDURE_NAME'));
2581  Result.UpdateStringByName('REMARKS',
2582  GetStringByName('REMARKS'));
2583  Result.UpdateShortByName('PROCEDURE_TYPE',
2584  GetShortByName('PROCEDURE_TYPE'));
2585  Result.InsertRow;
2586  end;
2587  Close;
2588  end;
2589 end;
2590 
2591 {**
2592  Gets a description of a catalog's stored procedure parameters
2593  and result columns.
2594 
2595  <P>Only descriptions matching the schema, procedure and
2596  parameter name criteria are returned. They are ordered by
2597  PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
2598  if any, is first. Next are the parameter descriptions in call
2599  order. The column descriptions follow in column number order.
2600 
2601  <P>Each row in the <code>ResultSet</code> is a parameter description or
2602  column description with the following fields:
2603  <OL>
2604  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2605  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2606  <LI><B>PROCEDURE_NAME</B> String => procedure name
2607  <LI><B>COLUMN_NAME</B> String => column/parameter name
2608  <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
2609  <UL>
2610  <LI> procedureColumnUnknown - nobody knows
2611  <LI> procedureColumnIn - IN parameter
2612  <LI> procedureColumnInOut - INOUT parameter
2613  <LI> procedureColumnOut - OUT parameter
2614  <LI> procedureColumnReturn - procedure return value
2615  <LI> procedureColumnResult - result column in <code>ResultSet</code>
2616  </UL>
2617  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2618  <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
2619  type name is fully qualified
2620  <LI><B>PRECISION</B> int => precision
2621  <LI><B>LENGTH</B> int => length in bytes of data
2622  <LI><B>SCALE</B> short => scale
2623  <LI><B>RADIX</B> short => radix
2624  <LI><B>NULLABLE</B> short => can it contain NULL?
2625  <UL>
2626  <LI> procedureNoNulls - does not allow NULL values
2627  <LI> procedureNullable - allows NULL values
2628  <LI> procedureNullableUnknown - nullability unknown
2629  </UL>
2630  <LI><B>REMARKS</B> String => comment describing parameter/column
2631  </OL>
2632 
2633  <P><B>Note:</B> Some databases may not return the column
2634  descriptions for a procedure. Additional columns beyond
2635  REMARKS can be defined by the database.
2636 
2637  @param catalog a catalog name; "" retrieves those without a
2638  catalog; null means drop catalog name from the selection criteria
2639  @param schemaPattern a schema name pattern; "" retrieves those
2640  without a schema
2641  @param procedureNamePattern a procedure name pattern
2642  @param columnNamePattern a column name pattern
2643  @return <code>ResultSet</code> - each row describes a stored procedure parameter or
2644  column
2645  @see #getSearchStringEscape
2646 }
2647 function TZSybaseDatabaseMetadata.UncachedGetProcedureColumns(const Catalog: string;
2648  const SchemaPattern: string; const ProcedureNamePattern: string;
2649  const ColumnNamePattern: string): IZResultSet;
2650 var
2651  ProcNamePart: string;
2652  NumberPart: string;
2653  status2: Integer;
2654 begin
2655  Result:=inherited UncachedGetProcedureColumns(Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern);
2656 
2657  with GetStatement.ExecuteQuery(
2658  Format('exec sp_jdbc_getprocedurecolumns %s, %s, %s, %s',
2659  [ComposeObjectString(Catalog), ComposeObjectString(SchemaPattern), ComposeObjectString(ProcedureNamePattern), ComposeObjectString(ColumnNamePattern)])) do
2660  begin
2661  while Next do
2662  begin
2663  Result.MoveToInsertRow;
2664  Result.UpdateStringByName('PROCEDURE_CAT',
2665  GetStringByName('PROCEDURE_CAT'));
2666  Result.UpdateStringByName('PROCEDURE_SCHEM',
2667  GetStringByName('PROCEDURE_SCHEM'));
2668  Result.UpdateStringByName('PROCEDURE_NAME',
2669  GetStringByName('PROCEDURE_NAME'));
2670  Result.UpdateStringByName('COLUMN_NAME',
2671  GetStringByName('COLUMN_NAME'));
2672  case GetShortByName('COLUMN_TYPE') of
2673  0, 1: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctIn));
2674  2: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
2675  3: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
2676  4: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
2677  5: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctReturn));
2678  else
2679  Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
2680  end;
2681  Result.UpdateShortByName('DATA_TYPE',
2682  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
2683  Result.UpdateStringByName('TYPE_NAME',
2684  GetStringByName('TYPE_NAME'));
2685  Result.UpdateIntByName('PRECISION',
2686  GetIntByName('PRECISION'));
2687  Result.UpdateIntByName('LENGTH',
2688  GetIntByName('LENGTH'));
2689  Result.UpdateShortByName('SCALE',
2690  GetShortByName('SCALE'));
2691  Result.UpdateShortByName('RADIX',
2692  GetShortByName('RADIX'));
2693  Result.UpdateShortByName('NULLABLE',
2694  GetShortByName('NULLABLE'));
2695  Result.UpdateStringByName('REMARKS',
2696  GetStringByName('REMARKS'));
2697  Result.InsertRow;
2698  end;
2699  Close;
2700  end;
2701  Result.BeforeFirst;
2702 
2703  NumberPart := '1';
2704  ProcNamePart := '';
2705  if AnsiPos(';', ProcNamePart) > 0 then
2706  begin
2707  NumberPart := Copy(ProcNamePart, LastDelimiter(';', ProcNamePart) + 1,
2708  Length(ProcNamePart));
2709  if NumberPart = '' then
2710  NumberPart := '1';
2711 
2712  ProcNamePart := Copy(ProcNamePart, 1, LastDelimiter(';', ProcNamePart));
2713  if ProcNamePart[Length(ProcNamePart)] = ';' then
2714  Delete(ProcNamePart, Length(ProcNamePart), 1);
2715  end;
2716  //status2 is added in sybase ASE 12.5 to store the storedprocedure parameters
2717  // input/output type this column does not exists in prior versions.
2718  // In prior versions there is no way to determine between input or output type.
2719  with GetStatement.ExecuteQuery(
2720  Format('select c.* from syscolumns c inner join sysobjects o on'
2721  + ' (o.id = c.id) where o.name = %s and c.number = %s order by colid',
2722  [AnsiQuotedStr(ProcNamePart, ''''), NumberPart])) do
2723  begin
2724  Result.Next;//Skip return parameter
2725  while Next do
2726  begin
2727  Result.Next;
2728  if FindColumn('status2') >= 1 then
2729  status2 := GetShortByName('status2')
2730  else
2731  status2 := 0;
2732  case status2 of
2733  0, 1: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctIn));
2734  2: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
2735  3: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
2736  4: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctInOut));
2737  5: Result.UpdateShortByName('COLUMN_TYPE', Ord(pctReturn));
2738  else
2739  Result.UpdateShortByName('COLUMN_TYPE', Ord(pctUnknown));
2740  end;
2741  Result.UpdateRow;
2742  end;
2743  Close;
2744  end;
2745 end;
2746 
2747 {**
2748  Gets a description of tables available in a catalog.
2749 
2750  <P>Only table descriptions matching the catalog, schema, table
2751  name and type criteria are returned. They are ordered by
2752  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
2753 
2754  <P>Each table description has the following columns:
2755  <OL>
2756  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2757  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2758  <LI><B>TABLE_NAME</B> String => table name
2759  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2760  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2761  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2762  <LI><B>REMARKS</B> String => explanatory comment on the table
2763  </OL>
2764 
2765  <P><B>Note:</B> Some databases may not return information for
2766  all tables.
2767 
2768  @param catalog a catalog name; "" retrieves those without a
2769  catalog; null means drop catalog name from the selection criteria
2770  @param schemaPattern a schema name pattern; "" retrieves those
2771  without a schema
2772  @param tableNamePattern a table name pattern
2773  @param types a list of table types to include; null returns all types
2774  @return <code>ResultSet</code> - each row is a table description
2775  @see #getSearchStringEscape
2776 }
2777 function TZSybaseDatabaseMetadata.UncachedGetTables(const Catalog: string;
2778  const SchemaPattern: string; const TableNamePattern: string;
2779  const Types: TStringDynArray): IZResultSet;
2780 var
2781  I: Integer;
2782  TableTypes: string;
2783 begin
2784  Result:=inherited UncachedGetTables(Catalog, SchemaPattern, TableNamePattern, Types);
2785 
2786  TableTypes := '';
2787  for I := 0 to Length(Types) - 1 do
2788  begin
2789  if TableTypes <> '' then
2790  TableTypes := TableTypes + ',';
2791  TableTypes := TableTypes + AnsiQuotedStr(Types[I], '''');
2792  end;
2793 
2794  with GetStatement.ExecuteQuery(
2795  Format('exec sp_jdbc_tables %s, %s, %s, %s',
2796  [ComposeObjectString(TableNamePattern), ComposeObjectString(SchemaPattern), ComposeObjectString(Catalog), ComposeObjectString(TableTypes)])) do
2797  begin
2798  while Next do
2799  while Next do
2800  begin
2801  Result.MoveToInsertRow;
2802  Result.UpdateStringByName('TABLE_CAT',
2803  GetStringByName('TABLE_CAT'));
2804  Result.UpdateStringByName('TABLE_SCHEM',
2805  GetStringByName('TABLE_SCHEM'));
2806  Result.UpdateStringByName('TABLE_NAME',
2807  GetStringByName('TABLE_NAME'));
2808  Result.UpdateStringByName('TABLE_TYPE',
2809  GetStringByName('TABLE_TYPE'));
2810  Result.UpdateStringByName('REMARKS',
2811  GetStringByName('REMARKS'));
2812  Result.InsertRow;
2813  end;
2814  Close;
2815  end;
2816 end;
2817 
2818 {**
2819  Gets the schema names available in this database. The results
2820  are ordered by schema name.
2821 
2822  <P>The schema column is:
2823  <OL>
2824  <LI><B>TABLE_SCHEM</B> String => schema name
2825  </OL>
2826 
2827  @return <code>ResultSet</code> - each row has a single String column that is a
2828  schema name
2829 }
2830 function TZSybaseDatabaseMetadata.UncachedGetSchemas: IZResultSet;
2831 begin
2832  Result:=inherited UncachedGetSchemas;
2833 
2834  with GetStatement.ExecuteQuery('exec sp_jdbc_getschemas') do
2835  begin
2836  while Next do
2837  begin
2838  Result.MoveToInsertRow;
2839  Result.UpdateStringByName('TABLE_SCHEM',
2840  GetStringByName('TABLE_SCHEM'));
2841  Result.InsertRow;
2842  end;
2843  Close;
2844  end;
2845 end;
2846 
2847 {**
2848  Gets the catalog names available in this database. The results
2849  are ordered by catalog name.
2850 
2851  <P>The catalog column is:
2852  <OL>
2853  <LI><B>TABLE_CAT</B> String => catalog name
2854  </OL>
2855 
2856  @return <code>ResultSet</code> - each row has a single String column that is a
2857  catalog name
2858 }
2859 function TZSybaseDatabaseMetadata.UncachedGetCatalogs: IZResultSet;
2860 begin
2861  Result:=inherited UncachedGetCatalogs;
2862 
2863  with GetStatement.ExecuteQuery('exec sp_jdbc_getcatalogs') do
2864  begin
2865  while Next do
2866  begin
2867  Result.MoveToInsertRow;
2868  Result.UpdateStringByName('TABLE_CAT',
2869  GetStringByName('TABLE_CAT'));
2870  Result.InsertRow;
2871  end;
2872  Close;
2873  end;
2874 end;
2875 
2876 {**
2877  Gets the table types available in this database. The results
2878  are ordered by table type.
2879 
2880  <P>The table type is:
2881  <OL>
2882  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2883  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2884  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2885  </OL>
2886 
2887  @return <code>ResultSet</code> - each row has a single String column that is a
2888  table type
2889 }
2890 function TZSybaseDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
2891 const
2892  TableTypes: array[0..2] of string = ('SYSTEM TABLE', 'TABLE', 'VIEW');
2893 var
2894  I: Integer;
2895 begin
2896  Result:=inherited UncachedGetTableTypes;
2897 
2898  for I := 0 to 2 do
2899  begin
2900  Result.MoveToInsertRow;
2901  Result.UpdateStringByName('TABLE_TYPE', TableTypes[I]);
2902  Result.InsertRow;
2903  end;
2904 end;
2905 
2906 {**
2907  Gets a description of table columns available in
2908  the specified catalog.
2909 
2910  <P>Only column descriptions matching the catalog, schema, table
2911  and column name criteria are returned. They are ordered by
2912  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
2913 
2914  <P>Each column description has the following columns:
2915  <OL>
2916  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2917  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2918  <LI><B>TABLE_NAME</B> String => table name
2919  <LI><B>COLUMN_NAME</B> String => column name
2920  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2921  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
2922  for a UDT the type name is fully qualified
2923  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
2924  types this is the maximum number of characters, for numeric or
2925  decimal types this is precision.
2926  <LI><B>BUFFER_LENGTH</B> is not used.
2927  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
2928  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
2929  <LI><B>NULLABLE</B> int => is NULL allowed?
2930  <UL>
2931  <LI> columnNoNulls - might not allow NULL values
2932  <LI> columnNullable - definitely allows NULL values
2933  <LI> columnNullableUnknown - nullability unknown
2934  </UL>
2935  <LI><B>REMARKS</B> String => comment describing column (may be null)
2936  <LI><B>COLUMN_DEF</B> String => default value (may be null)
2937  <LI><B>SQL_DATA_TYPE</B> int => unused
2938  <LI><B>SQL_DATETIME_SUB</B> int => unused
2939  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
2940  maximum number of bytes in the column
2941  <LI><B>ORDINAL_POSITION</B> int => index of column in table
2942  (starting at 1)
2943  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
2944  does not allow NULL values; "YES" means the column might
2945  allow NULL values. An empty string means nobody knows.
2946  </OL>
2947 
2948  @param catalog a catalog name; "" retrieves those without a
2949  catalog; null means drop catalog name from the selection criteria
2950  @param schemaPattern a schema name pattern; "" retrieves those
2951  without a schema
2952  @param tableNamePattern a table name pattern
2953  @param columnNamePattern a column name pattern
2954  @return <code>ResultSet</code> - each row is a column description
2955  @see #getSearchStringEscape
2956 }
2957 function TZSybaseDatabaseMetadata.UncachedGetColumns(const Catalog: string;
2958  const SchemaPattern: string; const TableNamePattern: string;
2959  const ColumnNamePattern: string): IZResultSet;
2960 begin
2961  Result:=inherited UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
2962 
2963  with GetStatement.ExecuteQuery('exec '+GetSP_Prefix(Catalog, SchemaPattern)+
2964  'sp_jdbc_columns '+ComposeObjectString(TableNamePattern)+', '+
2965  ComposeObjectString(SchemaPattern)+', '+ComposeObjectString(Catalog)+', '+
2966  ComposeObjectString(ColumnNamePattern)) do
2967  begin
2968  while Next do
2969  begin
2970  Result.MoveToInsertRow;
2971  Result.UpdateStringByName('TABLE_CAT',
2972  ''{GetStringByName('TABLE_CAT')});
2973  Result.UpdateStringByName('TABLE_SCHEM',
2974  ''{GetStringByName('TABLE_SCHEM')});
2975  Result.UpdateStringByName('TABLE_NAME',
2976  GetStringByName('TABLE_NAME'));
2977  Result.UpdateStringByName('COLUMN_NAME',
2978  GetStringByName('COLUMN_NAME'));
2979  //The value in the resultset will be used
2980  // Result.UpdateShortByName('DATA_TYPE',
2981  // Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
2982  Result.UpdateStringByName('TYPE_NAME',
2983  GetStringByName('TYPE_NAME'));
2984  Result.UpdateIntByName('COLUMN_SIZE',
2985  GetIntByName('COLUMN_SIZE'));
2986  Result.UpdateIntByName('BUFFER_LENGTH',
2987  GetIntByName('BUFFER_LENGTH'));
2988  Result.UpdateIntByName('DECIMAL_DIGITS',
2989  GetIntByName('DECIMAL_DIGITS'));
2990  Result.UpdateIntByName('NUM_PREC_RADIX',
2991  GetShortByName('NUM_PREC_RADIX'));
2992  Result.UpdateShortByName('NULLABLE',
2993  GetShortByName('NULLABLE'));
2994  Result.UpdateStringByName('REMARKS',
2995  GetStringByName('REMARKS'));
2996  Result.UpdateStringByName('COLUMN_DEF',
2997  GetStringByName('COLUMN_DEF'));
2998  Result.UpdateShortByName('SQL_DATA_TYPE',
2999  GetShortByName('SQL_DATA_TYPE'));
3000  Result.UpdateShortByName('SQL_DATETIME_SUB',
3001  GetShortByName('SQL_DATETIME_SUB'));
3002  Result.UpdateIntByName('CHAR_OCTET_LENGTH',
3003  GetIntByName('CHAR_OCTET_LENGTH'));
3004  Result.UpdateIntByName('ORDINAL_POSITION',
3005  GetIntByName('ORDINAL_POSITION'));
3006  Result.UpdateStringByName('IS_NULLABLE',
3007  GetStringByName('IS_NULLABLE'));
3008  Result.InsertRow;
3009  end;
3010  Close;
3011  end;
3012  Result.BeforeFirst;
3013  with GetStatement.ExecuteQuery(
3014  Format('select c.colid, c.name, c.type, c.prec, c.scale, c.status'
3015  + ' from syscolumns c inner join sysobjects o on (o.id = c.id)'
3016  + ' where o.name = %s order by colid', [AnsiQuotedStr(TableNamePattern, '''')])) do
3017  begin
3018  while Next do
3019  begin
3020  Result.Next;
3021  Result.UpdateBooleanByName('AUTO_INCREMENT',
3022  (GetShortByName('status') and $80) <> 0);
3023  Result.UpdateNullByName('CASE_SENSITIVE');
3024  Result.UpdateBooleanByName('SEARCHABLE',
3025  not (GetShortByName('type') in [34, 35]));
3026  Result.UpdateBooleanByName('WRITABLE',
3027  ((GetShortByName('status') and $80) = 0)
3028  (*and (GetShortByName('type') <> 37)*)); // <<<< *DEBUG WARUM?
3029  Result.UpdateBooleanByName('DEFINITELYWRITABLE',
3030  Result.GetBooleanByName('WRITABLE'));
3031  Result.UpdateBooleanByName('READONLY',
3032  not Result.GetBooleanByName('WRITABLE'));
3033  if Result.GetBooleanByName('AUTO_INCREMENT') then
3034  begin
3035  Result.UpdateShortByName('NULLABLE', 1);
3036  Result.UpdateStringByName('IS_NULLABLE', 'YES');
3037  end;
3038  Result.UpdateRow;
3039  end;
3040  Close;
3041  end;
3042 end;
3043 
3044 {**
3045  Gets a description of the access rights for a table's columns.
3046 
3047  <P>Only privileges matching the column name criteria are
3048  returned. They are ordered by COLUMN_NAME and PRIVILEGE.
3049 
3050  <P>Each privilige description has the following columns:
3051  <OL>
3052  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3053  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3054  <LI><B>TABLE_NAME</B> String => table name
3055  <LI><B>COLUMN_NAME</B> String => column name
3056  <LI><B>GRANTOR</B> => grantor of access (may be null)
3057  <LI><B>GRANTEE</B> String => grantee of access
3058  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
3059  INSERT, UPDATE, REFRENCES, ...)
3060  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
3061  to grant to others; "NO" if not; null if unknown
3062  </OL>
3063 
3064  @param catalog a catalog name; "" retrieves those without a
3065  catalog; null means drop catalog name from the selection criteria
3066  @param schema a schema name; "" retrieves those without a schema
3067  @param table a table name
3068  @param columnNamePattern a column name pattern
3069  @return <code>ResultSet</code> - each row is a column privilege description
3070  @see #getSearchStringEscape
3071 }
3072 function TZSybaseDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
3073  const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
3074 begin
3075  Result:=inherited UncachedGetColumnPrivileges(Catalog, Schema, Table, ColumnNamePattern);
3076 
3077  with GetStatement.ExecuteQuery(
3078  Format('exec sp_jdbc_getcolumnprivileges %s, %s, %s, %s',
3079  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table),
3080  ComposeObjectString(ColumnNamePattern, '''%''')])) do
3081  begin
3082  while Next do
3083  begin
3084  Result.MoveToInsertRow;
3085  Result.UpdateStringByName('TABLE_CAT',
3086  GetStringByName('TABLE_CAT'));
3087  Result.UpdateStringByName('TABLE_SCHEM',
3088  GetStringByName('TABLE_SCHEM'));
3089  Result.UpdateStringByName('TABLE_NAME',
3090  GetStringByName('TABLE_NAME'));
3091  Result.UpdateStringByName('COLUMN_NAME',
3092  GetStringByName('COLUMN_NAME'));
3093  Result.UpdateStringByName('GRANTOR',
3094  GetStringByName('GRANTOR'));
3095  Result.UpdateStringByName('GRANTEE',
3096  GetStringByName('GRANTEE'));
3097  Result.UpdateStringByName('PRIVILEGE',
3098  GetStringByName('PRIVILEGE'));
3099  Result.UpdateStringByName('IS_GRANTABLE',
3100  GetStringByName('IS_GRANTABLE'));
3101  Result.InsertRow;
3102  end;
3103  Close;
3104  end;
3105 end;
3106 
3107 {**
3108  Gets a description of the access rights for each table available
3109  in a catalog. Note that a table privilege applies to one or
3110  more columns in the table. It would be wrong to assume that
3111  this priviledge applies to all columns (this may be true for
3112  some systems but is not true for all.)
3113 
3114  <P>Only privileges matching the schema and table name
3115  criteria are returned. They are ordered by TABLE_SCHEM,
3116  TABLE_NAME, and PRIVILEGE.
3117 
3118  <P>Each privilige description has the following columns:
3119  <OL>
3120  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3121  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3122  <LI><B>TABLE_NAME</B> String => table name
3123  <LI><B>GRANTOR</B> => grantor of access (may be null)
3124  <LI><B>GRANTEE</B> String => grantee of access
3125  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
3126  INSERT, UPDATE, REFRENCES, ...)
3127  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
3128  to grant to others; "NO" if not; null if unknown
3129  </OL>
3130 
3131  @param catalog a catalog name; "" retrieves those without a
3132  catalog; null means drop catalog name from the selection criteria
3133  @param schemaPattern a schema name pattern; "" retrieves those
3134  without a schema
3135  @param tableNamePattern a table name pattern
3136  @return <code>ResultSet</code> - each row is a table privilege description
3137  @see #getSearchStringEscape
3138 }
3139 function TZSybaseDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
3140  const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
3141 begin
3142  Result:=inherited UncachedGetTablePrivileges(Catalog, SchemaPattern, TableNamePattern);
3143 
3144  with GetStatement.ExecuteQuery(
3145  Format('exec sp_jdbc_gettableprivileges %s, %s, %s',
3146  [ComposeObjectString(Catalog), ComposeObjectString(SchemaPattern), ComposeObjectString(TableNamePattern)])) do
3147  begin
3148  while Next do
3149  begin
3150  Result.MoveToInsertRow;
3151  Result.UpdateStringByName('TABLE_CAT',
3152  GetStringByName('TABLE_CAT'));
3153  Result.UpdateStringByName('TABLE_SCHEM',
3154  GetStringByName('TABLE_SCHEM'));
3155  Result.UpdateStringByName('TABLE_NAME',
3156  GetStringByName('TABLE_NAME'));
3157  Result.UpdateStringByName('GRANTOR',
3158  GetStringByName('GRANTOR'));
3159  Result.UpdateStringByName('GRANTEE',
3160  GetStringByName('GRANTEE'));
3161  Result.UpdateStringByName('PRIVILEGE',
3162  GetStringByName('PRIVILEGE'));
3163  Result.UpdateStringByName('IS_GRANTABLE',
3164  GetStringByName('IS_GRANTABLE'));
3165  Result.InsertRow;
3166  end;
3167  Close;
3168  end;
3169 end;
3170 
3171 {**
3172  Gets a description of a table's columns that are automatically
3173  updated when any value in a row is updated. They are
3174  unordered.
3175 
3176  <P>Each column description has the following columns:
3177  <OL>
3178  <LI><B>SCOPE</B> short => is not used
3179  <LI><B>COLUMN_NAME</B> String => column name
3180  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3181  <LI><B>TYPE_NAME</B> String => Data source dependent type name
3182  <LI><B>COLUMN_SIZE</B> int => precision
3183  <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
3184  <LI><B>DECIMAL_DIGITS</B> short => scale
3185  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
3186  like an Oracle ROWID
3187  <UL>
3188  <LI> versionColumnUnknown - may or may not be pseudo column
3189  <LI> versionColumnNotPseudo - is NOT a pseudo column
3190  <LI> versionColumnPseudo - is a pseudo column
3191  </UL>
3192  </OL>
3193 
3194  @param catalog a catalog name; "" retrieves those without a
3195  catalog; null means drop catalog name from the selection criteria
3196  @param schema a schema name; "" retrieves those without a schema
3197  @param table a table name
3198  @return <code>ResultSet</code> - each row is a column description
3199  @exception SQLException if a database access error occurs
3200 }
3201 function TZSybaseDatabaseMetadata.UncachedGetVersionColumns(const Catalog: string;
3202  const Schema: string; const Table: string): IZResultSet;
3203 begin
3204  Result:=inherited UncachedGetVersionColumns(Catalog, Schema, Table);
3205 
3206  with GetStatement.ExecuteQuery(
3207  Format('exec sp_jdbc_getversioncolumns %s, %s, %s',
3208  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table)])) do
3209  begin
3210  while Next do
3211  begin
3212  Result.MoveToInsertRow;
3213  Result.UpdateShortByName('SCOPE',
3214  GetShortByName('SCOPE'));
3215  Result.UpdateStringByName('COLUMN_NAME',
3216  GetStringByName('COLUMN_NAME'));
3217  Result.UpdateShortByName('DATA_TYPE',
3218  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
3219  Result.UpdateStringByName('TYPE_NAME',
3220  GetStringByName('TYPE_NAME'));
3221  Result.UpdateIntByName('COLUMN_SIZE',
3222  GetIntByName('COLUMN_SIZE'));
3223  Result.UpdateIntByName('BUFFER_LENGTH',
3224  GetIntByName('BUFFER_LENGTH'));
3225  Result.UpdateIntByName('DECIMAL_DIGITS',
3226  GetIntByName('DECIMAL_DIGITS'));
3227  Result.UpdateShortByName('PSEUDO_COLUMN',
3228  GetShortByName('PSEUDO_COLUMN'));
3229  Result.InsertRow;
3230  end;
3231  Close;
3232  end;
3233 end;
3234 
3235 {**
3236  Gets a description of a table's primary key columns. They
3237  are ordered by COLUMN_NAME.
3238 
3239  <P>Each primary key column description has the following columns:
3240  <OL>
3241  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3242  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3243  <LI><B>TABLE_NAME</B> String => table name
3244  <LI><B>COLUMN_NAME</B> String => column name
3245  <LI><B>KEY_SEQ</B> short => sequence number within primary key
3246  <LI><B>PK_NAME</B> String => primary key name (may be null)
3247  </OL>
3248 
3249  @param catalog a catalog name; "" retrieves those without a
3250  catalog; null means drop catalog name from the selection criteria
3251  @param schema a schema name; "" retrieves those
3252  without a schema
3253  @param table a table name
3254  @return <code>ResultSet</code> - each row is a primary key column description
3255  @exception SQLException if a database access error occurs
3256 }
3257 function TZSybaseDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
3258  const Schema: string; const Table: string): IZResultSet;
3259 begin
3260  Result:=inherited UncachedGetPrimaryKeys(Catalog, Schema, Table);
3261 
3262  with GetStatement.ExecuteQuery(
3263  Format('exec sp_jdbc_primarykey %s, %s, %s',
3264  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table)])) do
3265  begin
3266  while Next do
3267  begin
3268  Result.MoveToInsertRow;
3269  Result.UpdateStringByName('TABLE_CAT',
3270  GetStringByName('TABLE_CAT'));
3271  Result.UpdateStringByName('TABLE_SCHEM',
3272  GetStringByName('TABLE_SCHEM'));
3273  Result.UpdateStringByName('TABLE_NAME',
3274  GetStringByName('TABLE_NAME'));
3275  Result.UpdateStringByName('COLUMN_NAME',
3276  GetStringByName('COLUMN_NAME'));
3277  Result.UpdateShortByName('KEY_SEQ',
3278  GetShortByName('KEY_SEQ'));
3279  Result.UpdateStringByName('PK_NAME',
3280  GetStringByName('PK_NAME'));
3281  Result.InsertRow;
3282  end;
3283  Close;
3284  end;
3285 end;
3286 
3287 {**
3288  Gets a description of the primary key columns that are
3289  referenced by a table's foreign key columns (the primary keys
3290  imported by a table). They are ordered by PKTABLE_CAT,
3291  PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
3292 
3293  <P>Each primary key column description has the following columns:
3294  <OL>
3295  <LI><B>PKTABLE_CAT</B> String => primary key table catalog
3296  being imported (may be null)
3297  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
3298  being imported (may be null)
3299  <LI><B>PKTABLE_NAME</B> String => primary key table name
3300  being imported
3301  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3302  being imported
3303  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3304  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3305  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3306  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3307  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3308  <LI><B>UPDATE_RULE</B> short => What happens to
3309  foreign key when primary is updated:
3310  <UL>
3311  <LI> importedNoAction - do not allow update of primary
3312  key if it has been imported
3313  <LI> importedKeyCascade - change imported key to agree
3314  with primary key update
3315  <LI> importedKeySetNull - change imported key to NULL if
3316  its primary key has been updated
3317  <LI> importedKeySetDefault - change imported key to default values
3318  if its primary key has been updated
3319  <LI> importedKeyRestrict - same as importedKeyNoAction
3320  (for ODBC 2.x compatibility)
3321  </UL>
3322  <LI><B>DELETE_RULE</B> short => What happens to
3323  the foreign key when primary is deleted.
3324  <UL>
3325  <LI> importedKeyNoAction - do not allow delete of primary
3326  key if it has been imported
3327  <LI> importedKeyCascade - delete rows that import a deleted key
3328  <LI> importedKeySetNull - change imported key to NULL if
3329  its primary key has been deleted
3330  <LI> importedKeyRestrict - same as importedKeyNoAction
3331  (for ODBC 2.x compatibility)
3332  <LI> importedKeySetDefault - change imported key to default if
3333  its primary key has been deleted
3334  </UL>
3335  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3336  <LI><B>PK_NAME</B> String => primary key name (may be null)
3337  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3338  constraints be deferred until commit
3339  <UL>
3340  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3341  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3342  <LI> importedKeyNotDeferrable - see SQL92 for definition
3343  </UL>
3344  </OL>
3345 
3346  @param catalog a catalog name; "" retrieves those without a
3347  catalog; null means drop catalog name from the selection criteria
3348  @param schema a schema name; "" retrieves those
3349  without a schema
3350  @param table a table name
3351  @return <code>ResultSet</code> - each row is a primary key column description
3352  @see #getExportedKeys
3353 }
3354 function TZSybaseDatabaseMetadata.UncachedGetImportedKeys(const Catalog: string;
3355  const Schema: string; const Table: string): IZResultSet;
3356 begin
3357  Result:=inherited UncachedGetImportedKeys(Catalog, Schema, Table);
3358 
3359  with GetStatement.ExecuteQuery(
3360  Format('exec sp_jdbc_importkey %s, %s, %s',
3361  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table)])) do
3362  begin
3363  while Next do
3364  begin
3365  Result.MoveToInsertRow;
3366  Result.UpdateStringByName('PKTABLE_CAT',
3367  GetStringByName('PKTABLE_CAT'));
3368  Result.UpdateStringByName('PKTABLE_SCHEM',
3369  GetStringByName('PKTABLE_SCHEM'));
3370  Result.UpdateStringByName('PKTABLE_NAME',
3371  GetStringByName('PKTABLE_NAME'));
3372  Result.UpdateStringByName('PKCOLUMN_NAME',
3373  GetStringByName('PKCOLUMN_NAME'));
3374  Result.UpdateStringByName('FKTABLE_CAT',
3375  GetStringByName('FKTABLE_CAT'));
3376  Result.UpdateStringByName('FKTABLE_SCHEM',
3377  GetStringByName('FKTABLE_SCHEM'));
3378  Result.UpdateStringByName('FKTABLE_NAME',
3379  GetStringByName('FKTABLE_NAME'));
3380  Result.UpdateStringByName('FKCOLUMN_NAME',
3381  GetStringByName('FKCOLUMN_NAME'));
3382  Result.UpdateShortByName('KEY_SEQ',
3383  GetShortByName('KEY_SEQ'));
3384  Result.UpdateShortByName('UPDATE_RULE',
3385  GetShortByName('UPDATE_RULE'));
3386  Result.UpdateShortByName('DELETE_RULE',
3387  GetShortByName('DELETE_RULE'));
3388  Result.UpdateStringByName('FK_NAME',
3389  GetStringByName('FK_NAME'));
3390  Result.UpdateStringByName('PK_NAME',
3391  GetStringByName('PK_NAME'));
3392  Result.UpdateIntByName('DEFERRABILITY',
3393  GetIntByName('DEFERRABILITY'));
3394  Result.InsertRow;
3395  end;
3396  Close;
3397  end;
3398 end;
3399 
3400 {**
3401  Gets a description of the foreign key columns that reference a
3402  table's primary key columns (the foreign keys exported by a
3403  table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
3404  FKTABLE_NAME, and KEY_SEQ.
3405 
3406  <P>Each foreign key column description has the following columns:
3407  <OL>
3408  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3409  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3410  <LI><B>PKTABLE_NAME</B> String => primary key table name
3411  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3412  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3413  being exported (may be null)
3414  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3415  being exported (may be null)
3416  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3417  being exported
3418  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3419  being exported
3420  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3421  <LI><B>UPDATE_RULE</B> short => What happens to
3422  foreign key when primary is updated:
3423  <UL>
3424  <LI> importedNoAction - do not allow update of primary
3425  key if it has been imported
3426  <LI> importedKeyCascade - change imported key to agree
3427  with primary key update
3428  <LI> importedKeySetNull - change imported key to NULL if
3429  its primary key has been updated
3430  <LI> importedKeySetDefault - change imported key to default values
3431  if its primary key has been updated
3432  <LI> importedKeyRestrict - same as importedKeyNoAction
3433  (for ODBC 2.x compatibility)
3434  </UL>
3435  <LI><B>DELETE_RULE</B> short => What happens to
3436  the foreign key when primary is deleted.
3437  <UL>
3438  <LI> importedKeyNoAction - do not allow delete of primary
3439  key if it has been imported
3440  <LI> importedKeyCascade - delete rows that import a deleted key
3441  <LI> importedKeySetNull - change imported key to NULL if
3442  its primary key has been deleted
3443  <LI> importedKeyRestrict - same as importedKeyNoAction
3444  (for ODBC 2.x compatibility)
3445  <LI> importedKeySetDefault - change imported key to default if
3446  its primary key has been deleted
3447  </UL>
3448  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3449  <LI><B>PK_NAME</B> String => primary key name (may be null)
3450  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3451  constraints be deferred until commit
3452  <UL>
3453  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3454  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3455  <LI> importedKeyNotDeferrable - see SQL92 for definition
3456  </UL>
3457  </OL>
3458 
3459  @param catalog a catalog name; "" retrieves those without a
3460  catalog; null means drop catalog name from the selection criteria
3461  @param schema a schema name; "" retrieves those
3462  without a schema
3463  @param table a table name
3464  @return <code>ResultSet</code> - each row is a foreign key column description
3465  @see #getImportedKeys
3466 }
3467 function TZSybaseDatabaseMetadata.UncachedGetExportedKeys(const Catalog: string;
3468  const Schema: string; const Table: string): IZResultSet;
3469 begin
3470  Result:=inherited UncachedGetExportedKeys(Catalog, Schema, Table);
3471 
3472  with GetStatement.ExecuteQuery(
3473  Format('exec sp_jdbc_exportkey %s, %s, %s',
3474  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table)])) do
3475  begin
3476  while Next do
3477  begin
3478  Result.MoveToInsertRow;
3479  Result.UpdateStringByName('PKTABLE_CAT',
3480  GetStringByName('PKTABLE_CAT'));
3481  Result.UpdateStringByName('PKTABLE_SCHEM',
3482  GetStringByName('PKTABLE_SCHEM'));
3483  Result.UpdateStringByName('PKTABLE_NAME',
3484  GetStringByName('PKTABLE_NAME'));
3485  Result.UpdateStringByName('PKCOLUMN_NAME',
3486  GetStringByName('PKCOLUMN_NAME'));
3487  Result.UpdateStringByName('FKTABLE_CAT',
3488  GetStringByName('FKTABLE_CAT'));
3489  Result.UpdateStringByName('FKTABLE_SCHEM',
3490  GetStringByName('FKTABLE_SCHEM'));
3491  Result.UpdateStringByName('FKTABLE_NAME',
3492  GetStringByName('FKTABLE_NAME'));
3493  Result.UpdateStringByName('FKCOLUMN_NAME',
3494  GetStringByName('FKCOLUMN_NAME'));
3495  Result.UpdateShortByName('KEY_SEQ',
3496  GetShortByName('KEY_SEQ'));
3497  Result.UpdateShortByName('UPDATE_RULE',
3498  GetShortByName('UPDATE_RULE'));
3499  Result.UpdateShortByName('DELETE_RULE',
3500  GetShortByName('DELETE_RULE'));
3501  Result.UpdateStringByName('FK_NAME',
3502  GetStringByName('FK_NAME'));
3503  Result.UpdateStringByName('PK_NAME',
3504  GetStringByName('PK_NAME'));
3505  Result.UpdateIntByName('DEFERRABILITY',
3506  GetIntByName('DEFERRABILITY'));
3507  Result.InsertRow;
3508  end;
3509  Close;
3510  end;
3511 end;
3512 
3513 {**
3514  Gets a description of the foreign key columns in the foreign key
3515  table that reference the primary key columns of the primary key
3516  table (describe how one table imports another's key.) This
3517  should normally return a single foreign key/primary key pair
3518  (most tables only import a foreign key from a table once.) They
3519  are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
3520  KEY_SEQ.
3521 
3522  <P>Each foreign key column description has the following columns:
3523  <OL>
3524  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3525  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3526  <LI><B>PKTABLE_NAME</B> String => primary key table name
3527  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3528  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3529  being exported (may be null)
3530  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3531  being exported (may be null)
3532  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3533  being exported
3534  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3535  being exported
3536  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3537  <LI><B>UPDATE_RULE</B> short => What happens to
3538  foreign key when primary is updated:
3539  <UL>
3540  <LI> importedNoAction - do not allow update of primary
3541  key if it has been imported
3542  <LI> importedKeyCascade - change imported key to agree
3543  with primary key update
3544  <LI> importedKeySetNull - change imported key to NULL if
3545  its primary key has been updated
3546  <LI> importedKeySetDefault - change imported key to default values
3547  if its primary key has been updated
3548  <LI> importedKeyRestrict - same as importedKeyNoAction
3549  (for ODBC 2.x compatibility)
3550  </UL>
3551  <LI><B>DELETE_RULE</B> short => What happens to
3552  the foreign key when primary is deleted.
3553  <UL>
3554  <LI> importedKeyNoAction - do not allow delete of primary
3555  key if it has been imported
3556  <LI> importedKeyCascade - delete rows that import a deleted key
3557  <LI> importedKeySetNull - change imported key to NULL if
3558  its primary key has been deleted
3559  <LI> importedKeyRestrict - same as importedKeyNoAction
3560  (for ODBC 2.x compatibility)
3561  <LI> importedKeySetDefault - change imported key to default if
3562  its primary key has been deleted
3563  </UL>
3564  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3565  <LI><B>PK_NAME</B> String => primary key name (may be null)
3566  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3567  constraints be deferred until commit
3568  <UL>
3569  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3570  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3571  <LI> importedKeyNotDeferrable - see SQL92 for definition
3572  </UL>
3573  </OL>
3574 
3575  @param primaryCatalog a catalog name; "" retrieves those without a
3576  catalog; null means drop catalog name from the selection criteria
3577  @param primarySchema a schema name; "" retrieves those
3578  without a schema
3579  @param primaryTable the table name that exports the key
3580  @param foreignCatalog a catalog name; "" retrieves those without a
3581  catalog; null means drop catalog name from the selection criteria
3582  @param foreignSchema a schema name; "" retrieves those
3583  without a schema
3584  @param foreignTable the table name that imports the key
3585  @return <code>ResultSet</code> - each row is a foreign key column description
3586  @see #getImportedKeys
3587 }
3588 function TZSybaseDatabaseMetadata.UncachedGetCrossReference(const PrimaryCatalog: string;
3589  const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
3590  const ForeignSchema: string; const ForeignTable: string): IZResultSet;
3591 begin
3592  Result:=inherited UncachedGetCrossReference(PrimaryCatalog, PrimarySchema, PrimaryTable,
3593  ForeignCatalog, ForeignSchema, ForeignTable);
3594 
3595  with GetStatement.ExecuteQuery(
3596  Format('exec sp_jdbc_getcrossreferences %s, %s, %s, %s, %s, %s',
3597  [ComposeObjectString(PrimaryCatalog), ComposeObjectString(PrimarySchema), ComposeObjectString(PrimaryTable),
3598  ComposeObjectString(ForeignCatalog), ComposeObjectString(ForeignSchema), ComposeObjectString(ForeignTable)])) do
3599  begin
3600  while Next do
3601  begin
3602  Result.MoveToInsertRow;
3603  Result.UpdateStringByName('PKTABLE_CAT',
3604  GetStringByName('PKTABLE_CAT'));
3605  Result.UpdateStringByName('PKTABLE_SCHEM',
3606  GetStringByName('PKTABLE_SCHEM'));
3607  Result.UpdateStringByName('PKTABLE_NAME',
3608  GetStringByName('PKTABLE_NAME'));
3609  Result.UpdateStringByName('PKCOLUMN_NAME',
3610  GetStringByName('PKCOLUMN_NAME'));
3611  Result.UpdateStringByName('FKTABLE_CAT',
3612  GetStringByName('FKTABLE_CAT'));
3613  Result.UpdateStringByName('FKTABLE_SCHEM',
3614  GetStringByName('FKTABLE_SCHEM'));
3615  Result.UpdateStringByName('FKTABLE_NAME',
3616  GetStringByName('FKTABLE_NAME'));
3617  Result.UpdateStringByName('FKCOLUMN_NAME',
3618  GetStringByName('FKCOLUMN_NAME'));
3619  Result.UpdateShortByName('KEY_SEQ',
3620  GetShortByName('KEY_SEQ'));
3621  Result.UpdateShortByName('UPDATE_RULE',
3622  GetShortByName('UPDATE_RULE'));
3623  Result.UpdateShortByName('DELETE_RULE',
3624  GetShortByName('DELETE_RULE'));
3625  Result.UpdateStringByName('FK_NAME',
3626  GetStringByName('FK_NAME'));
3627  Result.UpdateStringByName('PK_NAME',
3628  GetStringByName('PK_NAME'));
3629  Result.UpdateIntByName('DEFERRABILITY',
3630  GetIntByName('DEFERRABILITY'));
3631  Result.InsertRow;
3632  end;
3633  Close;
3634  end;
3635 end;
3636 
3637 {**
3638  Gets a description of all the standard SQL types supported by
3639  this database. They are ordered by DATA_TYPE and then by how
3640  closely the data type maps to the corresponding JDBC SQL type.
3641 
3642  <P>Each type description has the following columns:
3643  <OL>
3644  <LI><B>TYPE_NAME</B> String => Type name
3645  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3646  <LI><B>PRECISION</B> int => maximum precision
3647  <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
3648  (may be null)
3649  <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
3650  (may be null)
3651  <LI><B>CREATE_PARAMS</B> String => parameters used in creating
3652  the type (may be null)
3653  <LI><B>NULLABLE</B> short => can you use NULL for this type?
3654  <UL>
3655  <LI> typeNoNulls - does not allow NULL values
3656  <LI> typeNullable - allows NULL values
3657  <LI> typeNullableUnknown - nullability unknown
3658  </UL>
3659  <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
3660  <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
3661  <UL>
3662  <LI> typePredNone - No support
3663  <LI> typePredChar - Only supported with WHERE .. LIKE
3664  <LI> typePredBasic - Supported except for WHERE .. LIKE
3665  <LI> typeSearchable - Supported for all WHERE ..
3666  </UL>
3667  <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
3668  <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
3669  <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
3670  auto-increment value?
3671  <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
3672  (may be null)
3673  <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
3674  <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
3675  <LI><B>SQL_DATA_TYPE</B> int => unused
3676  <LI><B>SQL_DATETIME_SUB</B> int => unused
3677  <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
3678  </OL>
3679 
3680  @return <code>ResultSet</code> - each row is an SQL type description
3681 }
3682 function TZSybaseDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
3683 begin
3684  Result:=inherited UncachedGetTypeInfo;
3685 
3686  with GetStatement.ExecuteQuery('exec sp_jdbc_datatype_info') do
3687  begin
3688  while Next do
3689  begin
3690  Result.MoveToInsertRow;
3691  Result.UpdateStringByName('TYPE_NAME',
3692  GetStringByName('TYPE_NAME'));
3693  Result.UpdateShortByName('DATA_TYPE',
3694  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
3695  Result.UpdateIntByName('PRECISION',
3696  GetIntByName('PRECISION'));
3697  Result.UpdateStringByName('LITERAL_PREFIX',
3698  GetStringByName('LITERAL_PREFIX'));
3699  Result.UpdateStringByName('LITERAL_SUFFIX',
3700  GetStringByName('LITERAL_SUFFIX'));
3701  Result.UpdateStringByName('CREATE_PARAMS',
3702  GetStringByName('CREATE_PARAMS'));
3703  Result.UpdateShortByName('NULLABLE',
3704  GetShortByName('NULLABLE'));
3705  Result.UpdateBooleanByName('CASE_SENSITIVE',
3706  GetShortByName('CASE_SENSITIVE') = 1);
3707  Result.UpdateShortByName('SEARCHABLE',
3708  GetShortByName('SEARCHABLE'));
3709  Result.UpdateBooleanByName('UNSIGNED_ATTRIBUTE',
3710  GetShortByName('UNSIGNED_ATTRIBUTE') = 1);
3711  Result.UpdateBooleanByName('FIXED_PREC_SCALE',
3712  GetShortByName('FIXED_PREC_SCALE') = 1);
3713  Result.UpdateBooleanByName('AUTO_INCREMENT',
3714  GetShortByName('AUTO_INCREMENT') = 1);
3715  Result.UpdateStringByName('LOCAL_TYPE_NAME',
3716  GetStringByName('LOCAL_TYPE_NAME'));
3717  Result.UpdateShortByName('MINIMUM_SCALE',
3718  GetShortByName('MINIMUM_SCALE'));
3719  Result.UpdateShortByName('MAXIMUM_SCALE',
3720  GetShortByName('MAXIMUM_SCALE'));
3721  Result.UpdateShortByName('SQL_DATA_TYPE',
3722  GetShortByName('SQL_DATA_TYPE'));
3723  Result.UpdateShortByName('SQL_DATETIME_SUB',
3724  GetShortByName('SQL_DATETIME_SUB'));
3725  Result.UpdateShortByName('NUM_PREC_RADIX',
3726  GetShortByName('NUM_PREC_RADIX'));
3727  Result.InsertRow;
3728  end;
3729  Close;
3730  end;
3731 end;
3732 
3733 {**
3734  Gets a description of a table's indices and statistics. They are
3735  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
3736 
3737  <P>Each index column description has the following columns:
3738  <OL>
3739  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3740  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3741  <LI><B>TABLE_NAME</B> String => table name
3742  <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
3743  false when TYPE is tableIndexStatistic
3744  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
3745  null when TYPE is tableIndexStatistic
3746  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
3747  tableIndexStatistic
3748  <LI><B>TYPE</B> short => index type:
3749  <UL>
3750  <LI> tableIndexStatistic - this identifies table statistics that are
3751  returned in conjuction with a table's index descriptions
3752  <LI> tableIndexClustered - this is a clustered index
3753  <LI> tableIndexHashed - this is a hashed index
3754  <LI> tableIndexOther - this is some other style of index
3755  </UL>
3756  <LI><B>ORDINAL_POSITION</B> short => column sequence number
3757  within index; zero when TYPE is tableIndexStatistic
3758  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
3759  tableIndexStatistic
3760  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
3761  "D" => descending, may be null if sort sequence is not supported;
3762  null when TYPE is tableIndexStatistic
3763  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
3764  this is the number of rows in the table; otherwise, it is the
3765  number of unique values in the index.
3766  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
3767  this is the number of pages used for the table, otherwise it
3768  is the number of pages used for the current index.
3769  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
3770  (may be null)
3771  </OL>
3772 
3773  @param catalog a catalog name; "" retrieves those without a
3774  catalog; null means drop catalog name from the selection criteria
3775  @param schema a schema name; "" retrieves those without a schema
3776  @param table a table name
3777  @param unique when true, return only indices for unique values;
3778  when false, return indices regardless of whether unique or not
3779  @param approximate when true, result is allowed to reflect approximate
3780  or out of data values; when false, results are requested to be
3781  accurate
3782  @return <code>ResultSet</code> - each row is an index column description
3783 }
3784 function TZSybaseDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
3785  const Schema: string; const Table: string; Unique: Boolean;
3786  Approximate: Boolean): IZResultSet;
3787 var
3788  Is_Unique, Accuracy: string;
3789 begin
3790  Result:=inherited UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
3791 
3792  if Unique then
3793  Is_Unique := '''1'''
3794  else Is_Unique := '''0''';
3795  if Approximate then
3796  Accuracy := '''1'''
3797  else Accuracy := '''0''';
3798 
3799  with GetStatement.ExecuteQuery(
3800  Format('exec sp_jdbc_getindexinfo %s, %s, %s, %s, %s',
3801  [ComposeObjectString(Catalog), ComposeObjectString(Schema), ComposeObjectString(Table), Is_Unique, Accuracy])) do
3802  begin
3803  while Next do
3804  begin
3805  Result.MoveToInsertRow;
3806  Result.UpdateStringByName('TABLE_CAT',
3807  GetStringByName('TABLE_CAT'));
3808  Result.UpdateStringByName('TABLE_SCHEM',
3809  GetStringByName('TABLE_SCHEM'));
3810  Result.UpdateStringByName('TABLE_NAME',
3811  GetStringByName('TABLE_NAME'));
3812  Result.UpdateBooleanByName('NON_UNIQUE',
3813  GetShortByName('NON_UNIQUE') = 1);
3814  Result.UpdateStringByName('INDEX_QUALIFIER',
3815  GetStringByName('INDEX_QUALIFIER'));
3816  Result.UpdateStringByName('INDEX_NAME',
3817  GetStringByName('INDEX_NAME'));
3818  Result.UpdateShortByName('TYPE',
3819  GetShortByName('TYPE'));
3820  Result.UpdateShortByName('ORDINAL_POSITION',
3821  GetShortByName('ORDINAL_POSITION'));
3822  Result.UpdateStringByName('COLUMN_NAME',
3823  GetStringByName('COLUMN_NAME'));
3824  Result.UpdateStringByName('ASC_OR_DESC',
3825  GetStringByName('ASC_OR_DESC'));
3826  Result.UpdateIntByName('CARDINALITY',
3827  GetIntByName('CARDINALITY'));
3828  Result.UpdateIntByName('PAGES',
3829  GetIntByName('PAGES'));
3830  Result.UpdateStringByName('FILTER_CONDITION',
3831  GetStringByName('FILTER_CONDITION'));
3832  Result.InsertRow;
3833  end;
3834  Close;
3835  end;
3836 end;
3837 
3838 {**
3839 
3840  Gets a description of the user-defined types defined in a particular
3841  schema. Schema-specific UDTs may have type JAVA_OBJECT, STRUCT,
3842  or DISTINCT.
3843 
3844  <P>Only types matching the catalog, schema, type name and type
3845  criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
3846  and TYPE_NAME. The type name parameter may be a fully-qualified
3847  name. In this case, the catalog and schemaPattern parameters are
3848  ignored.
3849 
3850  <P>Each type description has the following columns:
3851  <OL>
3852  <LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
3853  <LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
3854  <LI><B>TYPE_NAME</B> String => type name
3855  <LI><B>CLASS_NAME</B> String => Java class name
3856  <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
3857  One of JAVA_OBJECT, STRUCT, or DISTINCT
3858  <LI><B>REMARKS</B> String => explanatory comment on the type
3859  </OL>
3860 
3861  <P><B>Note:</B> If the driver does not support UDTs, an empty
3862  result set is returned.
3863 
3864  @param catalog a catalog name; "" retrieves those without a
3865  catalog; null means drop catalog name from the selection criteria
3866  @param schemaPattern a schema name pattern; "" retrieves those
3867  without a schema
3868  @param typeNamePattern a type name pattern; may be a fully-qualified name
3869  @param types a list of user-named types to include (JAVA_OBJECT,
3870  STRUCT, or DISTINCT); null returns all types
3871  @return <code>ResultSet</code> - each row is a type description
3872 }
3873 function TZSybaseDatabaseMetadata.UncachedGetUDTs(const Catalog: string;
3874  const SchemaPattern: string; const TypeNamePattern: string;
3875  const Types: TIntegerDynArray): IZResultSet;
3876 var
3877  I: Integer;
3878  UDTypes: string;
3879 begin
3880  Result:=inherited UncachedGetUDTs(Catalog, SchemaPattern, TypeNamePattern, Types);
3881 
3882  UDTypes := '';
3883  for I := 0 to Length(Types) - 1 do
3884  begin
3885  if Length(UDTypes) > 0 then
3886  UDTypes := UDTypes + ',';
3887  UDTypes := UDTypes + AnsiQuotedStr(IntToStr(Types[I]), '''');
3888  end;
3889 
3890  with GetStatement.ExecuteQuery(
3891  Format('exec sp_jdbc_getudts %s, %s, %s, %s',
3892  [ComposeObjectString(Catalog), ComposeObjectString(SchemaPattern, '''%'''),
3893  ComposeObjectString(TypeNamePattern, '''%'''), ComposeObjectString(UDTypes)])) do
3894  begin
3895  while Next do
3896  while Next do
3897  begin
3898  Result.MoveToInsertRow;
3899  Result.UpdateStringByName('TYPE_CAT',
3900  GetStringByName('TYPE_CAT'));
3901  Result.UpdateStringByName('TYPE_SCHEM',
3902  GetStringByName('TYPE_SCHEM'));
3903  Result.UpdateStringByName('TYPE_NAME',
3904  GetStringByName('TYPE_NAME'));
3905  Result.UpdateStringByName('JAVA_CLASS',
3906  GetStringByName('JAVA_CLASS'));
3907  Result.UpdateShortByName('DATA_TYPE',
3908  Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'), ConSettings.CPType)));
3909  Result.UpdateStringByName('REMARKS',
3910  GetStringByName('REMARKS'));
3911  Result.InsertRow;
3912  end;
3913  Close;
3914  end;
3915 end;
3916 
3917 end.
3918 
3919 
3920