zeoslib  UNKNOWN
 All Files
ZDbcOracleMetadata.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Oracle Database Connectivity Classes }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZDbcOracleMetadata;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 uses
59  Types, Classes, SysUtils, ZSysUtils, ZDbcIntfs, ZDbcMetadata,
60  ZCompatibility, ZDbcOracleUtils, ZDbcConnection, ZURL,
61  ZDbcCachedResultSet, ZDbcCache;
62 
63 type
64 
65  // technobot 2008-06-28 - methods moved as is from TZOracleDatabaseMetadata:
66  {** Implements Oracle Database Information. }
67  TZOracleDatabaseInfo = class(TZAbstractDatabaseInfo)
68 // function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
69 // const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
70  public
71  // database/driver/server info:
72  function GetDatabaseProductName: string; override;
73  function GetDatabaseProductVersion: string; override;
74  function GetDriverName: string; override;
75 // function GetDriverVersion: string; override; -> Same as parent
76  function GetDriverMajorVersion: Integer; override;
77  function GetDriverMinorVersion: Integer; override;
78 // function GetServerVersion: string; -> Not implemented
79 
80  // capabilities (what it can/cannot do):
81 // function AllProceduresAreCallable: Boolean; override; -> Not implemented
82 // function AllTablesAreSelectable: Boolean; override; -> Not implemented
83  function SupportsMixedCaseIdentifiers: Boolean; override;
84  function SupportsMixedCaseQuotedIdentifiers: Boolean; override;
85 // function SupportsAlterTableWithAddColumn: Boolean; override; -> Not implemented
86 // function SupportsAlterTableWithDropColumn: Boolean; override; -> Not implemented
87 // function SupportsColumnAliasing: Boolean; override; -> Not implemented
88 // function SupportsConvert: Boolean; override; -> Not implemented
89 // function SupportsConvertForTypes(FromType: TZSQLType; ToType: TZSQLType):
90 // Boolean; override; -> Not implemented
91 // function SupportsTableCorrelationNames: Boolean; override; -> Not implemented
92 // function SupportsDifferentTableCorrelationNames: Boolean; override; -> Not implemented
93  function SupportsExpressionsInOrderBy: Boolean; override;
94  function SupportsOrderByUnrelated: Boolean; override;
95  function SupportsGroupBy: Boolean; override;
96  function SupportsGroupByUnrelated: Boolean; override;
97  function SupportsGroupByBeyondSelect: Boolean; override;
98 // function SupportsLikeEscapeClause: Boolean; override; -> Not implemented
99 // function SupportsMultipleResultSets: Boolean; override; -> Not implemented
100 // function SupportsMultipleTransactions: Boolean; override; -> Not implemented
101 // function SupportsNonNullableColumns: Boolean; override; -> Not implemented
102 // function SupportsMinimumSQLGrammar: Boolean; override; -> Not implemented
103 // function SupportsCoreSQLGrammar: Boolean; override; -> Not implemented
104 // function SupportsExtendedSQLGrammar: Boolean; override; -> Not implemented
105 // function SupportsANSI92EntryLevelSQL: Boolean; override; -> Not implemented
106 // function SupportsANSI92IntermediateSQL: Boolean; override; -> Not implemented
107 // function SupportsANSI92FullSQL: Boolean; override; -> Not implemented
108  function SupportsIntegrityEnhancementFacility: Boolean; override;
109 // function SupportsOuterJoins: Boolean; override; -> Not implemented
110 // function SupportsFullOuterJoins: Boolean; override; -> Not implemented
111 // function SupportsLimitedOuterJoins: Boolean; override; -> Not implemented
112  function SupportsSchemasInDataManipulation: Boolean; override;
113  function SupportsSchemasInProcedureCalls: Boolean; override;
114  function SupportsSchemasInTableDefinitions: Boolean; override;
115  function SupportsSchemasInIndexDefinitions: Boolean; override;
116  function SupportsSchemasInPrivilegeDefinitions: Boolean; override;
117  function SupportsCatalogsInDataManipulation: Boolean; override;
118  function SupportsCatalogsInProcedureCalls: Boolean; override;
119  function SupportsCatalogsInTableDefinitions: Boolean; override;
120  function SupportsCatalogsInIndexDefinitions: Boolean; override;
121  function SupportsCatalogsInPrivilegeDefinitions: Boolean; override;
122  function SupportsPositionedDelete: Boolean; override;
123  function SupportsPositionedUpdate: Boolean; override;
124  function SupportsSelectForUpdate: Boolean; override;
125  function SupportsStoredProcedures: Boolean; override;
126  function SupportsSubqueriesInComparisons: Boolean; override;
127  function SupportsSubqueriesInExists: Boolean; override;
128  function SupportsSubqueriesInIns: Boolean; override;
129  function SupportsSubqueriesInQuantifieds: Boolean; override;
130  function SupportsCorrelatedSubqueries: Boolean; override;
131  function SupportsUnion: Boolean; override;
132  function SupportsUnionAll: Boolean; override;
133  function SupportsOpenCursorsAcrossCommit: Boolean; override;
134  function SupportsOpenCursorsAcrossRollback: Boolean; override;
135  function SupportsOpenStatementsAcrossCommit: Boolean; override;
136  function SupportsOpenStatementsAcrossRollback: Boolean; override;
137  function SupportsTransactions: Boolean; override;
138  function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
139  Boolean; override;
140  function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
141  function SupportsDataManipulationTransactionsOnly: Boolean; override;
142  function SupportsResultSetType(_Type: TZResultSetType): Boolean; override;
143  function SupportsResultSetConcurrency(_Type: TZResultSetType;
144  Concurrency: TZResultSetConcurrency): Boolean; override;
145 // function SupportsBatchUpdates: Boolean; override; -> Not implemented
146  function SupportsNonEscapedSearchStrings: Boolean; override;
147 
148  // maxima:
149  function GetMaxBinaryLiteralLength: Integer; override;
150  function GetMaxCharLiteralLength: Integer; override;
151  function GetMaxColumnNameLength: Integer; override;
152  function GetMaxColumnsInGroupBy: Integer; override;
153  function GetMaxColumnsInIndex: Integer; override;
154  function GetMaxColumnsInOrderBy: Integer; override;
155  function GetMaxColumnsInSelect: Integer; override;
156  function GetMaxColumnsInTable: Integer; override;
157  function GetMaxConnections: Integer; override;
158  function GetMaxCursorNameLength: Integer; override;
159  function GetMaxIndexLength: Integer; override;
160  function GetMaxSchemaNameLength: Integer; override;
161  function GetMaxProcedureNameLength: Integer; override;
162  function GetMaxCatalogNameLength: Integer; override;
163  function GetMaxRowSize: Integer; override;
164  function GetMaxStatementLength: Integer; override;
165  function GetMaxStatements: Integer; override;
166  function GetMaxTableNameLength: Integer; override;
167  function GetMaxTablesInSelect: Integer; override;
168  function GetMaxUserNameLength: Integer; override;
169 
170  // policies (how are various data and operations handled):
171 // function IsReadOnly: Boolean; override; -> Not implemented
172 // function IsCatalogAtStart: Boolean; override; -> Not implemented
173  function DoesMaxRowSizeIncludeBlobs: Boolean; override;
174 // function NullsAreSortedHigh: Boolean; override; -> Not implemented
175 // function NullsAreSortedLow: Boolean; override; -> Not implemented
176 // function NullsAreSortedAtStart: Boolean; override; -> Not implemented
177 // function NullsAreSortedAtEnd: Boolean; override; -> Not implemented
178 // function NullPlusNonNullIsNull: Boolean; override; -> Not implemented
179 // function UsesLocalFiles: Boolean; override; -> Not implemented
180  function UsesLocalFilePerTable: Boolean; override;
181  function StoresUpperCaseIdentifiers: Boolean; override;
182  function StoresLowerCaseIdentifiers: Boolean; override;
183  function StoresMixedCaseIdentifiers: Boolean; override;
184  function StoresUpperCaseQuotedIdentifiers: Boolean; override;
185  function StoresLowerCaseQuotedIdentifiers: Boolean; override;
186  function StoresMixedCaseQuotedIdentifiers: Boolean; override;
187  function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
188  function DataDefinitionCausesTransactionCommit: Boolean; override;
189  function DataDefinitionIgnoredInTransactions: Boolean; override;
190 
191  // interface details (terms, keywords, etc):
192  function GetSchemaTerm: string; override;
193  function GetProcedureTerm: string; override;
194  function GetCatalogTerm: string; override;
195  function GetCatalogSeparator: string; override;
196  function GetSQLKeywords: string; override;
197  function GetNumericFunctions: string; override;
198  function GetStringFunctions: string; override;
199  function GetSystemFunctions: string; override;
200  function GetTimeDateFunctions: string; override;
201  function GetSearchStringEscape: string; override;
202  function GetExtraNameCharacters: string; override;
203  end;
204 
205  {** Implements Oracle Database Metadata. }
206  TZOracleDatabaseMetadata = class(TZAbstractDatabaseMetadata)
207  protected
208  function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-28
209 
210  function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
211  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
212  function UncachedGetSchemas: IZResultSet; override;
213 // function UncachedGetCatalogs: IZResultSet; override; -> Not implemented
214  function UncachedGetTableTypes: IZResultSet; override;
215  function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
216  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
217  function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
218  const TableNamePattern: string): IZResultSet; override;
219  function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
220  const Table: string; const ColumnNamePattern: string): IZResultSet; override;
221  function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
222  const Table: string): IZResultSet; override;
223 // function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
224 // const Table: string): IZResultSet; override;
225 // function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
226 // const Table: string): IZResultSet; override;
227 // function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
228 // const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
229 // const ForeignTable: string): IZResultSet; override;
230  function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
231  Unique: Boolean; Approximate: Boolean): IZResultSet; override;
232 // function UncachedGetSequences(const Catalog: string; const SchemaPattern: string;
233 // const SequenceNamePattern: string): IZResultSet; virtual; -> Not implemented
234  function UncachedGetProcedures(const Catalog, SchemaPattern,
235  ProcedureNamePattern: string): IZResultSet;override;
236  function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
237  const ProcedureNamePattern: string; const ColumnNamePattern: string):
238  IZResultSet; override;
239 // function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
240 // const Table: string): IZResultSet; override;
241 // function UncachedGetTypeInfo: IZResultSet; override;
242  public
243  destructor Destroy; override;
244  end;
245 
246 implementation
247 
248 uses
249  ZDbcUtils;
250 
251 { TZOracleDatabaseInfo }
252 
253 //----------------------------------------------------------------------
254 // First, a variety of minor information about the target database.
255 
256 {**
257  What's the name of this database product?
258  @return database product name
259 }
260 function TZOracleDatabaseInfo.GetDatabaseProductName: string;
261 begin
262  Result := 'Oracle';
263 end;
264 
265 {**
266  What's the version of this database product?
267  @return database version
268 }
269 function TZOracleDatabaseInfo.GetDatabaseProductVersion: string;
270 begin
271  Result := '';
272 end;
273 
274 {**
275  What's the name of this JDBC driver?
276  @return JDBC driver name
277 }
278 function TZOracleDatabaseInfo.GetDriverName: string;
279 begin
280  Result := 'Zeos Database Connectivity Driver for Oracle';
281 end;
282 
283 {**
284  What's this JDBC driver's major version number?
285  @return JDBC driver major version
286 }
287 function TZOracleDatabaseInfo.GetDriverMajorVersion: Integer;
288 begin
289  Result := 1;
290 end;
291 
292 {**
293  What's this JDBC driver's minor version number?
294  @return JDBC driver minor version number
295 }
296 function TZOracleDatabaseInfo.GetDriverMinorVersion: Integer;
297 begin
298  Result := 0;
299 end;
300 
301 {**
302  Does the database use a file for each table?
303  @return true if the database uses a local file for each table
304 }
305 function TZOracleDatabaseInfo.UsesLocalFilePerTable: Boolean;
306 begin
307  Result := False;
308 end;
309 
310 {**
311  Does the database treat mixed case unquoted SQL identifiers as
312  case sensitive and as a result store them in mixed case?
313  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return false.
314  @return <code>true</code> if so; <code>false</code> otherwise
315 }
316 function TZOracleDatabaseInfo.SupportsMixedCaseIdentifiers: Boolean;
317 begin
318  Result := False;
319 end;
320 
321 {**
322  Does the database treat mixed case unquoted SQL identifiers as
323  case insensitive and store them in upper case?
324  @return <code>true</code> if so; <code>false</code> otherwise
325 }
326 function TZOracleDatabaseInfo.StoresUpperCaseIdentifiers: Boolean;
327 begin
328  Result := True;
329 end;
330 
331 {**
332  Does the database treat mixed case unquoted SQL identifiers as
333  case insensitive and store them in lower case?
334  @return <code>true</code> if so; <code>false</code> otherwise
335 }
336 function TZOracleDatabaseInfo.StoresLowerCaseIdentifiers: Boolean;
337 begin
338  Result := False;
339 end;
340 
341 {**
342  Does the database treat mixed case unquoted SQL identifiers as
343  case insensitive and store them in mixed case?
344  @return <code>true</code> if so; <code>false</code> otherwise
345 }
346 function TZOracleDatabaseInfo.StoresMixedCaseIdentifiers: Boolean;
347 begin
348  Result := False;
349 end;
350 
351 {**
352  Does the database treat mixed case quoted SQL identifiers as
353  case sensitive and as a result store them in mixed case?
354  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
355  @return <code>true</code> if so; <code>false</code> otherwise
356 }
357 function TZOracleDatabaseInfo.SupportsMixedCaseQuotedIdentifiers: Boolean;
358 begin
359  Result := True;
360 end;
361 
362 {**
363  Does the database treat mixed case quoted SQL identifiers as
364  case insensitive and store them in upper case?
365  @return <code>true</code> if so; <code>false</code> otherwise
366 }
367 function TZOracleDatabaseInfo.StoresUpperCaseQuotedIdentifiers: Boolean;
368 begin
369  Result := False;
370 end;
371 
372 {**
373  Does the database treat mixed case quoted SQL identifiers as
374  case insensitive and store them in lower case?
375  @return <code>true</code> if so; <code>false</code> otherwise
376 }
377 function TZOracleDatabaseInfo.StoresLowerCaseQuotedIdentifiers: Boolean;
378 begin
379  Result := False;
380 end;
381 
382 {**
383  Does the database treat mixed case quoted SQL identifiers as
384  case insensitive and store them in mixed case?
385  @return <code>true</code> if so; <code>false</code> otherwise
386 }
387 function TZOracleDatabaseInfo.StoresMixedCaseQuotedIdentifiers: Boolean;
388 begin
389  Result := True;
390 end;
391 
392 {**
393  Gets a comma-separated list of all a database's SQL keywords
394  that are NOT also SQL92 keywords.
395  @return the list
396 }
397 function TZOracleDatabaseInfo.GetSQLKeywords: string;
398 begin
399  Result := 'ACCESS,ADD,ALTER,AUDIT,CLUSTER,COLUMN,COMMENT,COMPRESS,CONNECT,'
400  + 'DATE,DROP,EXCLUSIVE,FILE,IDENTIFIED,IMMEDIATE,INCREMENT,INDEX,INITIAL,'
401  + 'INTERSECT,LEVEL,LOCK,LONG,MAXEXTENTS,MINUS,MODE,NOAUDIT,NOCOMPRESS,'
402  + 'NOWAIT,NUMBER,OFFLINE,ONLINE,PCTFREE,PRIOR';
403 end;
404 
405 {**
406  Gets a comma-separated list of math functions. These are the
407  X/Open CLI math function names used in the JDBC function escape
408  clause.
409  @return the list
410 }
411 function TZOracleDatabaseInfo.GetNumericFunctions: string;
412 begin
413  Result := 'ABS,ACOS,ASIN,ATAN,ATAN2,CEILING,COS,EXP,FLOOR,LOG,LOG10,MOD,PI,'
414  + 'POWER,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE';
415 end;
416 
417 {**
418  Gets a comma-separated list of string functions. These are the
419  X/Open CLI string function names used in the JDBC function escape
420  clause.
421  @return the list
422 }
423 function TZOracleDatabaseInfo.GetStringFunctions: string;
424 begin
425  Result := 'ASCII,CHAR,CONCAT,LCASE,LENGTH,LTRIM,REPLACE,RTRIM,SOUNDEX,'
426  + 'SUBSTRING,UCASE';
427 end;
428 
429 {**
430  Gets a comma-separated list of system functions. These are the
431  X/Open CLI system function names used in the JDBC function escape
432  clause.
433  @return the list
434 }
435 function TZOracleDatabaseInfo.GetSystemFunctions: string;
436 begin
437  Result := 'USER';
438 end;
439 
440 {**
441  Gets a comma-separated list of time and date functions.
442  @return the list
443 }
444 function TZOracleDatabaseInfo.GetTimeDateFunctions: string;
445 begin
446  Result := 'CURDATE,CURTIME,DAYOFMONTH,HOUR,MINUTE,MONTH,NOW,SECOND,YEAR';
447 end;
448 
449 {**
450  Gets the string that can be used to escape wildcard characters.
451  This is the string that can be used to escape '_' or '%' in
452  the string pattern style catalog search parameters.
453 
454  <P>The '_' character represents any single character.
455  <P>The '%' character represents any sequence of zero or
456  more characters.
457 
458  @return the string used to escape wildcard characters
459 }
460 function TZOracleDatabaseInfo.GetSearchStringEscape: string;
461 begin
462  Result := '//';
463 end;
464 
465 {**
466  Gets all the "extra" characters that can be used in unquoted
467  identifier names (those beyond a-z, A-Z, 0-9 and _).
468  @return the string containing the extra characters
469 }
470 function TZOracleDatabaseInfo.GetExtraNameCharacters: string;
471 begin
472  Result := '$#';
473 end;
474 
475 //--------------------------------------------------------------------
476 // Functions describing which features are supported.
477 
478 {**
479  Are expressions in "ORDER BY" lists supported?
480  @return <code>true</code> if so; <code>false</code> otherwise
481 }
482 function TZOracleDatabaseInfo.SupportsExpressionsInOrderBy: Boolean;
483 begin
484  Result := True;
485 end;
486 
487 {**
488  Can an "ORDER BY" clause use columns not in the SELECT statement?
489  @return <code>true</code> if so; <code>false</code> otherwise
490 }
491 function TZOracleDatabaseInfo.SupportsOrderByUnrelated: Boolean;
492 begin
493  Result := True;
494 end;
495 
496 {**
497  Is some form of "GROUP BY" clause supported?
498  @return <code>true</code> if so; <code>false</code> otherwise
499 }
500 function TZOracleDatabaseInfo.SupportsGroupBy: Boolean;
501 begin
502  Result := True;
503 end;
504 
505 {**
506  Can a "GROUP BY" clause use columns not in the SELECT?
507  @return <code>true</code> if so; <code>false</code> otherwise
508 }
509 function TZOracleDatabaseInfo.SupportsGroupByUnrelated: Boolean;
510 begin
511  Result := True;
512 end;
513 
514 {**
515  Can a "GROUP BY" clause add columns not in the SELECT
516  provided it specifies all the columns in the SELECT?
517  @return <code>true</code> if so; <code>false</code> otherwise
518 }
519 function TZOracleDatabaseInfo.SupportsGroupByBeyondSelect: Boolean;
520 begin
521  Result := True;
522 end;
523 
524 {**
525  Is the SQL Integrity Enhancement Facility supported?
526  @return <code>true</code> if so; <code>false</code> otherwise
527 }
528 function TZOracleDatabaseInfo.SupportsIntegrityEnhancementFacility: Boolean;
529 begin
530  Result := True;
531 end;
532 
533 {**
534  What's the database vendor's preferred term for "schema"?
535  @return the vendor term
536 }
537 function TZOracleDatabaseInfo.GetSchemaTerm: string;
538 begin
539  Result := 'schema';
540 end;
541 
542 {**
543  What's the database vendor's preferred term for "procedure"?
544  @return the vendor term
545 }
546 function TZOracleDatabaseInfo.GetProcedureTerm: string;
547 begin
548  Result := 'procedure';
549 end;
550 
551 {**
552  What's the database vendor's preferred term for "catalog"?
553  @return the vendor term
554 }
555 function TZOracleDatabaseInfo.GetCatalogTerm: string;
556 begin
557  Result := '';
558 end;
559 
560 {**
561  What's the separator between catalog and table name?
562  @return the separator string
563 }
564 function TZOracleDatabaseInfo.GetCatalogSeparator: string;
565 begin
566  Result := '';
567 end;
568 
569 {**
570  Can a schema name be used in a data manipulation statement?
571  @return <code>true</code> if so; <code>false</code> otherwise
572 }
573 function TZOracleDatabaseInfo.SupportsSchemasInDataManipulation: Boolean;
574 begin
575  Result := True;
576 end;
577 
578 {**
579  Can a schema name be used in a procedure call statement?
580  @return <code>true</code> if so; <code>false</code> otherwise
581 }
582 function TZOracleDatabaseInfo.SupportsSchemasInProcedureCalls: Boolean;
583 begin
584  Result := True;
585 end;
586 
587 {**
588  Can a schema name be used in a table definition statement?
589  @return <code>true</code> if so; <code>false</code> otherwise
590 }
591 function TZOracleDatabaseInfo.SupportsSchemasInTableDefinitions: Boolean;
592 begin
593  Result := True;
594 end;
595 
596 {**
597  Can a schema name be used in an index definition statement?
598  @return <code>true</code> if so; <code>false</code> otherwise
599 }
600 function TZOracleDatabaseInfo.SupportsSchemasInIndexDefinitions: Boolean;
601 begin
602  Result := True;
603 end;
604 
605 {**
606  Can a schema name be used in a privilege definition statement?
607  @return <code>true</code> if so; <code>false</code> otherwise
608 }
609 function TZOracleDatabaseInfo.SupportsSchemasInPrivilegeDefinitions: Boolean;
610 begin
611  Result := True;
612 end;
613 
614 {**
615  Can a catalog name be used in a data manipulation statement?
616  @return <code>true</code> if so; <code>false</code> otherwise
617 }
618 function TZOracleDatabaseInfo.SupportsCatalogsInDataManipulation: Boolean;
619 begin
620  Result := False;
621 end;
622 
623 {**
624  Can a catalog name be used in a procedure call statement?
625  @return <code>true</code> if so; <code>false</code> otherwise
626 }
627 function TZOracleDatabaseInfo.SupportsCatalogsInProcedureCalls: Boolean;
628 begin
629  Result := False;
630 end;
631 
632 {**
633  Can a catalog name be used in a table definition statement?
634  @return <code>true</code> if so; <code>false</code> otherwise
635 }
636 function TZOracleDatabaseInfo.SupportsCatalogsInTableDefinitions: Boolean;
637 begin
638  Result := False;
639 end;
640 
641 {**
642  Can a catalog name be used in an index definition statement?
643  @return <code>true</code> if so; <code>false</code> otherwise
644 }
645 function TZOracleDatabaseInfo.SupportsCatalogsInIndexDefinitions: Boolean;
646 begin
647  Result := False;
648 end;
649 
650 {**
651  Can a catalog name be used in a privilege definition statement?
652  @return <code>true</code> if so; <code>false</code> otherwise
653 }
654 function TZOracleDatabaseInfo.SupportsCatalogsInPrivilegeDefinitions: Boolean;
655 begin
656  Result := False;
657 end;
658 
659 {**
660  Is positioned DELETE supported?
661  @return <code>true</code> if so; <code>false</code> otherwise
662 }
663 function TZOracleDatabaseInfo.SupportsPositionedDelete: Boolean;
664 begin
665  Result := False;
666 end;
667 
668 {**
669  Is positioned UPDATE supported?
670  @return <code>true</code> if so; <code>false</code> otherwise
671 }
672 function TZOracleDatabaseInfo.SupportsPositionedUpdate: Boolean;
673 begin
674  Result := False;
675 end;
676 
677 {**
678  Is SELECT for UPDATE supported?
679  @return <code>true</code> if so; <code>false</code> otherwise
680 }
681 function TZOracleDatabaseInfo.SupportsSelectForUpdate: Boolean;
682 begin
683  Result := True;
684 end;
685 
686 {**
687  Are stored procedure calls using the stored procedure escape
688  syntax supported?
689  @return <code>true</code> if so; <code>false</code> otherwise
690 }
691 function TZOracleDatabaseInfo.SupportsStoredProcedures: Boolean;
692 begin
693  Result := True;
694 end;
695 
696 {**
697  Are subqueries in comparison expressions supported?
698  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
699  @return <code>true</code> if so; <code>false</code> otherwise
700 }
701 function TZOracleDatabaseInfo.SupportsSubqueriesInComparisons: Boolean;
702 begin
703  Result := True;
704 end;
705 
706 {**
707  Are subqueries in 'exists' expressions supported?
708  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
709  @return <code>true</code> if so; <code>false</code> otherwise
710 }
711 function TZOracleDatabaseInfo.SupportsSubqueriesInExists: Boolean;
712 begin
713  Result := True;
714 end;
715 
716 {**
717  Are subqueries in 'in' statements supported?
718  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
719  @return <code>true</code> if so; <code>false</code> otherwise
720 }
721 function TZOracleDatabaseInfo.SupportsSubqueriesInIns: Boolean;
722 begin
723  Result := True;
724 end;
725 
726 {**
727  Are subqueries in quantified expressions supported?
728  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
729  @return <code>true</code> if so; <code>false</code> otherwise
730 }
731 function TZOracleDatabaseInfo.SupportsSubqueriesInQuantifieds: Boolean;
732 begin
733  Result := True;
734 end;
735 
736 {**
737  Are correlated subqueries supported?
738  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
739  @return <code>true</code> if so; <code>false</code> otherwise
740 }
741 function TZOracleDatabaseInfo.SupportsCorrelatedSubqueries: Boolean;
742 begin
743  Result := True;
744 end;
745 
746 {**
747  Is SQL UNION supported?
748  @return <code>true</code> if so; <code>false</code> otherwise
749 }
750 function TZOracleDatabaseInfo.SupportsUnion: Boolean;
751 begin
752  Result := True;
753 end;
754 
755 {**
756  Is SQL UNION ALL supported?
757  @return <code>true</code> if so; <code>false</code> otherwise
758 }
759 function TZOracleDatabaseInfo.SupportsUnionAll: Boolean;
760 begin
761  Result := True;
762 end;
763 
764 {**
765  Can cursors remain open across commits?
766  @return <code>true</code> if cursors always remain open;
767  <code>false</code> if they might not remain open
768 }
769 function TZOracleDatabaseInfo.SupportsOpenCursorsAcrossCommit: Boolean;
770 begin
771  Result := False;
772 end;
773 
774 {**
775  Can cursors remain open across rollbacks?
776  @return <code>true</code> if cursors always remain open;
777  <code>false</code> if they might not remain open
778 }
779 function TZOracleDatabaseInfo.SupportsOpenCursorsAcrossRollback: Boolean;
780 begin
781  Result := False;
782 end;
783 
784 {**
785  Can statements remain open across commits?
786  @return <code>true</code> if statements always remain open;
787  <code>false</code> if they might not remain open
788 }
789 function TZOracleDatabaseInfo.SupportsOpenStatementsAcrossCommit: Boolean;
790 begin
791  Result := False;
792 end;
793 
794 {**
795  Can statements remain open across rollbacks?
796  @return <code>true</code> if statements always remain open;
797  <code>false</code> if they might not remain open
798 }
799 function TZOracleDatabaseInfo.SupportsOpenStatementsAcrossRollback: Boolean;
800 begin
801  Result := False;
802 end;
803 
804 //----------------------------------------------------------------------
805 // The following group of methods exposes various limitations
806 // based on the target database with the current driver.
807 // Unless otherwise specified, a result of zero means there is no
808 // limit, or the limit is not known.
809 
810 {**
811  How many hex characters can you have in an inline binary literal?
812  @return max binary literal length in hex characters;
813  a result of zero means that there is no limit or the limit is not known
814 }
815 function TZOracleDatabaseInfo.GetMaxBinaryLiteralLength: Integer;
816 begin
817  Result := 1000;
818 end;
819 
820 {**
821  What's the max length for a character literal?
822  @return max literal length;
823  a result of zero means that there is no limit or the limit is not known
824 }
825 function TZOracleDatabaseInfo.GetMaxCharLiteralLength: Integer;
826 begin
827  Result := 2000;
828 end;
829 
830 {**
831  What's the limit on column name length?
832  @return max column name length;
833  a result of zero means that there is no limit or the limit is not known
834 }
835 function TZOracleDatabaseInfo.GetMaxColumnNameLength: Integer;
836 begin
837  Result := 30;
838 end;
839 
840 {**
841  What's the maximum number of columns in a "GROUP BY" clause?
842  @return max number of columns;
843  a result of zero means that there is no limit or the limit is not known
844 }
845 function TZOracleDatabaseInfo.GetMaxColumnsInGroupBy: Integer;
846 begin
847  Result := 0;
848 end;
849 
850 {**
851  What's the maximum number of columns allowed in an index?
852  @return max number of columns;
853  a result of zero means that there is no limit or the limit is not known
854 }
855 function TZOracleDatabaseInfo.GetMaxColumnsInIndex: Integer;
856 begin
857  Result := 32;
858 end;
859 
860 {**
861  What's the maximum number of columns in an "ORDER BY" clause?
862  @return max number of columns;
863  a result of zero means that there is no limit or the limit is not known
864 }
865 function TZOracleDatabaseInfo.GetMaxColumnsInOrderBy: Integer;
866 begin
867  Result := 0;
868 end;
869 
870 {**
871  What's the maximum number of columns in a "SELECT" list?
872  @return max number of columns;
873  a result of zero means that there is no limit or the limit is not known
874 }
875 function TZOracleDatabaseInfo.GetMaxColumnsInSelect: Integer;
876 begin
877  Result := 0;
878 end;
879 
880 {**
881  What's the maximum number of columns in a table?
882  @return max number of columns;
883  a result of zero means that there is no limit or the limit is not known
884 }
885 function TZOracleDatabaseInfo.GetMaxColumnsInTable: Integer;
886 begin
887  Result := 1000;
888 end;
889 
890 {**
891  How many active connections can we have at a time to this database?
892  @return max number of active connections;
893  a result of zero means that there is no limit or the limit is not known
894 }
895 function TZOracleDatabaseInfo.GetMaxConnections: Integer;
896 begin
897  Result := 0;
898 end;
899 
900 {**
901  What's the maximum cursor name length?
902  @return max cursor name length in bytes;
903  a result of zero means that there is no limit or the limit is not known
904 }
905 function TZOracleDatabaseInfo.GetMaxCursorNameLength: Integer;
906 begin
907  Result := 0;
908 end;
909 
910 {**
911  Retrieves the maximum number of bytes for an index, including all
912  of the parts of the index.
913  @return max index length in bytes, which includes the composite of all
914  the constituent parts of the index;
915  a result of zero means that there is no limit or the limit is not known
916 }
917 function TZOracleDatabaseInfo.GetMaxIndexLength: Integer;
918 begin
919  Result := 0;
920 end;
921 
922 {**
923  What's the maximum length allowed for a schema name?
924  @return max name length in bytes;
925  a result of zero means that there is no limit or the limit is not known
926 }
927 function TZOracleDatabaseInfo.GetMaxSchemaNameLength: Integer;
928 begin
929  Result := 30;
930 end;
931 
932 {**
933  What's the maximum length of a procedure name?
934  @return max name length in bytes;
935  a result of zero means that there is no limit or the limit is not known
936 }
937 function TZOracleDatabaseInfo.GetMaxProcedureNameLength: Integer;
938 begin
939  Result := 30;
940 end;
941 
942 {**
943  What's the maximum length of a catalog name?
944  @return max name length in bytes;
945  a result of zero means that there is no limit or the limit is not known
946 }
947 function TZOracleDatabaseInfo.GetMaxCatalogNameLength: Integer;
948 begin
949  Result := 0;
950 end;
951 
952 {**
953  What's the maximum length of a single row?
954  @return max row size in bytes;
955  a result of zero means that there is no limit or the limit is not known
956 }
957 function TZOracleDatabaseInfo.GetMaxRowSize: Integer;
958 begin
959  Result := 2000;
960 end;
961 
962 {**
963  Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
964  blobs?
965  @return <code>true</code> if so; <code>false</code> otherwise
966 }
967 function TZOracleDatabaseInfo.DoesMaxRowSizeIncludeBlobs: Boolean;
968 begin
969  Result := True;
970 end;
971 
972 {**
973  What's the maximum length of an SQL statement?
974  @return max length in bytes;
975  a result of zero means that there is no limit or the limit is not known
976 }
977 function TZOracleDatabaseInfo.GetMaxStatementLength: Integer;
978 begin
979  Result := 65535;
980 end;
981 
982 {**
983  How many active statements can we have open at one time to this
984  database?
985  @return the maximum number of statements that can be open at one time;
986  a result of zero means that there is no limit or the limit is not known
987 }
988 function TZOracleDatabaseInfo.GetMaxStatements: Integer;
989 begin
990  Result := 0;
991 end;
992 
993 {**
994  What's the maximum length of a table name?
995  @return max name length in bytes;
996  a result of zero means that there is no limit or the limit is not known
997 }
998 function TZOracleDatabaseInfo.GetMaxTableNameLength: Integer;
999 begin
1000  Result := 30;
1001 end;
1002 
1003 {**
1004  What's the maximum number of tables in a SELECT statement?
1005  @return the maximum number of tables allowed in a SELECT statement;
1006  a result of zero means that there is no limit or the limit is not known
1007 }
1008 function TZOracleDatabaseInfo.GetMaxTablesInSelect: Integer;
1009 begin
1010  Result := 0;
1011 end;
1012 
1013 {**
1014  What's the maximum length of a user name?
1015  @return max user name length in bytes;
1016  a result of zero means that there is no limit or the limit is not known
1017 }
1018 function TZOracleDatabaseInfo.GetMaxUserNameLength: Integer;
1019 begin
1020  Result := 30;
1021 end;
1022 
1023 //----------------------------------------------------------------------
1024 
1025 {**
1026  What's the database's default transaction isolation level? The
1027  values are defined in <code>java.sql.Connection</code>.
1028  @return the default isolation level
1029  @see Connection
1030 }
1031 function TZOracleDatabaseInfo.GetDefaultTransactionIsolation:
1032  TZTransactIsolationLevel;
1033 begin
1034  Result := tiReadCommitted;
1035 end;
1036 
1037 {**
1038  Are transactions supported? If not, invoking the method
1039  <code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
1040  @return <code>true</code> if transactions are supported; <code>false</code> otherwise
1041 }
1042 function TZOracleDatabaseInfo.SupportsTransactions: Boolean;
1043 begin
1044  Result := True;
1045 end;
1046 
1047 {**
1048  Does this database support the given transaction isolation level?
1049  @param level the values are defined in <code>java.sql.Connection</code>
1050  @return <code>true</code> if so; <code>false</code> otherwise
1051  @see Connection
1052 }
1053 function TZOracleDatabaseInfo.SupportsTransactionIsolationLevel(
1054  Level: TZTransactIsolationLevel): Boolean;
1055 begin
1056  Result := True;
1057 end;
1058 
1059 {**
1060  Are both data definition and data manipulation statements
1061  within a transaction supported?
1062  @return <code>true</code> if so; <code>false</code> otherwise
1063 }
1064 function TZOracleDatabaseInfo.
1065  SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
1066 begin
1067  Result := True;
1068 end;
1069 
1070 {**
1071  Are only data manipulation statements within a transaction
1072  supported?
1073  @return <code>true</code> if so; <code>false</code> otherwise
1074 }
1075 function TZOracleDatabaseInfo.
1076  SupportsDataManipulationTransactionsOnly: Boolean;
1077 begin
1078  Result := True;
1079 end;
1080 
1081 {**
1082  Does a data definition statement within a transaction force the
1083  transaction to commit?
1084  @return <code>true</code> if so; <code>false</code> otherwise
1085 }
1086 function TZOracleDatabaseInfo.DataDefinitionCausesTransactionCommit: Boolean;
1087 begin
1088  Result := True;
1089 end;
1090 
1091 {**
1092  Is a data definition statement within a transaction ignored?
1093  @return <code>true</code> if so; <code>false</code> otherwise
1094 }
1095 function TZOracleDatabaseInfo.DataDefinitionIgnoredInTransactions: Boolean;
1096 begin
1097  Result := False;
1098 end;
1099 
1100 {**
1101  Does the database support the given result set type?
1102  @param type defined in <code>java.sql.ResultSet</code>
1103  @return <code>true</code> if so; <code>false</code> otherwise
1104 }
1105 function TZOracleDatabaseInfo.SupportsResultSetType(
1106  _Type: TZResultSetType): Boolean;
1107 begin
1108  Result := _Type = rtForwardOnly;
1109 end;
1110 
1111 {**
1112  Does the database support the concurrency type in combination
1113  with the given result set type?
1114 
1115  @param type defined in <code>java.sql.ResultSet</code>
1116  @param concurrency type defined in <code>java.sql.ResultSet</code>
1117  @return <code>true</code> if so; <code>false</code> otherwise
1118 }
1119 function TZOracleDatabaseInfo.SupportsResultSetConcurrency(
1120  _Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
1121 begin
1122  Result := (_Type = rtForwardOnly) and (Concurrency = rcReadOnly);
1123 end;
1124 
1125 {**
1126  Does the Database or Actual Version understand non escaped search strings?
1127  @return <code>true</code> if the DataBase does understand non escaped
1128  search strings
1129 }
1130 function TZOracleDatabaseInfo.SupportsNonEscapedSearchStrings: Boolean;
1131 begin
1132  Result := MetaData.GetConnection.GetClientVersion > 10000000;
1133 end;
1134 
1135 { TZOracleDatabaseMetadata }
1136 
1137 {**
1138  Destroys this object and cleanups the memory.
1139 }
1140 destructor TZOracleDatabaseMetadata.Destroy;
1141 begin
1142  inherited Destroy;
1143 end;
1144 
1145 {**
1146  Constructs a database information object and returns the interface to it. Used
1147  internally by the constructor.
1148  @return the database information object interface
1149 }
1150 function TZOracleDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
1151 begin
1152  Result := TZOracleDatabaseInfo.Create(Self);
1153 end;
1154 
1155 {**
1156  Gets a description of tables available in a catalog.
1157 
1158  <P>Only table descriptions matching the catalog, schema, table
1159  name and type criteria are returned. They are ordered by
1160  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1161 
1162  <P>Each table description has the following columns:
1163  <OL>
1164  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1165  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1166  <LI><B>TABLE_NAME</B> String => table name
1167  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1168  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1169  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1170  <LI><B>REMARKS</B> String => explanatory comment on the table
1171  </OL>
1172 
1173  <P><B>Note:</B> Some databases may not return information for
1174  all tables.
1175 
1176  @param catalog a catalog name; "" retrieves those without a
1177  catalog; null means drop catalog name from the selection criteria
1178  @param schemaPattern a schema name pattern; "" retrieves those
1179  without a schema
1180  @param tableNamePattern a table name pattern
1181  @param types a list of table types to include; null returns all types
1182  @return <code>ResultSet</code> - each row is a table description
1183  @see #getSearchStringEscape
1184 }
1185 function TZOracleDatabaseMetadata.UncachedGetTables(const Catalog: string;
1186  const SchemaPattern: string; const TableNamePattern: string;
1187  const Types: TStringDynArray): IZResultSet;
1188 var
1189  NameCondition, OwnerCondition, PartSQL, SQL: string;
1190 
1191  function IncludedType(const TypeName: string): Boolean;
1192  var I: Integer;
1193  begin
1194  Result := False;
1195  for I := Low(Types) to High(Types) do
1196  Result := Result or (UpperCase(Types[I]) = TypeName);
1197  Result := Result or (Length(Types) = 0);
1198  end;
1199 
1200  function CreateWhere: String;
1201  begin
1202  Result := '';
1203  If OwnerCondition <> '' then
1204  Result := OwnerCondition;
1205  If NameCondition <> '' then
1206  If Result <> '' then
1207  Result := Result + ' AND ' + NameCondition
1208  Else
1209  Result := NameCondition;
1210  If Result <> '' then
1211  Result := ' Where ' + Result;
1212  end;
1213 
1214 begin
1215  OwnerCondition := ConstructNameCondition(SchemaPattern,'OWNER');
1216 
1217  if IncludedType('TABLE') then
1218  begin
1219  NameCondition := ConstructNameCondition(TableNamePattern,'TABLE_NAME');
1220  SQL := 'SELECT NULL AS TABLE_CAT, OWNER AS TABLE_SCHEM, TABLE_NAME,'
1221  + ' ''TABLE'' AS TABLE_TYPE, NULL AS REMARKS FROM SYS.ALL_TABLES'
1222  + CreateWhere;
1223  end else
1224  SQL := '';
1225 
1226  if IncludedType('SYNONYM') then
1227  begin
1228  NameCondition := ConstructNameCondition(TableNamePattern,'SYNONYM_NAME');
1229  PartSQL := 'SELECT NULL AS TABLE_CAT, OWNER AS TABLE_SCHEM,'
1230  + ' SYNONYM_NAME AS TABLE_NAME, ''SYNONYM'' AS TABLE_TYPE,'
1231  + ' NULL AS REMARKS FROM SYS.ALL_SYNONYMS'
1232  + CreateWhere;
1233  if SQL <> '' then
1234  SQL := SQL + ' UNION ';
1235  SQL := SQL + PartSQL;
1236  end;
1237 
1238  if IncludedType('VIEW') then
1239  begin
1240  NameCondition := ConstructNameCondition(TableNamePattern,'VIEW_NAME');
1241  PartSQL := 'SELECT NULL AS TABLE_CAT, OWNER AS TABLE_SCHEM,'
1242  + ' VIEW_NAME AS TABLE_NAME, ''VIEW'' AS TABLE_TYPE,'
1243  + ' NULL AS REMARKS FROM SYS.ALL_VIEWS'
1244  + CreateWhere;
1245  if SQL <> '' then
1246  SQL := SQL + ' UNION ';
1247  SQL := SQL + PartSQL;
1248  end;
1249 
1250  if IncludedType('SEQUENCE') then
1251  begin
1252  OwnerCondition := ConstructNameCondition(SchemaPattern,'SEQUENCE_OWNER');
1253  NameCondition := ConstructNameCondition(TableNamePattern,'SEQUENCE_NAME');
1254  PartSQL := 'SELECT NULL AS TABLE_CAT, SEQUENCE_OWNER AS TABLE_SCHEM,'
1255  + ' SEQUENCE_NAME AS TABLE_NAME, ''SEQUENCE'' AS TABLE_TYPE,'
1256  + ' NULL AS REMARKS FROM SYS.ALL_SEQUENCES'
1257  + CreateWhere;
1258  if SQL <> '' then
1259  SQL := SQL + ' UNION ';
1260  SQL := SQL + PartSQL;
1261  end;
1262 
1263  Result := CopyToVirtualResultSet(
1264  GetConnection.CreateStatement.ExecuteQuery(SQL),
1265  ConstructVirtualResultSet(TableColumnsDynArray));
1266 end;
1267 
1268 
1269 function TZOracleDatabaseMetadata.UncachedGetProcedureColumns(const Catalog,
1270  SchemaPattern, ProcedureNamePattern, ColumnNamePattern: string): IZResultSet;
1271 var
1272  ColumnIndexes : Array[1..9] of integer;
1273  colName: string;
1274  IZStmt: IZStatement;
1275  TempSet: IZResultSet;
1276  Names, Procs: TStrings;
1277  PackageName, ProcName, TempProcedureNamePattern, TmpSchemaPattern: String;
1278 
1279  function GetNextName(const AName: String; NameEmpty: Boolean = False): String;
1280  var
1281  N: Integer;
1282  NewName: String;
1283  begin
1284  if ( PackageName = '' ) or ( not ( PackageName = ProcedureNamePattern ) ) then
1285  NewName := AName
1286  else
1287  NewName := ProcName+'.'+AName;
1288  if (Names.IndexOf(NewName) = -1) and not NameEmpty then
1289  begin
1290  Names.Add(NewName);
1291  Result := NewName;
1292  end
1293  else
1294  for N := 1 to MaxInt do
1295  if Names.IndexOf(NewName+IntToStr(N)) = -1 then
1296  begin
1297  Result := NewName+IntToStr(N);
1298  Names.Add(Result);
1299  Break;
1300  end;
1301  end;
1302 
1303  procedure InsertProcedureColumnValues(Source: IZResultSet; IsResultParam: Boolean = False);
1304  var
1305  TypeName, SubTypeName: string;
1306  begin
1307  TypeName := Source.GetString(ColumnIndexes[4]);
1308  SubTypeName := Source.GetString(ColumnIndexes[5]);
1309  PackageName := Source.GetString(ColumnIndexes[8]);
1310  ProcName := Source.GetString(ColumnIndexes[9]);
1311 
1312  Result.MoveToInsertRow;
1313  Result.UpdateNull(1); //PROCEDURE_CAT
1314  Result.UpdateNull(2); //PROCEDURE_SCHEM
1315  Result.UpdateString(3, Source.GetString(ColumnIndexes[1])); //TABLE_NAME
1316  if IsResultParam then
1317  Result.UpdateInt(5, Ord(pctReturn))
1318  else
1319  if Source.GetString(ColumnIndexes[3]) = 'IN' then
1320  Result.UpdateInt(5, Ord(pctIn))
1321  else
1322  if Source.GetString(ColumnIndexes[3]) = 'OUT' then
1323  Result.UpdateInt(5, Ord(pctOut))
1324  else
1325  if ( Source.GetString(ColumnIndexes[3]) = 'IN/OUT') then
1326  Result.UpdateInt(5, Ord(pctInOut))
1327  else
1328  Result.UpdateInt(5, Ord(pctUnknown));
1329 
1330  ColName := Source.GetString(ColumnIndexes[2]);
1331  if IsResultParam then
1332  Result.UpdateString(4, GetNextName('ReturnValue', False)) //COLUMN_NAME
1333  else
1334  Result.UpdateString(4, GetNextName(ColName, Length(ColName) = 0)); //COLUMN_NAME
1335 
1336  Result.UpdateInt(6, Ord(ConvertOracleTypeToSQLType(TypeName,
1337  Source.GetInt(ColumnIndexes[6]),Source.GetInt(ColumnIndexes[7]),
1338  ConSettings.CPType))); //DATA_TYPE
1339  Result.UpdateString(7,TypeName); //TYPE_NAME
1340  Result.UpdateInt(10, Source.GetInt(ColumnIndexes[6])); //PRECISION
1341  Result.UpdateNull(9); //BUFFER_LENGTH
1342  Result.UpdateInt(10, Source.GetInt(ColumnIndexes[7]));
1343  Result.UpdateInt(11, 10);
1344  //Result.UpdateInt(12, GetInt(ColumnIndexes[8]));
1345  Result.UpdateNull(12);
1346  Result.UpdateString(12, Source.GetString(ColumnIndexes[6]));
1347  Result.InsertRow;
1348  end;
1349 
1350  function GetColumnSQL(PosChar: String; Package: String = ''): String;
1351  var
1352  OwnerCondition, PackageNameCondition, PackageAsProcCondition, PackageProcNameCondition: string;
1353 
1354  procedure SplitPackageAndProc(Value: String);
1355  var
1356  iPos: Integer;
1357  begin
1358  PackageName := '';
1359  ProcName := 'Value';
1360  iPos := Pos('.', Value);
1361  if (iPos > 0) then
1362  begin
1363  PackageNameCondition := ConstructNameCondition(Copy(Value, 1, iPos-1),'package_name');
1364  PackageProcNameCondition := ConstructNameCondition(Copy(Value, iPos+1,Length(Value)-iPos),'object_name');
1365  PackageAsProcCondition := ConstructNameCondition(Copy(Value, iPos+1,Length(Value)-iPos),'package_name');
1366  PackageName := '= '+#39+IC.ExtractQuote(Copy(Value, 1, iPos-1))+#39;
1367  ProcName := IC.ExtractQuote(Copy(Value, iPos+1,Length(Value)-iPos));
1368  end
1369  else
1370  begin
1371  PackageNameCondition := 'package_name IS NULL';
1372  PackageProcNameCondition := ConstructNameCondition(Value,'object_name');
1373  PackageAsProcCondition := ConstructNameCondition(Value,'package_name');
1374  PackageName := 'IS NULL';
1375  ProcName := IC.ExtractQuote(Value);
1376  end;
1377  end;
1378  begin
1379  OwnerCondition := ConstructNameCondition(TmpSchemaPattern,'OWNER');
1380  SplitPackageAndProc(TempProcedureNamePattern);
1381  Result := 'select * from all_arguments where ('+PackageNameCondition+
1382  ' AND '+PackageProcNameCondition+
1383  ' OR '+ PackageAsProcCondition+')'+
1384  'AND POSITION '+PosChar+' 0';
1385  If OwnerCondition <> '' then
1386  Result := Result + ' AND ' + OwnerCondition;
1387  Result := Result + ' ORDER BY POSITION';
1388  end;
1389 
1390  procedure AddColumns(WasNext: Boolean; WasFunc: Boolean);
1391  begin
1392  if WasNext then InsertProcedureColumnValues(TempSet, WasFunc);
1393  while TempSet.Next do
1394  InsertProcedureColumnValues(TempSet, WasFunc);
1395  TempSet.Close;
1396 
1397  if not WasFunc then
1398  begin
1399  TempSet := IZStmt.ExecuteQuery(GetColumnSQL('=')); //ReturnValue has allways Position = 0
1400  with TempSet do
1401  begin
1402  while Next do
1403  InsertProcedureColumnValues(TempSet, True);
1404  Close;
1405  end;
1406  end;
1407  end;
1408 
1409  procedure GetMoreProcedures;
1410  var
1411  i: Integer;
1412  PackageNameCondition: String;
1413  begin
1414  PackageNameCondition := ConstructNameCondition(ProcedureNamePattern,'package_name');
1415  If PackageNameCondition <> '' then
1416  PackageNameCondition := ' WHERE ' + PackageNameCondition;
1417  TempSet.Close;
1418  TempSet := IZStmt.ExecuteQuery('select object_name from user_arguments '
1419  + PackageNameCondition + ' GROUP BY object_name order by object_name');
1420  while TempSet.Next do
1421  Procs.Add(TempSet.GetString(1));
1422  TempSet.Close;
1423  for i := 0 to Procs.Count -1 do
1424  begin
1425  TempProcedureNamePattern := ProcedureNamePattern+'.'+IC.Quote(Procs[i]);
1426  TempSet := IZStmt.ExecuteQuery(GetColumnSQL('>')); //ParameterValues have allways Position > 0
1427  AddColumns(False, False);
1428  end;
1429  end;
1430 
1431  function CheckSchema: Boolean;
1432  begin
1433  if TmpSchemaPattern = '' then
1434  Result := False
1435  else
1436  with GetConnection.CreateStatement.ExecuteQuery('SELECT COUNT(*) FROM ALL_USERS WHERE '+ConstructNameCondition(TmpSchemaPattern,'username')) do
1437  begin
1438  Next;
1439  Result := GetInt(1) > 0;
1440  Close;
1441  end;
1442  end;
1443 begin
1444  Result:=inherited UncachedGetProcedureColumns(Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern);
1445 
1446  {improve SplitQualifiedObjectName: Oracle does'nt support catalogs}
1447  if Catalog = '' then
1448  TmpSchemaPattern := SchemaPattern
1449  else
1450  TmpSchemaPattern := Catalog;
1451 
1452  if ( TmpSchemaPattern = '' ) then
1453  TempProcedureNamePattern := ProcedureNamePattern //just a procedurename or package or both
1454  else
1455  if CheckSchema then
1456  TempProcedureNamePattern := ProcedureNamePattern //Schema exists not a package
1457  else
1458  begin
1459  TempProcedureNamePattern := TmpSchemaPattern+'.'+ProcedureNamePattern; //no Schema so it's a PackageName
1460  TmpSchemaPattern := '';
1461  end;
1462  if TempProcedureNamePattern <> '' then
1463  begin
1464  Names := TStringList.Create;
1465  Procs := TStringList.Create;
1466 
1467  IZStmt := GetConnection.CreateStatement;
1468  TempSet := IZStmt.ExecuteQuery(GetColumnSQL('>')); //ParameterValues have allways Position > 0
1469 
1470  with TempSet do
1471  begin
1472  ColumnIndexes[1] := FindColumn('object_name');
1473  ColumnIndexes[2] := FindColumn('argument_name');
1474  ColumnIndexes[3] := FindColumn('IN_OUT'); //'RDB$PARAMETER_TYPE');
1475  ColumnIndexes[4] := FindColumn('DATA_TYPE');//'RDB$FIELD_TYPE');
1476  ColumnIndexes[5] := FindColumn('TYPE_SUBNAME');//RDB$FIELD_SUB_TYPE');
1477  ColumnIndexes[6] := FindColumn('DATA_PRECISION');//RDB$FIELD_PRECISION');
1478  ColumnIndexes[7] := FindColumn('DATA_SCALE');//RDB$FIELD_SCALE');
1479  ColumnIndexes[8] := FindColumn('package_name');
1480  ColumnIndexes[9] := FindColumn('object_name');
1481  end;
1482  if ( PackageName <> 'IS NULL' ) and ( ProcName <> '' ) then
1483  AddColumns(False, False)
1484  else
1485  if TempSet.Next then
1486  if ( TempSet.GetString(ColumnIndexes[8]) = ProcName ) then
1487  {Package without proc found}
1488  GetMoreProcedures
1489  else
1490  AddColumns(True, False)
1491  else
1492  begin
1493  TempSet.Close;
1494  TempSet := IZStmt.ExecuteQuery(GetColumnSQL('=')); //ParameterValues have allways Position > 0
1495  if TempSet.Next then
1496  if ( TempSet.GetString(ColumnIndexes[8]) = ProcName ) then
1497  {Package without proc found}
1498  GetMoreProcedures
1499  else
1500  AddColumns(True, True)
1501  end;
1502  TempSet := nil;
1503  IZStmt.Close;
1504  FreeAndNil(Names);
1505  FreeAndNil(Procs);
1506  end;
1507 end;
1508 
1509 function TZOracleDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
1510  const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
1511 var
1512  SQL: string;
1513  LProcedureNamePattern, LSchemaNamePattern: string;
1514  sName:string;
1515 begin
1516  Result:=inherited UncachedGetProcedures(Catalog, SchemaPattern, ProcedureNamePattern);
1517 
1518  LProcedureNamePattern := ConstructNameCondition(ProcedureNamePattern,'decode(procedure_name,null,object_name,object_name||''.''||procedure_name)');
1519  LSchemaNamePattern := ConstructNameCondition(SchemaPattern,'owner');
1520  SQL := 'select NULL AS PROCEDURE_CAT, OWNER AS PROCEDURE_SCHEM, '+
1521  'OBJECT_NAME, PROCEDURE_NAME AS PROCEDURE_NAME, '+
1522  'OVERLOAD AS PROCEDURE_OVERLOAD, OBJECT_TYPE AS PROCEDURE_TYPE FROM '+
1523  'ALL_PROCEDURES WHERE 1=1';
1524  if LProcedureNamePattern <> '' then
1525  SQL := SQL + ' AND ' + LProcedureNamePattern;
1526  if LSchemaNamePattern <> '' then
1527  SQL := SQL + ' AND ' + LSchemaNamePattern;
1528  SQL := SQL + ' ORDER BY decode(owner,user,0,1),owner,object_name,procedure_name,overload';
1529 
1530  with GetConnection.CreateStatement.ExecuteQuery(SQL) do
1531  begin
1532  while Next do
1533  begin
1534  sName := IC.Quote(GetString(3));
1535  if GetString(4) <> '' then
1536  sName := sName+'.'+IC.Quote(GetString(4));
1537  Result.MoveToInsertRow;
1538  Result.UpdateNull(1);
1539  Result.UpdateString(2, GetString(2));
1540  Result.UpdateString(3, sName); //PROCEDURE_NAME
1541  Result.UpdateString(4, GetString(5)); //PROCEDURE_OVERLOAD
1542  Result.UpdateNull(5);
1543  Result.UpdateNull(6);
1544  Result.UpdateNull(7);
1545  if GetString(6) = 'FUNCTION' then
1546  Result.UpdateInt(8, Ord(prtReturnsResult))
1547  else if GetString(6) = 'PROCDEURE' then
1548  Result.UpdateInt(8, Ord(prtNoResult))
1549  else
1550  Result.UpdateInt(8, Ord(prtUnknown)); //Package
1551  Result.InsertRow;
1552  end;
1553  Close;
1554  end;
1555 end;
1556 
1557 
1558 {**
1559  Gets the schema names available in this database. The results
1560  are ordered by schema name.
1561 
1562  <P>The schema column is:
1563  <OL>
1564  <LI><B>TABLE_SCHEM</B> String => schema name
1565  </OL>
1566 
1567  @return <code>ResultSet</code> - each row has a single String column that is a
1568  schema name
1569 }
1570 function TZOracleDatabaseMetadata.UncachedGetSchemas: IZResultSet;
1571 begin
1572  Result := CopyToVirtualResultSet(
1573  GetConnection.CreateStatement.ExecuteQuery(
1574  'SELECT USERNAME AS TABLE_SCHEM FROM SYS.ALL_USERS'),
1575  ConstructVirtualResultSet(SchemaColumnsDynArray));
1576 end;
1577 
1578 {**
1579  Gets the table types available in this database. The results
1580  are ordered by table type.
1581 
1582  <P>The table type is:
1583  <OL>
1584  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1585  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1586  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1587  </OL>
1588 
1589  @return <code>ResultSet</code> - each row has a single String column that is a
1590  table type
1591 }
1592 function TZOracleDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
1593 const
1594  TableTypeCount = 4;
1595  Types: array [1..TableTypeCount] of String = (
1596  'TABLE', 'SYNONYM', 'VIEW', 'SEQUENCE'
1597  );
1598 var
1599  I: Integer;
1600 begin
1601  Result:=inherited UncachedGetTableTypes;
1602 
1603  for I := 1 to TableTypeCount do
1604  begin
1605  Result.MoveToInsertRow;
1606  Result.UpdateString(1, Types[I]);
1607  Result.InsertRow;
1608  end;
1609 end;
1610 
1611 {**
1612  Gets a description of table columns available in
1613  the specified catalog.
1614 
1615  <P>Only column descriptions matching the catalog, schema, table
1616  and column name criteria are returned. They are ordered by
1617  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1618 
1619  <P>Each column description has the following columns:
1620  <OL>
1621  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1622  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1623  <LI><B>TABLE_NAME</B> String => table name
1624  <LI><B>COLUMN_NAME</B> String => column name
1625  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1626  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
1627  for a UDT the type name is fully qualified
1628  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1629  types this is the maximum number of characters, for numeric or
1630  decimal types this is precision.
1631  <LI><B>BUFFER_LENGTH</B> is not used.
1632  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1633  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1634  <LI><B>NULLABLE</B> int => is NULL allowed?
1635  <UL>
1636  <LI> columnNoNulls - might not allow NULL values
1637  <LI> columnNullable - definitely allows NULL values
1638  <LI> columnNullableUnknown - nullability unknown
1639  </UL>
1640  <LI><B>REMARKS</B> String => comment describing column (may be null)
1641  <LI><B>COLUMN_DEF</B> String => default value (may be null)
1642  <LI><B>SQL_DATA_TYPE</B> int => unused
1643  <LI><B>SQL_DATETIME_SUB</B> int => unused
1644  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1645  maximum number of bytes in the column
1646  <LI><B>ORDINAL_POSITION</B> int => index of column in table
1647  (starting at 1)
1648  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1649  does not allow NULL values; "YES" means the column might
1650  allow NULL values. An empty string means nobody knows.
1651  </OL>
1652 
1653  @param catalog a catalog name; "" retrieves those without a
1654  catalog; null means drop catalog name from the selection criteria
1655  @param schemaPattern a schema name pattern; "" retrieves those
1656  without a schema
1657  @param tableNamePattern a table name pattern
1658  @param columnNamePattern a column name pattern
1659  @return <code>ResultSet</code> - each row is a column description
1660  @see #getSearchStringEscape
1661 }
1662 function TZOracleDatabaseMetadata.UncachedGetColumns(const Catalog: string;
1663  const SchemaPattern: string; const TableNamePattern: string;
1664  const ColumnNamePattern: string): IZResultSet;
1665 var
1666  SQL: string;
1667  SQLType: TZSQLType;
1668  OwnerCondition,TableCondition,ColumnCondition: String;
1669 
1670  function CreateWhere: String;
1671  begin
1672  Result := '';
1673  If OwnerCondition <> '' then
1674  Result := OwnerCondition;
1675  If TableCondition <> '' then
1676  If Result <> '' then
1677  Result := Result + ' AND ' + TableCondition
1678  Else
1679  Result := TableCondition;
1680  If ColumnCondition <> '' then
1681  If Result <> '' then
1682  Result := Result + ' AND ' + ColumnCondition
1683  Else
1684  Result := ColumnCondition;
1685  If Result <> '' then
1686  Result := ' Where ' + Result;
1687  end;
1688 
1689 begin
1690  OwnerCondition := ConstructNameCondition(SchemaPattern,'OWNER');
1691  TableCondition := ConstructNameCondition(TableNamePattern,'TABLE_NAME');
1692  ColumnCondition := ConstructNameCondition(ColumnNamePattern,'COLUMN_NAME');
1693  Result:=inherited UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
1694 
1695  SQL := 'SELECT NULL, OWNER, TABLE_NAME, COLUMN_NAME, NULL, DATA_TYPE,'
1696  + ' DATA_LENGTH, NULL, DATA_PRECISION, DATA_SCALE, NULLABLE, NULL,'
1697  + ' DATA_DEFAULT, NULL, NULL, NULL, COLUMN_ID, NULLABLE'
1698  + ' FROM SYS.ALL_TAB_COLUMNS'
1699  + CreateWhere;
1700 
1701  with GetConnection.CreateStatement.ExecuteQuery(SQL) do
1702  begin
1703  while Next do
1704  begin
1705  Result.MoveToInsertRow;
1706  Result.UpdateNull(1);
1707  Result.UpdateString(2, GetString(2));
1708  Result.UpdateString(3, GetString(3));
1709  Result.UpdateString(4, GetString(4));
1710  SQLType := ConvertOracleTypeToSQLType(GetString(6), GetInt(9),
1711  GetInt(10), ConSettings.CPType);
1712  Result.UpdateInt(5, Ord(SQLType));
1713  Result.UpdateString(6, GetString(6));
1714  Result.UpdateInt(7, GetFieldSize(SQLType, ConSettings, GetInt(7), ConSettings.ClientCodePage.CharWidth)); //FIELD_SIZE
1715  Result.UpdateNull(8);
1716  Result.UpdateInt(9, GetInt(9));
1717  Result.UpdateInt(10, GetInt(10));
1718 
1719  if UpperCase(GetString(11)) = 'N' then
1720  begin
1721  Result.UpdateInt(11, Ord(ntNoNulls));
1722  Result.UpdateString(18, 'NO');
1723  end
1724  else
1725  begin
1726  Result.UpdateInt(11, Ord(ntNullable));
1727  Result.UpdateString(18, 'YES');
1728  end;
1729 
1730  Result.UpdateNull(12);
1731  Result.UpdateString(13, GetString(13));
1732  Result.UpdateNull(14);
1733  Result.UpdateNull(15);
1734  Result.UpdateNull(16);
1735  Result.UpdateInt(17, GetInt(17));
1736 
1737  Result.UpdateNull(19); //AUTO_INCREMENT
1738  Result.UpdateBoolean(20, //CASE_SENSITIVE
1739  IC.IsCaseSensitive(GetString(4)));
1740  Result.UpdateBoolean(21, True); //SEARCHABLE
1741  Result.UpdateBoolean(22, not (GetString(6) = 'BFILE')); //WRITABLE
1742  Result.UpdateBoolean(23, True); //DEFINITELYWRITABLE
1743  Result.UpdateBoolean(24, (GetString(6) = 'BFILE')); //READONLY
1744 
1745  Result.InsertRow;
1746  end;
1747  Close;
1748  end;
1749 end;
1750 
1751 {**
1752  Gets a description of the access rights for a table's columns.
1753 
1754  <P>Only privileges matching the column name criteria are
1755  returned. They are ordered by COLUMN_NAME and PRIVILEGE.
1756 
1757  <P>Each privilige description has the following columns:
1758  <OL>
1759  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1760  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1761  <LI><B>TABLE_NAME</B> String => table name
1762  <LI><B>COLUMN_NAME</B> String => column name
1763  <LI><B>GRANTOR</B> => grantor of access (may be null)
1764  <LI><B>GRANTEE</B> String => grantee of access
1765  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1766  INSERT, UPDATE, REFRENCES, ...)
1767  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1768  to grant to others; "NO" if not; null if unknown
1769  </OL>
1770 
1771  @param catalog a catalog name; "" retrieves those without a
1772  catalog; null means drop catalog name from the selection criteria
1773  @param schema a schema name; "" retrieves those without a schema
1774  @param table a table name
1775  @param columnNamePattern a column name pattern
1776  @return <code>ResultSet</code> - each row is a column privilege description
1777  @see #getSearchStringEscape
1778 }
1779 function TZOracleDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
1780  const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
1781 var
1782  SQL: string;
1783  OwnerCondition,TableCondition,ColumnCondition: String;
1784 
1785  function CreateWhere: String;
1786  begin
1787  Result := '';
1788  If OwnerCondition <> '' then
1789  Result := OwnerCondition;
1790  If TableCondition <> '' then
1791  If Result <> '' then
1792  Result := Result + ' AND ' + TableCondition
1793  Else
1794  Result := TableCondition;
1795  If ColumnCondition <> '' then
1796  If Result <> '' then
1797  Result := Result + ' AND ' + ColumnCondition
1798  Else
1799  Result := ColumnCondition;
1800  If Result <> '' then
1801  Result := ' Where ' + Result;
1802  end;
1803 
1804 begin
1805  OwnerCondition := ConstructNameCondition(Schema,'TABLE_SCHEMA');
1806  TableCondition := ConstructNameCondition(Table,'TABLE_NAME');
1807  ColumnCondition := ConstructNameCondition(ColumnNamePattern,'COLUMN_NAME');
1808  SQL := 'SELECT NULL AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME,'
1809  + ' COLUMN_NAME, GRANTOR, GRANTEE, PRIVILEGE, GRANTABLE AS IS_GRANTABLE'
1810  + ' FROM SYS.ALL_COL_PRIVS'
1811  + CreateWhere;
1812 
1813  Result := CopyToVirtualResultSet(
1814  GetConnection.CreateStatement.ExecuteQuery(SQL),
1815  ConstructVirtualResultSet(TableColPrivColumnsDynArray));
1816 end;
1817 
1818 {**
1819  Gets a description of the access rights for each table available
1820  in a catalog. Note that a table privilege applies to one or
1821  more columns in the table. It would be wrong to assume that
1822  this priviledge applies to all columns (this may be true for
1823  some systems but is not true for all.)
1824 
1825  <P>Only privileges matching the schema and table name
1826  criteria are returned. They are ordered by TABLE_SCHEM,
1827  TABLE_NAME, and PRIVILEGE.
1828 
1829  <P>Each privilige description has the following columns:
1830  <OL>
1831  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1832  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1833  <LI><B>TABLE_NAME</B> String => table name
1834  <LI><B>GRANTOR</B> => grantor of access (may be null)
1835  <LI><B>GRANTEE</B> String => grantee of access
1836  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1837  INSERT, UPDATE, REFRENCES, ...)
1838  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1839  to grant to others; "NO" if not; null if unknown
1840  </OL>
1841 
1842  @param catalog a catalog name; "" retrieves those without a
1843  catalog; null means drop catalog name from the selection criteria
1844  @param schemaPattern a schema name pattern; "" retrieves those
1845  without a schema
1846  @param tableNamePattern a table name pattern
1847  @return <code>ResultSet</code> - each row is a table privilege description
1848  @see #getSearchStringEscape
1849 }
1850 function TZOracleDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
1851  const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
1852 var
1853  SQL: string;
1854  OwnerCondition,TableCondition: String;
1855 
1856  function CreateWhere: String;
1857  begin
1858  Result := '';
1859  If OwnerCondition <> '' then
1860  Result := OwnerCondition;
1861  If TableCondition <> '' then
1862  If Result <> '' then
1863  Result := Result + ' AND ' + TableCondition
1864  Else
1865  Result := TableCondition;
1866  If Result <> '' then
1867  Result := ' Where ' + Result;
1868  end;
1869 
1870 begin
1871  OwnerCondition := ConstructNameCondition(SchemaPattern,'TABLE_SCHEMA');
1872  TableCondition := ConstructNameCondition(TableNamePattern,'TABLE_NAME');
1873  SQL := 'SELECT NULL AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME,'
1874  + ' GRANTOR, GRANTEE, PRIVILEGE, GRANTABLE AS IS_GRANTABLE'
1875  + ' FROM SYS.ALL_TAB_PRIVS '
1876  + CreateWhere;
1877 
1878  Result := CopyToVirtualResultSet(
1879  GetConnection.CreateStatement.ExecuteQuery(SQL),
1880  ConstructVirtualResultSet(TablePrivColumnsDynArray));
1881 end;
1882 
1883 {**
1884  Gets a description of a table's primary key columns. They
1885  are ordered by COLUMN_NAME.
1886 
1887  <P>Each primary key column description has the following columns:
1888  <OL>
1889  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1890  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1891  <LI><B>TABLE_NAME</B> String => table name
1892  <LI><B>COLUMN_NAME</B> String => column name
1893  <LI><B>KEY_SEQ</B> short => sequence number within primary key
1894  <LI><B>PK_NAME</B> String => primary key name (may be null)
1895  </OL>
1896 
1897  @param catalog a catalog name; "" retrieves those without a
1898  catalog; null means drop catalog name from the selection criteria
1899  @param schema a schema name; "" retrieves those
1900  without a schema
1901  @param table a table name
1902  @return <code>ResultSet</code> - each row is a primary key column description
1903  @exception SQLException if a database access error occurs
1904 }
1905 function TZOracleDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
1906  const Schema: string; const Table: string): IZResultSet;
1907 var
1908  SQL: string;
1909  OwnerCondition,TableCondition: String;
1910 
1911  function CreateExtraWhere: String;
1912  begin
1913  Result := '';
1914  If OwnerCondition <> '' then
1915  Result := OwnerCondition;
1916  If TableCondition <> '' then
1917  If Result <> '' then
1918  Result := Result + ' AND ' + TableCondition
1919  Else
1920  Result := TableCondition;
1921  If Result <> '' then
1922  Result := ' AND ' + Result;
1923  end;
1924 
1925 begin
1926  OwnerCondition := ConstructNameCondition(Schema,'A.OWNER');
1927  TableCondition := ConstructNameCondition(Table,'A.TABLE_NAME');
1928  SQL := 'SELECT NULL AS TABLE_CAT, A.OWNER AS TABLE_SCHEM, A.TABLE_NAME,'
1929  + ' B.COLUMN_NAME, B.COLUMN_POSITION AS KEY_SEQ, A.INDEX_NAME AS PK_NAME'
1930  + ' FROM ALL_INDEXES A, ALL_IND_COLUMNS B'
1931  + ' WHERE A.OWNER=B.INDEX_OWNER AND A.INDEX_NAME=B.INDEX_NAME'
1932  + ' AND A.TABLE_OWNER=B.TABLE_OWNER AND A.TABLE_NAME=B.TABLE_NAME'
1933  + ' AND A.UNIQUENESS=''UNIQUE'' AND A.GENERATED=''Y'''
1934  + ' AND A.INDEX_NAME LIKE ''SYS_%'''
1935  + CreateExtraWhere
1936  + ' ORDER BY A.INDEX_NAME, B.COLUMN_POSITION';
1937 
1938  Result := CopyToVirtualResultSet(
1939  GetConnection.CreateStatement.ExecuteQuery(SQL),
1940  ConstructVirtualResultSet(PrimaryKeyColumnsDynArray));
1941 end;
1942 
1943 {**
1944  Gets a description of a table's indices and statistics. They are
1945  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
1946 
1947  <P>Each index column description has the following columns:
1948  <OL>
1949  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1950  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1951  <LI><B>TABLE_NAME</B> String => table name
1952  <LI><B>NON_UNIQUE</B> Boolean => Can index values be non-unique?
1953  false when TYPE is tableIndexStatistic
1954  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
1955  null when TYPE is tableIndexStatistic
1956  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
1957  tableIndexStatistic
1958  <LI><B>TYPE</B> short => index type:
1959  <UL>
1960  <LI> tableIndexStatistic - this identifies table statistics that are
1961  returned in conjuction with a table's index descriptions
1962  <LI> tableIndexClustered - this is a clustered index
1963  <LI> tableIndexHashed - this is a hashed index
1964  <LI> tableIndexOther - this is some other style of index
1965  </UL>
1966  <LI><B>ORDINAL_POSITION</B> short => column sequence number
1967  within index; zero when TYPE is tableIndexStatistic
1968  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
1969  tableIndexStatistic
1970  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
1971  "D" => descending, may be null if sort sequence is not supported;
1972  null when TYPE is tableIndexStatistic
1973  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
1974  this is the number of rows in the table; otherwise, it is the
1975  number of unique values in the index.
1976  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
1977  this is the number of pages used for the table, otherwise it
1978  is the number of pages used for the current index.
1979  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
1980  (may be null)
1981  </OL>
1982 
1983  @param catalog a catalog name; "" retrieves those without a
1984  catalog; null means drop catalog name from the selection criteria
1985  @param schema a schema name; "" retrieves those without a schema
1986  @param table a table name
1987  @param unique when true, return only indices for unique values;
1988  when false, return indices regardless of whether unique or not
1989  @param approximate when true, result is allowed to reflect approximate
1990  or out of data values; when false, results are requested to be
1991  accurate
1992  @return <code>ResultSet</code> - each row is an index column description
1993 }
1994 function TZOracleDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
1995  const Schema: string; const Table: string; Unique: Boolean;
1996  Approximate: Boolean): IZResultSet;
1997 var
1998  SQL: string;
1999  OwnerCondition,TableCondition: String;
2000 
2001  function CreateExtraWhere: String;
2002  begin
2003  Result := '';
2004  If OwnerCondition <> '' then
2005  Result := OwnerCondition;
2006  If TableCondition <> '' then
2007  If Result <> '' then
2008  Result := Result + ' AND ' + TableCondition
2009  Else
2010  Result := TableCondition;
2011  If Result <> '' then
2012  Result := ' AND ' + Result;
2013  end;
2014 
2015 begin
2016  OwnerCondition := ConstructNameCondition(Schema,'A.TABLE_OWNER');
2017  TableCondition := ConstructNameCondition(Table,'A.TABLE_NAME');
2018  Result:=inherited UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
2019 
2020  SQL := 'SELECT NULL, A.OWNER, A.TABLE_NAME, A.UNIQUENESS, NULL,'
2021  + ' A.INDEX_NAME, 3, B.COLUMN_POSITION, B.COLUMN_NAME, B.DESCEND,'
2022  + ' 0, 0, NULL FROM ALL_INDEXES A, ALL_IND_COLUMNS B'
2023  + ' WHERE A.OWNER=B.INDEX_OWNER AND A.INDEX_NAME=B.INDEX_NAME'
2024  + ' AND A.TABLE_OWNER=B.TABLE_OWNER AND A.TABLE_NAME=B.TABLE_NAME'
2025  + CreateExtraWhere;
2026  if Unique then
2027  SQL := SQL + ' AND A.UNIQUENESS=''UNIQUE''';
2028  SQL := SQL + ' ORDER BY A.UNIQUENESS DESC, A.INDEX_NAME, B.COLUMN_POSITION';
2029 
2030  with GetConnection.CreateStatement.ExecuteQuery(SQL) do
2031  begin
2032  while Next do
2033  begin
2034  Result.MoveToInsertRow;
2035 
2036  Result.UpdateNull(1);
2037  Result.UpdateString(2, GetString(2));
2038  Result.UpdateString(3, GetString(3));
2039  Result.UpdateBoolean(4,
2040  UpperCase(GetString(4)) <> 'UNIQUE');
2041  Result.UpdateNull(5);
2042  Result.UpdateString(6, GetString(6));
2043  Result.UpdateInt(7, GetInt(7));
2044  Result.UpdateInt(8, GetInt(8));
2045  Result.UpdateString(9, GetString(9));
2046  if GetString(10) = 'ASC' then
2047  Result.UpdateString(10, 'A')
2048  else Result.UpdateString(10, 'D');
2049  Result.UpdateInt(11, GetInt(11));
2050  Result.UpdateInt(12, GetInt(12));
2051  Result.UpdateNull(13);
2052 
2053  Result.InsertRow;
2054  end;
2055  Close;
2056  end;
2057 end;
2058 
2059 end.