1 {*********************************************************}
3 { Zeos Database Objects }
4 { MySQL Database Connectivity Classes }
6 { Originally written by Sergey Seroukhov }
7 { and Sergey Merkuriev }
9 {*********************************************************}
11 {@********************************************************}
12 { Copyright (c) 1999-2012 Zeos Development Group }
14 { License Agreement: }
16 { This library is distributed in the hope that it will be }
17 { useful, but WITHOUT ANY WARRANTY; without even the }
18 { implied warranty of MERCHANTABILITY or FITNESS FOR }
19 { A PARTICULAR PURPOSE. See the GNU Lesser General }
20 { Public License for more details. }
22 { The source code of the ZEOS Libraries and packages are }
23 { distributed under the Library GNU General Public }
24 { License (see the file COPYING / COPYING.ZEOS) }
25 { with the following modification: }
26 { As a special exception, the copyright holders of this }
27 { library give you permission to link this library with }
28 { independent modules to produce an executable, }
29 { regardless of the license terms of these independent }
30 { modules, and to copy and distribute the resulting }
31 { executable under terms of your choice, provided that }
32 { you also meet, for each linked independent module, }
33 { the terms and conditions of the license of that module. }
34 { An independent module is a module which is not derived }
35 { from or based on this library. If you modify this }
36 { library, you may extend this exception to your version }
37 { of the library, but you are not obligated to do so. }
38 { If you do not wish to do so, delete this exception }
39 { statement from your version. }
42 { The project web site is located on: }
43 { http://zeos.firmos.at (FORUM) }
44 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
45 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
47 { http://www.sourceforge.net/projects/zeoslib. }
50 { Zeos Development Group. }
51 {********************************************************@}
53 unit ZDbcMySqlMetadata;
60 Types, Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils,
61 ZClasses, ZSysUtils, ZDbcIntfs, ZDbcMetadata, ZDbcResultSet, ZDbcConnection,
62 ZDbcCachedResultSet, ZDbcResultSetMetadata, ZURL, ZCompatibility;
66 // technobot 2008-06-26 - methods moved as is from TZMySQLDatabaseMetadata:
67 {** Implements MySQL Database Information. }
68 TZMySQLDatabaseInfo = class(TZAbstractDatabaseInfo)
70 procedure GetVersion(var MajorVersion, MinorVersion: integer);
72 constructor Create(const Metadata: TZAbstractDatabaseMetadata);
74 // database/driver/server info:
75 function GetDatabaseProductName: string; override;
76 function GetDatabaseProductVersion: string; override;
77 function GetDriverName: string; override;
78 // function GetDriverVersion: string; override; -> Same as parent
79 function GetDriverMajorVersion: Integer; override;
80 function GetDriverMinorVersion: Integer; override;
81 // function GetServerVersion: string; -> Not implemented
83 // capabilities (what it can/cannot do):
84 // function AllProceduresAreCallable: Boolean; override; -> Not implemented
85 // function AllTablesAreSelectable: Boolean; override; -> Not implemented
86 // function SupportsMixedCaseIdentifiers: Boolean; override; -> Not implemented
87 // function SupportsMixedCaseQuotedIdentifiers: Boolean; override; -> Not implemented
88 // function SupportsAlterTableWithAddColumn: Boolean; override; -> Not implemented
89 // function SupportsAlterTableWithDropColumn: Boolean; override; -> Not implemented
90 // function SupportsColumnAliasing: Boolean; override; -> Not implemented
91 // function SupportsConvert: Boolean; override; -> Not implemented
92 // function SupportsConvertForTypes(FromType: TZSQLType; ToType: TZSQLType):
93 // Boolean; override; -> Not implemented
94 // function SupportsTableCorrelationNames: Boolean; override; -> Not implemented
95 // function SupportsDifferentTableCorrelationNames: Boolean; override; -> Not implemented
96 // function SupportsExpressionsInOrderBy: Boolean; override; -> Not implemented
97 function SupportsOrderByUnrelated: Boolean; override;
98 // function SupportsGroupBy: Boolean; override; -> Not implemented
99 function SupportsGroupByUnrelated: Boolean; override;
100 function SupportsGroupByBeyondSelect: Boolean; override;
101 // function SupportsLikeEscapeClause: Boolean; override; -> Not implemented
102 // function SupportsMultipleResultSets: Boolean; override; -> Not implemented
103 // function SupportsMultipleTransactions: Boolean; override; -> Not implemented
104 // function SupportsNonNullableColumns: Boolean; override; -> Not implemented
105 // function SupportsMinimumSQLGrammar: Boolean; override; -> Not implemented
106 // function SupportsCoreSQLGrammar: Boolean; override; -> Not implemented
107 // function SupportsExtendedSQLGrammar: Boolean; override; -> Not implemented
108 // function SupportsANSI92EntryLevelSQL: Boolean; override; -> Not implemented
109 // function SupportsANSI92IntermediateSQL: Boolean; override; -> Not implemented
110 // function SupportsANSI92FullSQL: Boolean; override; -> Not implemented
111 function SupportsIntegrityEnhancementFacility: Boolean; override;
112 // function SupportsOuterJoins: Boolean; override; -> Not implemented
113 // function SupportsFullOuterJoins: Boolean; override; -> Not implemented
114 // function SupportsLimitedOuterJoins: Boolean; override; -> Not implemented
115 // function SupportsSchemasInDataManipulation: Boolean; override; -> Not implemented
116 // function SupportsSchemasInProcedureCalls: Boolean; override; -> Not implemented
117 // function SupportsSchemasInTableDefinitions: Boolean; override; -> Not implemented
118 // function SupportsSchemasInIndexDefinitions: Boolean; override; -> Not implemented
119 // function SupportsSchemasInPrivilegeDefinitions: Boolean; override; -> Not implemented
120 function SupportsCatalogsInDataManipulation: Boolean; override;
121 // function SupportsCatalogsInProcedureCalls: Boolean; override; -> Not implemented
122 function SupportsCatalogsInTableDefinitions: Boolean; override;
123 // function SupportsCatalogsInIndexDefinitions: Boolean; override; -> Not implemented
124 // function SupportsCatalogsInPrivilegeDefinitions: Boolean; override; -> Not implemented
125 // function SupportsPositionedDelete: Boolean; override; -> Not implemented
126 // function SupportsPositionedUpdate: Boolean; override; -> Not implemented
127 // function SupportsSelectForUpdate: Boolean; override; -> Not implemented
128 // function SupportsStoredProcedures: Boolean; override; -> Not implemented
129 function SupportsSubqueriesInComparisons: Boolean; override;
130 // function SupportsSubqueriesInExists: Boolean; override; -> Not implemented
131 // function SupportsSubqueriesInIns: Boolean; override; -> Not implemented
132 // function SupportsSubqueriesInQuantifieds: Boolean; override; -> Not implemented
133 // function SupportsCorrelatedSubqueries: Boolean; override; -> Not implemented
134 // function SupportsUnion: Boolean; override; -> Not implemented
135 function SupportsUnionAll: Boolean; override;
136 // function SupportsOpenCursorsAcrossCommit: Boolean; override; -> Not implemented
137 // function SupportsOpenCursorsAcrossRollback: Boolean; override; -> Not implemented
138 function SupportsOpenStatementsAcrossCommit: Boolean; override;
139 function SupportsOpenStatementsAcrossRollback: Boolean; override;
140 // function SupportsTransactions: Boolean; override; -> Not implemented
141 // function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
142 // Boolean; override; -> Not implemented
143 function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
144 function SupportsDataManipulationTransactionsOnly: Boolean; override;
145 // function SupportsResultSetType(_Type: TZResultSetType): Boolean; override; -> Not implemented
146 // function SupportsResultSetConcurrency(_Type: TZResultSetType;
147 // Concurrency: TZResultSetConcurrency): Boolean; override; -> Not implemented
148 // function SupportsBatchUpdates: Boolean; override; -> Not implemented
151 function GetMaxBinaryLiteralLength: Integer; override;
152 function GetMaxCharLiteralLength: Integer; override;
153 function GetMaxColumnNameLength: Integer; override;
154 function GetMaxColumnsInGroupBy: Integer; override;
155 function GetMaxColumnsInIndex: Integer; override;
156 function GetMaxColumnsInOrderBy: Integer; override;
157 function GetMaxColumnsInSelect: Integer; override;
158 function GetMaxColumnsInTable: Integer; override;
159 function GetMaxConnections: Integer; override;
160 function GetMaxCursorNameLength: Integer; override;
161 function GetMaxIndexLength: Integer; override;
162 // function GetMaxSchemaNameLength: Integer; override; -> Not implemented
163 // function GetMaxProcedureNameLength: Integer; override; -> Not implemented
164 function GetMaxCatalogNameLength: Integer; override;
165 function GetMaxRowSize: Integer; override;
166 function GetMaxStatementLength: Integer; override;
167 function GetMaxStatements: Integer; override;
168 function GetMaxTableNameLength: Integer; override;
169 function GetMaxTablesInSelect: Integer; override;
170 function GetMaxUserNameLength: Integer; override;
172 // policies (how are various data and operations handled):
173 // function IsReadOnly: Boolean; override; -> Not implemented
174 // function IsCatalogAtStart: Boolean; override; -> Not implemented
175 function DoesMaxRowSizeIncludeBlobs: Boolean; override;
176 // function NullsAreSortedHigh: Boolean; override; -> Not implemented
177 // function NullsAreSortedLow: Boolean; override; -> Not implemented
178 // function NullsAreSortedAtStart: Boolean; override; -> Not implemented
179 // function NullsAreSortedAtEnd: Boolean; override; -> Not implemented
180 // function NullPlusNonNullIsNull: Boolean; override; -> Not implemented
181 // function UsesLocalFiles: Boolean; override; -> Not implemented
182 function UsesLocalFilePerTable: Boolean; override;
183 // function StoresUpperCaseIdentifiers: Boolean; override; -> Not implemented
184 // function StoresLowerCaseIdentifiers: Boolean; override; -> Not implemented
185 function StoresMixedCaseIdentifiers: Boolean; override;
186 // function StoresUpperCaseQuotedIdentifiers: Boolean; override; -> Not implemented
187 // function StoresLowerCaseQuotedIdentifiers: Boolean; override; -> Not implemented
188 // function StoresMixedCaseQuotedIdentifiers: Boolean; override; -> Not implemented
189 function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
190 // function DataDefinitionCausesTransactionCommit: Boolean; override; -> Not implemented
191 // function DataDefinitionIgnoredInTransactions: Boolean; override; -> Not implemented
193 // interface details (terms, keywords, etc):
194 function GetSchemaTerm: string; override;
195 function GetProcedureTerm: string; override;
196 function GetCatalogTerm: string; override;
197 // function GetCatalogSeparator: string; override; -> Not implemented
198 function GetSQLKeywords: string; override;
199 function GetNumericFunctions: string; override;
200 function GetStringFunctions: string; override;
201 function GetSystemFunctions: string; override;
202 function GetTimeDateFunctions: string; override;
203 function GetSearchStringEscape: string; override;
204 function GetExtraNameCharacters: string; override;
207 {** Implements MySQL Database Metadata. }
208 TZMySQLDatabaseMetadata = class(TZAbstractDatabaseMetadata)
210 function CreateDatabaseInfo: IZDatabaseInfo; override; // technobot 2008-06-26
212 procedure GetCatalogAndNamePattern(const Catalog, SchemaPattern,
213 NamePattern: string; out OutCatalog, OutNamePattern: string);
214 function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
215 const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
216 // function UncachedGetSchemas: IZResultSet; override; -> Not implemented
217 function UncachedGetCatalogs: IZResultSet; override;
218 function UncachedGetTableTypes: IZResultSet; override;
219 function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
220 const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
221 function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
222 const TableNamePattern: string): IZResultSet; override;
223 function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
224 const Table: string; const ColumnNamePattern: string): IZResultSet; override;
225 function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
226 const Table: string): IZResultSet; override;
227 function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
228 const Table: string): IZResultSet; override;
229 function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
230 const Table: string): IZResultSet; override;
231 function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
232 const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
233 const ForeignTable: string): IZResultSet; override;
234 function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
235 Unique: Boolean; Approximate: Boolean): IZResultSet; override;
236 // function UncachedGetSequences(const Catalog: string; const SchemaPattern: string;
237 // const SequenceNamePattern: string): IZResultSet; override; -> Not implemented
238 function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
239 const ProcedureNamePattern: string): IZResultSet; override;
240 function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
241 const ProcedureNamePattern: string; const ColumnNamePattern: string):
242 IZResultSet; override;
243 function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
244 const Table: string): IZResultSet; override;
245 function UncachedGetTypeInfo: IZResultSet; override;
246 // function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
247 // const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
248 function UncachedGetCollationAndCharSet(const Catalog, SchemaPattern,
249 TableNamePattern, ColumnNamePattern: string): IZResultSet; override; //EgonHugeist
250 function UncachedGetCharacterSets: IZResultSet; override; //EgonHugeist
252 destructor Destroy; override;
258 Math, ZMessages, ZDbcUtils, ZCollections, ZDbcMySqlUtils;
260 { TZMySQLDatabaseInfo }
263 Constructs this object.
264 @param Metadata the interface of the correpsonding database metadata object
266 constructor TZMySQLDatabaseInfo.Create(const Metadata: TZAbstractDatabaseMetadata);
268 inherited Create(MetaData, '`');
271 //----------------------------------------------------------------------
272 // First, a variety of minor information about the target database.
275 What's the name of this database product?
276 @return database product name
278 function TZMySQLDatabaseInfo.GetDatabaseProductName: string;
284 What's the version of this database product?
285 @return database version
287 function TZMySQLDatabaseInfo.GetDatabaseProductVersion: string;
293 What's the name of this JDBC driver?
294 @return JDBC driver name
296 function TZMySQLDatabaseInfo.GetDriverName: string;
298 Result := 'Zeos Database Connectivity Driver for MySQL';
302 What's this JDBC driver's major version number?
303 @return JDBC driver major version
305 function TZMySQLDatabaseInfo.GetDriverMajorVersion: Integer;
311 What's this JDBC driver's minor version number?
312 @return JDBC driver minor version number
314 function TZMySQLDatabaseInfo.GetDriverMinorVersion: Integer;
320 Does the database use a file for each table?
321 @return true if the database uses a local file for each table
323 function TZMySQLDatabaseInfo.UsesLocalFilePerTable: Boolean;
329 Does the database treat mixed case unquoted SQL identifiers as
330 case insensitive and store them in mixed case?
331 @return <code>true</code> if so; <code>false</code> otherwise
333 function TZMySQLDatabaseInfo.StoresMixedCaseIdentifiers: Boolean;
339 Gets a comma-separated list of all a database's SQL keywords
340 that are NOT also SQL92 keywords.
343 function TZMySQLDatabaseInfo.GetSQLKeywords: string;
345 Result := 'AUTO_INCREMENT,BINARY,BLOB,ENUM,INFILE,LOAD,MEDIUMINT,OPTION,'
346 + 'OUTFILE,REPLACE,SET,TEXT,UNSIGNED,ZEROFILL';
347 { mdaems : added all reserved words indicated by mysql documentation (up to mysql 5.1)}
348 Result := Result + 'ACCESSIBLE,ADD,ALL,ALTER,ANALYZE,AND,ASC,ASENSITIVE,'
349 + ' BEFORE,BETWEEN,BIGINT,BOTH,CALL,CASCADE,CASE,CHANGE,CHARACTER,CHECK,'
350 + 'COLLATE,COLUMN,CONDITION,CONSTRAINT,CONTINUE,CONVERT,CROSS,'
351 + 'CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_USER,CURSOR,'
352 + 'DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,'
353 + 'DEC,DECIMAL,DECLARE,DEFAULT,DELAYED,DESC,DESCRIBE,DETERMINISTIC,'
354 + 'DISTINCT,DISTINCTROW,DIV,DOUBLE,DUAL,EACH,ELSE,ELSEIF,ENCLOSED,'
355 + 'ESCAPED,EXISTS,EXIT,EXPLAIN,FALSE,FETCH,FLOAT,FLOAT4,FLOAT8,FOR,'
356 + 'FORCE,FOREIGN,FULLTEXT,GENERAL,GRANT,HIGH_PRIORITY,HOUR_MICROSECOND,'
357 + 'HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,IGNORE_SERVER_IDS,IN,INNER,INOUT,INSENSITIVE,INT,'
358 + 'INT1,INT2,INT3,INT4,INT8,INTERVAL,ITERATE,JOIN,KEYS,KILL,LEADING,'
359 + 'LEAVE,LEFT,LIKE,LIMIT,LINEAR,LINES,LOCALTIME,LOCALTIMESTAMP,LOCK,'
360 + 'LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_HEARTBEAT_PERIOD,MASTER_SSL_VERIFY_SERVER_CERT,'
361 + 'MATCH,MAXVALUE,MEDIUMBLOB,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,'
362 + 'MOD,MODIFIES,NATURAL,NOT,NO_WRITE_TO_BINLOG,NUMERIC,OPTIMIZE,'
363 + 'OPTIONALLY,OR,OUT,OUTER,PRECISION,PROCEDURE,PURGE,RANGE,READ,READS,'
364 + 'READ_ONLY,READ_WRITE,REAL,REFERENCES,REGEXP,RELEASE,RENAME,REPEAT,'
365 + 'REQUIRE,RESIGNAL SIGNAL,RESTRICT,RETURN,REVOKE,RIGHT,RLIKE,SCHEMA,SCHEMAS,'
366 + 'SECOND_MICROSECOND,SENSITIVE,SEPARATOR,SHOW,SLOW,SMALLINT,SPATIAL,'
367 + 'SPECIFIC,SQL,SQLEXCEPTION,SQLSTATE,SQLWARNING,SQL_BIG_RESULT,'
368 + 'SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STRAIGHT_JOIN,'
369 + 'TERMINATED,THEN,TINYBLOB,TINYINT,TINYTEXT,TO,TRAILING,TRIGGER,'
370 + 'TRUE,UNDO,UNION,UNIQUE,UNLOCK,USAGE,USE,USING,UTC_DATE,UTC_TIME,'
371 + 'UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VARYING,WHEN,WHILE,WITH,'
372 + 'WRITE,X509,XOR,YEAR_MONTH,ACCESSIBLE,LINEAR,'
373 + 'MASTER_SSL_VERIFY_SERVER_CERT,RANGE,READ_ONLY,READ_WRITE';
377 Gets a comma-separated list of math functions. These are the
378 X/Open CLI math function names used in the JDBC function escape
382 function TZMySQLDatabaseInfo.GetNumericFunctions: string;
384 Result := 'ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS,COT,DEGREES,EXP,'
385 + 'FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW,POWER,RADIANS,RAND,ROUND,SIN,SQRT,'
387 { mdaems : added all numeric functions indicated by mysql documentation (up to mysql 5.1)}
388 Result := Result + 'BIT_COUNT,CEIL,CRC32,LN,LOG2,SIGN,UUID';
392 Gets a comma-separated list of string functions. These are the
393 X/Open CLI string function names used in the JDBC function escape
397 function TZMySQLDatabaseInfo.GetStringFunctions: string;
399 Result := 'ASCII,CHAR,CHAR_LENGTH,CHARACTER_LENGTH,CONCAT,ELT,FIELD,'
400 + 'FIND_IN_SET,INSERT,INSTR,INTERVAL,LCASE,LEFT,LENGTH,LOCATE,LOWER,LTRIM,'
401 + 'MID,POSITION,OCTET_LENGTH,REPEAT,REPLACE,REVERSE,RIGHT,RTRIM,SPACE,'
402 + 'SOUNDEX,SUBSTRING,SUBSTRING_INDEX,TRIM,UCASE,UPPER';
403 { mdaems : added all string functions indicated by mysql documentation (up to mysql 5.1)}
404 Result := Result + 'AES_DECRYPT,AES_ENCRYPT,BIN,BIT_LENGTH,CHARSET,'
405 + 'COERCIBILITY,COLLATION,COMPRESS,CONCAT_WS,DECODE,DES_DECRYPT,DES_ENCRYPT,'
406 + 'ENCODE,ENCRYPT,EXPORT_SET,FORMAT,HEX,LOAD_FILE,LPAD,MAKE_SET,MD5,OCT,ORD,'
407 + 'QUOTE,RPAD,STRCMP,SHA,SHA1,SUBSTR,UNHEX,EXTRACTVALUE,UPDATEXML,'
408 + 'UNCOMPRESS,UNCOMPRESSED_LENGTH';
412 Gets a comma-separated list of system functions. These are the
413 X/Open CLI system function names used in the JDBC function escape
417 function TZMySQLDatabaseInfo.GetSystemFunctions: string;
419 Result := 'DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,'
420 + 'LAST_INSERT_ID,VERSION';
421 { mdaems : added all system functions indicated by mysql documentation (up to mysql 5.1)}
422 Result := Result + 'BENCHMARK,CONNECTION_ID,CURRENT_USER,DEFAULT,FOUND_ROWS,'
423 + 'GET_LOCK,INET_ATON,INET_NTOA,IS_FREE_LOCK,IS_USED_LOCK,MASTER_POS_WAIT,'
424 + 'NAME_CONST,OLD_PASSWORD,RELEASE_LOCK,ROW_COUNT,SCHEMA,SLEEP';
428 Gets a comma-separated list of time and date functions.
431 function TZMySQLDatabaseInfo.GetTimeDateFunctions: string;
433 Result := 'DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,MONTHNAME,'
434 + 'QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,PERIOD_DIFF,TO_DAYS,'
435 + 'FROM_DAYS,DATE_FORMAT,TIME_FORMAT,CURDATE,CURRENT_DATE,CURTIME,'
436 + 'CURRENT_TIME,NOW,SYSDATE,CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,'
437 + 'SEC_TO_TIME,TIME_TO_SEC';
438 { mdaems : added all time and date functions indicated by mysql documentation (up to mysql 5.1)}
439 Result := Result + 'ADDDATE,ADDTIME,CONVERT_TZ,CURRENT_TIMESTAMP,DATE_ADD,'
440 + 'DATE_SUB,DATE,DATEDIFF,DAYOFWEEK,GET_FORMAT,LAST_DAY,LOCALTIME,'
441 + 'LOCALTIMESTAMP,MAKEDATE,MAKETIME,MICROSECOND,STR_TO_DATE,SUBDATE,SUBTIME,'
442 + 'TIMEDIFF,TIMESTAMP,TIMESTAMPADD,TIMESTAMPDIFF,UTC_DATE,UTC_TIME,'
443 + 'UTC_TIMESTAMP,WEEKOFYEAR,YEARWEEK';
447 Gets the string that can be used to escape wildcard characters.
448 This is the string that can be used to escape '_' or '%' in
449 the string pattern style catalog search parameters.
451 <P>The '_' character represents any single character.
452 <P>The '%' character represents any sequence of zero or
455 @return the string used to escape wildcard characters
457 function TZMySQLDatabaseInfo.GetSearchStringEscape: string;
463 Gets all the "extra" characters that can be used in unquoted
464 identifier names (those beyond a-z, A-Z, 0-9 and _).
465 @return the string containing the extra characters
467 function TZMySQLDatabaseInfo.GetExtraNameCharacters: string;
472 //--------------------------------------------------------------------
473 // Functions describing which features are supported.
476 Can an "ORDER BY" clause use columns not in the SELECT statement?
477 @return <code>true</code> if so; <code>false</code> otherwise
479 function TZMySQLDatabaseInfo.SupportsOrderByUnrelated: Boolean;
481 MajorVersion: Integer;
482 MinorVersion: Integer;
484 GetVersion(MajorVersion, MinorVersion);
485 // changed from False by mdaems. After testing with lower versions, please correct.
486 Result := MajorVersion >= 5;
490 Can a "GROUP BY" clause use columns not in the SELECT?
491 @return <code>true</code> if so; <code>false</code> otherwise
493 function TZMySQLDatabaseInfo.SupportsGroupByUnrelated: Boolean;
499 Can a "GROUP BY" clause add columns not in the SELECT
500 provided it specifies all the columns in the SELECT?
501 @return <code>true</code> if so; <code>false</code> otherwise
503 function TZMySQLDatabaseInfo.SupportsGroupByBeyondSelect: Boolean;
509 Is the SQL Integrity Enhancement Facility supported?
510 @return <code>true</code> if so; <code>false</code> otherwise
512 function TZMySQLDatabaseInfo.SupportsIntegrityEnhancementFacility: Boolean;
518 What's the database vendor's preferred term for "schema"?
519 @return the vendor term
521 function TZMySQLDatabaseInfo.GetSchemaTerm: string;
527 What's the database vendor's preferred term for "procedure"?
528 @return the vendor term
530 function TZMySQLDatabaseInfo.GetProcedureTerm: string;
536 What's the database vendor's preferred term for "catalog"?
537 @return the vendor term
539 function TZMySQLDatabaseInfo.GetCatalogTerm: string;
541 Result := 'Database';
545 Can a catalog name be used in a data manipulation statement?
546 @return <code>true</code> if so; <code>false</code> otherwise
548 function TZMySQLDatabaseInfo.SupportsCatalogsInDataManipulation: Boolean;
550 MajorVersion: Integer;
551 MinorVersion: Integer;
553 GetVersion(MajorVersion, MinorVersion);
554 Result := ((MajorVersion = 3) and (MinorVersion >= 22)) or (MajorVersion > 3);
558 Can a catalog name be used in a table definition statement?
559 @return <code>true</code> if so; <code>false</code> otherwise
561 function TZMySQLDatabaseInfo.SupportsCatalogsInTableDefinitions: Boolean;
567 Are subqueries in comparison expressions supported?
568 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
569 @return <code>true</code> if so; <code>false</code> otherwise
571 function TZMySQLDatabaseInfo.SupportsSubqueriesInComparisons: Boolean;
577 Is SQL UNION ALL supported?
578 @return <code>true</code> if so; <code>false</code> otherwise
580 function TZMySQLDatabaseInfo.SupportsUnionAll: Boolean;
582 MajorVersion: Integer;
583 MinorVersion: Integer;
585 GetVersion(MajorVersion, MinorVersion);
586 Result := MajorVersion >= 4;
590 Can statements remain open across commits?
591 @return <code>true</code> if statements always remain open;
592 <code>false</code> if they might not remain open
594 function TZMySQLDatabaseInfo.SupportsOpenStatementsAcrossCommit: Boolean;
600 Can statements remain open across rollbacks?
601 @return <code>true</code> if statements always remain open;
602 <code>false</code> if they might not remain open
604 function TZMySQLDatabaseInfo.SupportsOpenStatementsAcrossRollback: Boolean;
609 //----------------------------------------------------------------------
610 // The following group of methods exposes various limitations
611 // based on the target database with the current driver.
612 // Unless otherwise specified, a result of zero means there is no
613 // limit, or the limit is not known.
616 How many hex characters can you have in an inline binary literal?
617 @return max binary literal length in hex characters;
618 a result of zero means that there is no limit or the limit is not known
620 function TZMySQLDatabaseInfo.GetMaxBinaryLiteralLength: Integer;
626 What's the max length for a character literal?
627 @return max literal length;
628 a result of zero means that there is no limit or the limit is not known
630 function TZMySQLDatabaseInfo.GetMaxCharLiteralLength: Integer;
636 What's the limit on column name length?
637 @return max column name length;
638 a result of zero means that there is no limit or the limit is not known
640 function TZMySQLDatabaseInfo.GetMaxColumnNameLength: Integer;
646 What's the maximum number of columns in a "GROUP BY" clause?
647 @return max number of columns;
648 a result of zero means that there is no limit or the limit is not known
650 function TZMySQLDatabaseInfo.GetMaxColumnsInGroupBy: Integer;
656 What's the maximum number of columns allowed in an index?
657 @return max number of columns;
658 a result of zero means that there is no limit or the limit is not known
660 function TZMySQLDatabaseInfo.GetMaxColumnsInIndex: Integer;
666 What's the maximum number of columns in an "ORDER BY" clause?
667 @return max number of columns;
668 a result of zero means that there is no limit or the limit is not known
670 function TZMySQLDatabaseInfo.GetMaxColumnsInOrderBy: Integer;
676 What's the maximum number of columns in a "SELECT" list?
677 @return max number of columns;
678 a result of zero means that there is no limit or the limit is not known
680 function TZMySQLDatabaseInfo.GetMaxColumnsInSelect: Integer;
686 What's the maximum number of columns in a table?
687 @return max number of columns;
688 a result of zero means that there is no limit or the limit is not known
690 function TZMySQLDatabaseInfo.GetMaxColumnsInTable: Integer;
696 How many active connections can we have at a time to this database?
697 @return max number of active connections;
698 a result of zero means that there is no limit or the limit is not known
700 function TZMySQLDatabaseInfo.GetMaxConnections: Integer;
706 What's the maximum cursor name length?
707 @return max cursor name length in bytes;
708 a result of zero means that there is no limit or the limit is not known
710 function TZMySQLDatabaseInfo.GetMaxCursorNameLength: Integer;
716 Retrieves the maximum number of bytes for an index, including all
717 of the parts of the index.
718 @return max index length in bytes, which includes the composite of all
719 the constituent parts of the index;
720 a result of zero means that there is no limit or the limit is not known
722 function TZMySQLDatabaseInfo.GetMaxIndexLength: Integer;
728 What's the maximum length of a catalog name?
729 @return max name length in bytes;
730 a result of zero means that there is no limit or the limit is not known
732 function TZMySQLDatabaseInfo.GetMaxCatalogNameLength: Integer;
738 What's the maximum length of a single row?
739 @return max row size in bytes;
740 a result of zero means that there is no limit or the limit is not known
742 function TZMySQLDatabaseInfo.GetMaxRowSize: Integer;
744 Result := 2147483639;
748 Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
750 @return <code>true</code> if so; <code>false</code> otherwise
752 function TZMySQLDatabaseInfo.DoesMaxRowSizeIncludeBlobs: Boolean;
758 What's the maximum length of an SQL statement?
759 @return max length in bytes;
760 a result of zero means that there is no limit or the limit is not known
762 function TZMySQLDatabaseInfo.GetMaxStatementLength: Integer;
768 How many active statements can we have open at one time to this
770 @return the maximum number of statements that can be open at one time;
771 a result of zero means that there is no limit or the limit is not known
773 function TZMySQLDatabaseInfo.GetMaxStatements: Integer;
779 What's the maximum length of a table name?
780 @return max name length in bytes;
781 a result of zero means that there is no limit or the limit is not known
783 function TZMySQLDatabaseInfo.GetMaxTableNameLength: Integer;
789 What's the maximum number of tables in a SELECT statement?
790 @return the maximum number of tables allowed in a SELECT statement;
791 a result of zero means that there is no limit or the limit is not known
793 function TZMySQLDatabaseInfo.GetMaxTablesInSelect: Integer;
799 What's the maximum length of a user name?
800 @return max user name length in bytes;
801 a result of zero means that there is no limit or the limit is not known
803 function TZMySQLDatabaseInfo.GetMaxUserNameLength: Integer;
808 //----------------------------------------------------------------------
811 What's the database's default transaction isolation level? The
812 values are defined in <code>java.sql.Connection</code>.
813 @return the default isolation level
816 function TZMySQLDatabaseInfo.GetDefaultTransactionIsolation:
817 TZTransactIsolationLevel;
823 Are both data definition and data manipulation statements
824 within a transaction supported?
825 @return <code>true</code> if so; <code>false</code> otherwise
827 function TZMySQLDatabaseInfo.
828 SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
834 Are only data manipulation statements within a transaction
836 @return <code>true</code> if so; <code>false</code> otherwise
838 function TZMySQLDatabaseInfo.SupportsDataManipulationTransactionsOnly: Boolean;
840 case Metadata.GetConnection.GetTransactionIsolation of
841 tiReadUncommitted: Result := True;
842 tiReadCommitted: Result := True;
843 tiRepeatableRead: Result := True;
844 tiSerializable: Result := True;
851 Gets the MySQL version info.
852 @param MajorVesion the major version of MySQL server.
853 @param MinorVersion the minor version of MySQL server.
855 procedure TZMySQLDatabaseInfo.GetVersion(var MajorVersion,
856 MinorVersion: Integer);
858 VersionList: TStrings;
859 Subversion : integer;
861 DecodeSqlVersioning(Metadata.GetConnection.GetHostVersion,
862 MajorVersion,MinorVersion, Subversion);
863 if (Majorversion < 4) or ((majorversion=4) and (Minorversion = 0)) then
864 with Metadata.GetConnection.CreateStatement.ExecuteQuery('SELECT VERSION()') do
866 VersionList := SplitString(String(GetString(1)), '.-');
868 if VersionList.Count >= 2 then
870 MajorVersion := StrToIntDef(VersionList.Strings[0], 0);
871 MinorVersion := StrToIntDef(VersionList.Strings[1], 0);
880 { TZMySQLDatabaseMetadata }
883 Destroys this object and cleanups the memory.
885 destructor TZMySQLDatabaseMetadata.Destroy;
891 Constructs a database information object and returns the interface to it. Used
892 internally by the constructor.
893 @return the database information object interface
895 function TZMySQLDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
897 Result := TZMySQLDatabaseInfo.Create(Self);
900 procedure TZMySQLDatabaseMetadata.GetCatalogAndNamePattern(const Catalog,
901 SchemaPattern, NamePattern: string; out OutCatalog, OutNamePattern: string);
905 if SchemaPattern <> '' then
906 OutCatalog := NormalizePatternCase(SchemaPattern)
908 OutCatalog := NormalizePatternCase(FDatabase);
911 OutCatalog := NormalizePatternCase(Catalog);
913 if NamePattern = '' then
914 OutNamePattern := '%'
916 OutNamePattern := NormalizePatternCase(NamePattern);
920 Gets a description of tables available in a catalog.
922 <P>Only table descriptions matching the catalog, schema, table
923 name and type criteria are returned. They are ordered by
924 TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
926 <P>Each table description has the following columns:
928 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
929 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
930 <LI><B>TABLE_NAME</B> String => table name
931 <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
932 "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
933 "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
934 <LI><B>REMARKS</B> String => explanatory comment on the table
937 <P><B>Note:</B> Some databases may not return information for
940 @param catalog a catalog name; "" retrieves those without a
941 catalog; null means drop catalog name from the selection criteria
942 @param schemaPattern a schema name pattern; "" retrieves those
944 @param tableNamePattern a table name pattern
945 @param types a list of table types to include; null returns all types
946 @return <code>ResultSet</code> - each row is a table description
947 @see #getSearchStringEscape
949 function TZMySQLDatabaseMetadata.UncachedGetTables(const Catalog: string;
950 const SchemaPattern: string; const TableNamePattern: string;
951 const Types: TStringDynArray): IZResultSet;
953 LCatalog, LTableNamePattern: string;
955 Result := inherited UncachedGetTables(Catalog, SchemaPattern, TableNamePattern, Types);
957 GetCatalogAndNamePattern(Catalog, SchemaPattern, TableNamePattern,
958 LCatalog, LTableNamePattern);
960 with GetConnection.CreateStatement.ExecuteQuery(
961 Format('SHOW TABLES FROM %s LIKE ''%s''',
962 [IC.Quote(LCatalog), LTableNamePattern])) do
966 Result.MoveToInsertRow;
967 Result.UpdateString(1, LCatalog);
968 Result.UpdateString(3, GetString(1));
969 Result.UpdateString(4, 'TABLE');
975 // If a table was specified but not found, check if it could be a temporary table
976 if not Result.First and (LTableNamePattern <> '%') then
979 EnterSilentMySQLError;
981 if GetConnection.CreateStatement.ExecuteQuery(
982 Format('SHOW COLUMNS FROM %s.%s',
984 IC.Quote(LTableNamePattern)])).Next then
986 Result.MoveToInsertRow;
987 Result.UpdateString(1, LCatalog);
988 Result.UpdateString(3, LTableNamePattern);
989 Result.UpdateString(4, 'TABLE');
993 LeaveSilentMySQLError;
996 on EZMySQLSilentException do ;
997 on EZSQLException do ;
1003 Gets the catalog names available in this database. The results
1004 are ordered by catalog name.
1006 <P>The catalog column is:
1008 <LI><B>TABLE_CAT</B> String => catalog name
1011 @return <code>ResultSet</code> - each row has a single String column that is a
1014 function TZMySQLDatabaseMetadata.UncachedGetCatalogs: IZResultSet;
1016 Result:=inherited UncachedGetCatalogs;
1018 with GetConnection.CreateStatement.ExecuteQuery('SHOW DATABASES') do
1022 Result.MoveToInsertRow;
1023 Result.UpdateString(1, GetString(1));
1031 Gets the table types available in this database. The results
1032 are ordered by table type.
1034 <P>The table type is:
1036 <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1037 "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1038 "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1041 @return <code>ResultSet</code> - each row has a single String column that is a
1044 function TZMySQLDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
1046 Result:=inherited UncachedGetTableTypes;
1048 Result.MoveToInsertRow;
1049 Result.UpdateString(1, 'TABLE');
1054 Gets a description of table columns available in
1055 the specified catalog.
1057 <P>Only column descriptions matching the catalog, schema, table
1058 and column name criteria are returned. They are ordered by
1059 TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1061 <P>Each column description has the following columns:
1063 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1064 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1065 <LI><B>TABLE_NAME</B> String => table name
1066 <LI><B>COLUMN_NAME</B> String => column name
1067 <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
1068 <LI><B>TYPE_NAME</B> String => Data source dependent type name,
1069 for a UDT the type name is fully qualified
1070 <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1071 types this is the maximum number of characters, for numeric or
1072 decimal types this is precision.
1073 <LI><B>BUFFER_LENGTH</B> is not used.
1074 <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1075 <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1076 <LI><B>NULLABLE</B> int => is NULL allowed?
1078 <LI> columnNoNulls - might not allow NULL values
1079 <LI> columnNullable - definitely allows NULL values
1080 <LI> columnNullableUnknown - nullability unknown
1082 <LI><B>REMARKS</B> String => comment describing column (may be null)
1083 <LI><B>COLUMN_DEF</B> String => default value (may be null)
1084 <LI><B>SQL_DATA_TYPE</B> int => unused
1085 <LI><B>SQL_DATETIME_SUB</B> int => unused
1086 <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1087 maximum number of bytes in the column
1088 <LI><B>ORDINAL_POSITION</B> int => index of column in table
1090 <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1091 does not allow NULL values; "YES" means the column might
1092 allow NULL values. An empty string means nobody knows.
1095 @param catalog a catalog name; "" retrieves those without a
1096 catalog; null means drop catalog name from the selection criteria
1097 @param schemaPattern a schema name pattern; "" retrieves those
1099 @param tableNamePattern a table name pattern
1100 @param columnNamePattern a column name pattern
1101 @return <code>ResultSet</code> - each row is a column description
1102 @see #getSearchStringEscape
1104 function TZMySQLDatabaseMetadata.UncachedGetColumns(const Catalog: string;
1105 const SchemaPattern: string; const TableNamePattern: string;
1106 const ColumnNamePattern: string): IZResultSet;
1109 MySQLType: TZSQLType;
1110 TempCatalog, TempColumnNamePattern, TempTableNamePattern: string;
1112 TypeName, TypeInfoSecond: String;
1113 Nullable, DefaultValue: String;
1114 HasDefaultValue: Boolean;
1115 ColumnSize, ColumnDecimals: Integer;
1116 OrdPosition: Integer;
1118 TableNameList: TStrings;
1119 TableNameLength: Integer;
1120 ColumnIndexes : Array[1..6] of integer;
1124 Res:=inherited UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
1126 GetCatalogAndNamePattern(Catalog, SchemaPattern, ColumnNamePattern,
1127 TempCatalog, TempColumnNamePattern);
1129 TableNameLength := 0;
1130 TableNameList := TStringList.Create;
1132 with GetTables(Catalog, SchemaPattern, TableNamePattern, nil) do
1136 TableNameList.Add(GetString(3)); //TABLE_NAME
1137 TableNameLength := Max(TableNameLength, Length(TableNameList[TableNameList.Count - 1]));
1142 for I := 0 to TableNameList.Count - 1 do
1145 TempTableNamePattern := TableNameList.Strings[I];
1147 with GetConnection.CreateStatement.ExecuteQuery(
1148 Format('SHOW FULL COLUMNS FROM %s.%s LIKE ''%s''',
1149 [IC.Quote(TempCatalog),
1150 IC.Quote(TempTableNamePattern),
1151 TempColumnNamePattern])) do
1153 ColumnIndexes[1] := FindColumn('Field');
1154 ColumnIndexes[2] := FindColumn('Type');
1155 ColumnIndexes[3] := FindColumn('Null');
1156 ColumnIndexes[4] := FindColumn('Extra');
1157 ColumnIndexes[5] := FindColumn('Default');
1158 ColumnIndexes[6] := FindColumn('Collation');
1161 {initialise some variables}
1162 Res.MoveToInsertRow;
1163 Res.UpdateString(1, TempCatalog);
1164 Res.UpdateString(2, '');
1165 Res.UpdateString(3, TempTableNamePattern) ;
1166 Res.UpdateString(4, GetString(ColumnIndexes[1]));
1168 ConvertMySQLColumnInfoFromString(GetString(ColumnIndexes[2]),
1169 ConSettings, TypeName,
1170 TypeInfoSecond, MySQLType, ColumnSize, ColumnDecimals);
1171 Res.UpdateInt(5, Ord(MySQLType));
1172 Res.UpdateString(6, TypeName);
1173 Res.UpdateInt(7, ColumnSize);
1174 Res.UpdateInt(8, MAXBUF);
1175 Res.UpdateInt(9, ColumnDecimals);
1178 { Sets nullable fields. }
1179 Nullable := GetString(ColumnIndexes[3]);
1180 if Nullable <> '' then
1181 if Nullable = 'YES' then
1183 Res.UpdateInt(11, Ord(ntNullable));
1184 Res.UpdateString(18, 'YES');
1188 Res.UpdateInt(11, Ord(ntNoNulls));
1189 Res.UpdateString(18, 'NO');
1193 Res.UpdateInt(11, 0);
1194 Res.UpdateString(18, 'NO');
1196 Res.UpdateString(12, GetString(ColumnIndexes[4]));
1197 // MySQL is a bit bizarre.
1198 if IsNull(ColumnIndexes[5]) then
1200 // MySQL bizarity 1:
1201 // NULL actually means that the default is NULL.
1202 // Superfluous, since there's a NULL / NOT NULL flag to control whether the field may have no value.
1203 // So we just ignore this, the field gets set to NULL if nothing was specified...
1204 HasDefaultValue := false;
1209 DefaultValue := GetString(ColumnIndexes[5]);
1210 if not (DefaultValue = '') then
1211 HasDefaultValue := true
1214 // MySQL bizarity 2:
1215 // For CHAR, BLOB, TEXT and SET types, '' either means: default value is '' or: no default value
1216 // There's absolutely no way of telling when using SHOW COLUMNS FROM,
1217 // the correct information can /only/ be discerned by using information_schema.
1218 // TODO: For now, just use '' as default value for these types, but this should really be fixed to use information_schema.
1219 // For ENUM types, '' means: default value is first value in enum set
1220 // For other types, '' means: no default value
1221 HasDefaultValue := false;
1222 if Pos('blob', TypeName) > 0 then HasDefaultValue := true;
1223 if Pos('text', TypeName) > 0 then HasDefaultValue := true;
1224 if Pos('char', TypeName) > 0 then HasDefaultValue := true;
1225 if 'set' = TypeName then HasDefaultValue := true;
1226 if 'enum' = TypeName then
1228 HasDefaultValue := true;
1229 DefaultValue := Copy(TypeInfoSecond, 2,length(TypeInfoSecond)-1);
1230 DefaultValue := Copy(DefaultValue, 1, Pos('''', DefaultValue) - 1);
1234 if HasDefaultValue then
1236 // String values in the 'Default value' field are not escaped with apostrophes.
1237 // Guess this makes it impossible to specify a function call or similar via default values.
1238 if (MySQLType in [stString, stUnicodeString, stBinaryStream, stAsciiStream]) then
1240 // Since we changed date/time-related columntypes to be presented
1241 // as strings, we need to move the CURRENT_TIMESTAMP-check to here.
1242 // Also left the other line in order to minimize the changes in ZeosLib
1243 if DefaultValue <> 'CURRENT_TIMESTAMP' then
1244 DefaultValue := '''' + DefaultValue + ''''
1246 else if (MySQLType in [stDate, stTime, stTimestamp]) then
1248 if DefaultValue <> 'CURRENT_TIMESTAMP' then
1249 DefaultValue := '''' + DefaultValue + ''''
1251 else if (MySQLType = stBoolean) and (TypeName = 'enum') then
1253 if (DefaultValue = 'y') or (DefaultValue = 'Y') then
1256 DefaultValue := '0';
1259 Res.UpdateString(13, DefaultValue);
1262 Res.UpdateInt(17, OrdPosition);
1264 Res.UpdateBoolean(19, //AUTO_INCREMENT
1265 Trim(LowerCase(GetString(ColumnIndexes[4]))) = 'auto_increment'); //Extra
1266 Res.UpdateBoolean(20, //CASE_SENSITIVE
1267 IC.IsCaseSensitive(GetString(ColumnIndexes[1]))); //Field
1268 Res.UpdateBoolean(21, True); //SEARCHABLE
1269 Res.UpdateBoolean(22, True); //WRITABLE
1270 Res.UpdateBoolean(23, True); //DEFINITELYWRITABLE
1271 Res.UpdateBoolean(24, False); //READONLY
1286 Gets a description of the access rights for a table's columns.
1288 <P>Only privileges matching the column name criteria are
1289 returned. They are ordered by COLUMN_NAME and PRIVILEGE.
1291 <P>Each privilige description has the following columns:
1293 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1294 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1295 <LI><B>TABLE_NAME</B> String => table name
1296 <LI><B>COLUMN_NAME</B> String => column name
1297 <LI><B>GRANTOR</B> => grantor of access (may be null)
1298 <LI><B>GRANTEE</B> String => grantee of access
1299 <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1300 INSERT, UPDATE, REFRENCES, ...)
1301 <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1302 to grant to others; "NO" if not; null if unknown
1305 @param catalog a catalog name; "" retrieves those without a
1306 catalog; null means drop catalog name from the selection criteria
1307 @param schema a schema name; "" retrieves those without a schema
1308 @param table a table name
1309 @param columnNamePattern a column name pattern
1310 @return <code>ResultSet</code> - each row is a column privilege description
1311 @see #getSearchStringEscape
1313 function TZMySQLDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
1314 const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
1317 Host, Database, Grantor, User, FullUser: String;
1318 AllPrivileges, ColumnName, Privilege: String;
1319 PrivilegesList: TStrings;
1320 ColumnNameCondition, TableNameCondition, SchemaCondition: string;
1322 Result:=inherited UncachedGetColumnPrivileges(Catalog, Schema, Table, ColumnNamePattern);
1324 If Catalog = '' then
1325 If Schema <> '' then
1326 SchemaCondition := ConstructNameCondition(Schema,'c.db')
1328 SchemaCondition := ConstructNameCondition(FDatabase,'c.db')
1330 SchemaCondition := ConstructNameCondition(Catalog,'c.db');
1331 TableNameCondition := ConstructNameCondition(Table,'c.table_name');
1332 ColumnNameCondition := ConstructNameCondition(ColumnNamePattern,'c.column_name');
1333 If SchemaCondition <> '' then
1334 SchemaCondition := ' and ' + SchemaCondition;
1335 If TableNameCondition <> '' then
1336 TableNameCondition := ' and ' + TableNameCondition;
1337 If ColumnNameCondition <> '' then
1338 ColumnNameCondition := ' and ' + ColumnNameCondition;
1340 PrivilegesList := TStringList.Create;
1342 with GetConnection.CreateStatement.ExecuteQuery(
1343 'SELECT c.host, c.db, t.grantor, c.user, c.table_name,'
1344 + ' c.column_name, c.column_priv FROM mysql.columns_priv c,'
1345 + ' mysql.tables_priv t WHERE c.host=t.host AND c.db=t.db'
1346 + ' AND c.table_name=t.table_name'
1347 + SchemaCondition + TableNameCondition + ColumnNameCondition
1352 Host := GetString(1);
1353 Database := GetString(2);
1354 Grantor := GetString(4);
1355 User := GetString(5);
1359 FullUser := User + '@' + Host;
1360 ColumnName := GetString(6);
1362 AllPrivileges := GetString(7);
1363 PutSplitString(PrivilegesList, AllPrivileges, ',');
1365 for I := 0 to PrivilegesList.Count - 1 do
1367 Result.MoveToInsertRow;
1368 Privilege := Trim(PrivilegesList.Strings[I]);
1369 Result.UpdateString(1, Database);
1370 Result.UpdateNull(2);
1371 Result.UpdateString(3, Table);
1372 Result.UpdateString(4, ColumnName);
1373 Result.UpdateString(5, Grantor);
1374 Result.UpdateString(6, FullUser);
1375 Result.UpdateString(7, Privilege);
1376 Result.UpdateNull(8);
1383 PrivilegesList.Free;
1388 Gets a description of the access rights for each table available
1389 in a catalog. Note that a table privilege applies to one or
1390 more columns in the table. It would be wrong to assume that
1391 this priviledge applies to all columns (this may be true for
1392 some systems but is not true for all.)
1394 <P>Only privileges matching the schema and table name
1395 criteria are returned. They are ordered by TABLE_SCHEM,
1396 TABLE_NAME, and PRIVILEGE.
1398 <P>Each privilige description has the following columns:
1400 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1401 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1402 <LI><B>TABLE_NAME</B> String => table name
1403 <LI><B>GRANTOR</B> => grantor of access (may be null)
1404 <LI><B>GRANTEE</B> String => grantee of access
1405 <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1406 INSERT, UPDATE, REFRENCES, ...)
1407 <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1408 to grant to others; "NO" if not; null if unknown
1411 @param catalog a catalog name; "" retrieves those without a
1412 catalog; null means drop catalog name from the selection criteria
1413 @param schemaPattern a schema name pattern; "" retrieves those
1415 @param tableNamePattern a table name pattern
1416 @return <code>ResultSet</code> - each row is a table privilege description
1417 @see #getSearchStringEscape
1419 function TZMySQLDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
1420 const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
1423 Host, Database, Table, Grantor, User, FullUser: String;
1424 AllPrivileges, Privilege: String;
1425 PrivilegesList: TStrings;
1426 TableNameCondition, SchemaCondition: string;
1428 Result:=inherited UncachedGetTablePrivileges(Catalog, SchemaPattern, TableNamePattern);
1430 If Catalog = '' then
1431 If SchemaPattern <> '' then
1432 SchemaCondition := ConstructNameCondition(SchemaPattern,'db')
1434 SchemaCondition := ConstructNameCondition(FDatabase,'db')
1436 SchemaCondition := ConstructNameCondition(Catalog,'db');
1437 TableNameCondition := ConstructNameCondition(TableNamePattern,'table_name');
1438 If SchemaCondition <> '' then
1439 SchemaCondition := ' and ' + SchemaCondition;
1440 If TableNameCondition <> '' then
1441 TableNameCondition := ' and ' + TableNameCondition;
1443 PrivilegesList := TStringList.Create;
1445 with GetConnection.CreateStatement.ExecuteQuery(
1446 'SELECT host,db,table_name,grantor,user,table_priv'
1447 + ' from mysql.tables_priv WHERE 1=1'
1448 + SchemaCondition + TableNameCondition
1453 Host := GetString(1);
1454 Database := GetString(2);
1455 Table := GetString(3);
1456 Grantor := GetString(4);
1457 User := GetString(5);
1461 FullUser := User + '@' + Host;
1463 AllPrivileges := GetString(6);
1464 PutSplitString(PrivilegesList, AllPrivileges, ',');
1466 for I := 0 to PrivilegesList.Count - 1 do
1468 Result.MoveToInsertRow;
1469 Privilege := Trim(PrivilegesList.Strings[I]);
1470 Result.UpdateString(1, Database);
1471 Result.UpdateNull(2);
1472 Result.UpdateString(3, Table);
1473 Result.UpdateString(4, Grantor);
1474 Result.UpdateString(5, FullUser);
1475 Result.UpdateString(6, Privilege);
1476 Result.UpdateNull(7);
1483 PrivilegesList.Free;
1488 Gets a description of a table's primary key columns. They
1489 are ordered by COLUMN_NAME.
1491 <P>Each primary key column description has the following columns:
1493 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1494 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1495 <LI><B>TABLE_NAME</B> String => table name
1496 <LI><B>COLUMN_NAME</B> String => column name
1497 <LI><B>KEY_SEQ</B> short => sequence number within primary key
1498 <LI><B>PK_NAME</B> String => primary key name (may be null)
1501 @param catalog a catalog name; "" retrieves those without a
1502 catalog; null means drop catalog name from the selection criteria
1503 @param schema a schema name; "" retrieves those
1505 @param table a table name
1506 @return <code>ResultSet</code> - each row is a primary key column description
1507 @exception SQLException if a database access error occurs
1509 function TZMySQLDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
1510 const Schema: string; const Table: string): IZResultSet;
1513 LCatalog, LTable: string;
1514 ColumnIndexes : Array[1..3] of integer;
1517 raise Exception.Create(STableIsNotSpecified); //CHANGE IT!
1519 Result:=inherited UncachedGetPrimaryKeys(Catalog, Schema, Table);
1521 GetCatalogAndNamePattern(Catalog, Schema, Table,
1524 with GetConnection.CreateStatement.ExecuteQuery(
1525 Format('SHOW KEYS FROM %s.%s',
1526 [IC.Quote(LCatalog),
1527 IC.Quote(LTable)])) do
1529 ColumnIndexes[1] := FindColumn('Key_name');
1530 ColumnIndexes[2] := FindColumn('Column_name');
1531 ColumnIndexes[3] := FindColumn('Seq_in_index');
1534 KeyType := UpperCase(String(GetString(ColumnIndexes[1])));
1535 KeyType := Copy(KeyType, 1, 3);
1536 if KeyType = 'PRI' then
1538 Result.MoveToInsertRow;
1539 Result.UpdateString(1, LCatalog);
1540 Result.UpdateString(2, '');
1541 Result.UpdateString(3, Table);
1542 Result.UpdateString(4, GetString(ColumnIndexes[2]));
1543 Result.UpdateString(5, GetString(ColumnIndexes[3]));
1544 Result.UpdateNull(6);
1553 Gets a description of the primary key columns that are
1554 referenced by a table's foreign key columns (the primary keys
1555 imported by a table). They are ordered by PKTABLE_CAT,
1556 PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
1558 <P>Each primary key column description has the following columns:
1560 <LI><B>PKTABLE_CAT</B> String => primary key table catalog
1561 being imported (may be null)
1562 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
1563 being imported (may be null)
1564 <LI><B>PKTABLE_NAME</B> String => primary key table name
1566 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
1568 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
1569 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
1570 <LI><B>FKTABLE_NAME</B> String => foreign key table name
1571 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
1572 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
1573 <LI><B>UPDATE_RULE</B> short => What happens to
1574 foreign key when primary is updated:
1576 <LI> importedNoAction - do not allow update of primary
1577 key if it has been imported
1578 <LI> importedKeyCascade - change imported key to agree
1579 with primary key update
1580 <LI> importedKeySetNull - change imported key to NULL if
1581 its primary key has been updated
1582 <LI> importedKeySetDefault - change imported key to default values
1583 if its primary key has been updated
1584 <LI> importedKeyRestrict - same as importedKeyNoAction
1585 (for ODBC 2.x compatibility)
1587 <LI><B>DELETE_RULE</B> short => What happens to
1588 the foreign key when primary is deleted.
1590 <LI> importedKeyNoAction - do not allow delete of primary
1591 key if it has been imported
1592 <LI> importedKeyCascade - delete rows that import a deleted key
1593 <LI> importedKeySetNull - change imported key to NULL if
1594 its primary key has been deleted
1595 <LI> importedKeyRestrict - same as importedKeyNoAction
1596 (for ODBC 2.x compatibility)
1597 <LI> importedKeySetDefault - change imported key to default if
1598 its primary key has been deleted
1600 <LI><B>FK_NAME</B> String => foreign key name (may be null)
1601 <LI><B>PK_NAME</B> String => primary key name (may be null)
1602 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
1603 constraints be deferred until commit
1605 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
1606 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
1607 <LI> importedKeyNotDeferrable - see SQL92 for definition
1611 @param catalog a catalog name; "" retrieves those without a
1612 catalog; null means drop catalog name from the selection criteria
1613 @param schema a schema name; "" retrieves those
1615 @param table a table name
1616 @return <code>ResultSet</code> - each row is a primary key column description
1617 @see #getExportedKeys
1619 function TZMySQLDatabaseMetadata.UncachedGetImportedKeys(const Catalog: string;
1620 const Schema: string; const Table: string): IZResultSet;
1624 LCatalog, LTable: string;
1625 TableType, Comment, Keys: String;
1626 CommentList, KeyList: TStrings;
1627 ColumnIndexes : Array[1..2] of integer;
1630 raise Exception.Create(STableIsNotSpecified); //CHANGE IT!
1632 Result := inherited UncachedGetImportedKeys(Catalog, Schema, Table);
1634 GetCatalogAndNamePattern(Catalog, Schema, Table,
1637 KeyList := TStringList.Create;
1638 CommentList := TStringList.Create;
1640 with GetConnection.CreateStatement.ExecuteQuery(
1641 Format('SHOW TABLE STATUS FROM %s LIKE ''%s''',
1642 [IC.Quote(LCatalog), LTable])) do
1644 ColumnIndexes[1] := FindColumn('Type');
1645 ColumnIndexes[2] := FindColumn('Comment');
1648 TableType := GetString(ColumnIndexes[1]);
1649 if (TableType <> '') and (LowerCase(TableType) = 'innodb') then
1651 Comment := GetString(ColumnIndexes[2]);
1652 if Comment <> '' then
1654 PutSplitString(CommentList, Comment, ';');
1657 if CommentList.Count > 4 then
1659 for I := 0 to CommentList.Count - 1 do
1661 Keys := CommentList.Strings[1];
1662 Result.MoveToInsertRow;
1663 PutSplitString(KeyList, Keys, '() /');
1665 Result.UpdateString(1, KeyList.Strings[2]); // PKTABLE_CAT
1666 Result.UpdateNull(2); // PKTABLE_SCHEM
1667 Result.UpdateString(3, KeyList.Strings[3]); // PKTABLE_NAME
1668 Result.UpdateString(4, KeyList.Strings[4]); // PKCOLUMN_NAME
1669 Result.UpdateString(5, LCatalog);
1670 Result.UpdateNull(6);// FKTABLE_SCHEM
1671 Result.UpdateString(7, Table); // FKTABLE_NAME
1672 Result.UpdateString(8, KeyList.Strings[0]); // FKCOLUMN_NAME
1674 Result.UpdateInt(9, KeySeq); // KEY_SEQ
1675 Result.UpdateInt(10, Ord(ikSetDefault)); // UPDATE_RULE
1676 Result.UpdateInt(11, Ord(ikSetDefault)); // DELETE_RULE
1677 Result.UpdateNull(12); // FK_NAME
1678 Result.UpdateNull(13); // PK_NAME
1679 Result.UpdateInt(14, Ord(ikSetDefault)); // DEFERRABILITY
1696 Gets a description of the foreign key columns that reference a
1697 table's primary key columns (the foreign keys exported by a
1698 table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
1699 FKTABLE_NAME, and KEY_SEQ.
1701 <P>Each foreign key column description has the following columns:
1703 <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
1704 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
1705 <LI><B>PKTABLE_NAME</B> String => primary key table name
1706 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
1707 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
1708 being exported (may be null)
1709 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
1710 being exported (may be null)
1711 <LI><B>FKTABLE_NAME</B> String => foreign key table name
1713 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
1715 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
1716 <LI><B>UPDATE_RULE</B> short => What happens to
1717 foreign key when primary is updated:
1719 <LI> importedNoAction - do not allow update of primary
1720 key if it has been imported
1721 <LI> importedKeyCascade - change imported key to agree
1722 with primary key update
1723 <LI> importedKeySetNull - change imported key to NULL if
1724 its primary key has been updated
1725 <LI> importedKeySetDefault - change imported key to default values
1726 if its primary key has been updated
1727 <LI> importedKeyRestrict - same as importedKeyNoAction
1728 (for ODBC 2.x compatibility)
1730 <LI><B>DELETE_RULE</B> short => What happens to
1731 the foreign key when primary is deleted.
1733 <LI> importedKeyNoAction - do not allow delete of primary
1734 key if it has been imported
1735 <LI> importedKeyCascade - delete rows that import a deleted key
1736 <LI> importedKeySetNull - change imported key to NULL if
1737 its primary key has been deleted
1738 <LI> importedKeyRestrict - same as importedKeyNoAction
1739 (for ODBC 2.x compatibility)
1740 <LI> importedKeySetDefault - change imported key to default if
1741 its primary key has been deleted
1743 <LI><B>FK_NAME</B> String => foreign key name (may be null)
1744 <LI><B>PK_NAME</B> String => primary key name (may be null)
1745 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
1746 constraints be deferred until commit
1748 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
1749 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
1750 <LI> importedKeyNotDeferrable - see SQL92 for definition
1754 @param catalog a catalog name; "" retrieves those without a
1755 catalog; null means drop catalog name from the selection criteria
1756 @param schema a schema name; "" retrieves those
1758 @param table a table name
1759 @return <code>ResultSet</code> - each row is a foreign key column description
1760 @see #getImportedKeys
1762 function TZMySQLDatabaseMetadata.UncachedGetExportedKeys(const Catalog: string;
1763 const Schema: string; const Table: string): IZResultSet;
1767 LCatalog, LTable: string;
1768 TableType, Comment, Keys: String;
1769 CommentList, KeyList: TStrings;
1770 ColumnIndexes : Array[1..3] of integer;
1773 raise Exception.Create(STableIsNotSpecified); //CHANGE IT!
1775 Result:=inherited UncachedGetExportedKeys(Catalog, Schema, Table);
1777 GetCatalogAndNamePattern(Catalog, Schema, Table,
1780 KeyList := TStringList.Create;
1781 CommentList := TStringList.Create;
1783 with GetConnection.CreateStatement.ExecuteQuery(
1784 Format('SHOW TABLE STATUS FROM %s',
1785 [IC.Quote(LCatalog)])) do
1787 ColumnIndexes[1] := FindColumn('Type');
1788 ColumnIndexes[2] := FindColumn('Comment');
1789 ColumnIndexes[3] := FindColumn('Name');
1792 TableType := GetString(ColumnIndexes[1]);
1793 if (TableType <> '') and (LowerCase(TableType) = 'innodb') then
1795 Comment := GetString(ColumnIndexes[2]);
1796 if Comment <> '' then
1798 PutSplitString(CommentList, Comment, ';');
1800 if CommentList.Count > 4 then
1802 for I := 0 to CommentList.Count-1 do
1804 Keys := CommentList.Strings[1];
1805 Result.MoveToInsertRow;
1806 PutSplitString(KeyList, Keys, '() /');
1808 Result.UpdateString(5, LCatalog);
1809 Result.UpdateNull(6);// FKTABLE_SCHEM
1810 Result.UpdateString(7, GetString(ColumnIndexes[3])); // FKTABLE_NAME
1811 Result.UpdateString(8, KeyList.Strings[0]); // PKTABLE_CAT
1813 Result.UpdateString(1, KeyList.Strings[2]); // PKTABLE_CAT
1814 Result.UpdateNull(2); // PKTABLE_SCHEM
1815 Result.UpdateString(3, Table); // PKTABLE_NAME
1816 Result.UpdateInt(9, KeySeq); // KEY_SEQ
1818 Result.UpdateInt(10, Ord(ikSetDefault)); // UPDATE_RULE
1819 Result.UpdateInt(11, Ord(ikSetDefault)); // DELETE_RULE
1820 Result.UpdateNull(12); // FK_NAME
1821 Result.UpdateNull(13); // PK_NAME
1822 Result.UpdateInt(14, Ord(ikSetDefault)); // DEFERRABILITY
1839 Gets a description of the foreign key columns in the foreign key
1840 table that reference the primary key columns of the primary key
1841 table (describe how one table imports another's key.) This
1842 should normally return a single foreign key/primary key pair
1843 (most tables only import a foreign key from a table once.) They
1844 are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
1847 <P>Each foreign key column description has the following columns:
1849 <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
1850 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
1851 <LI><B>PKTABLE_NAME</B> String => primary key table name
1852 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
1853 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
1854 being exported (may be null)
1855 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
1856 being exported (may be null)
1857 <LI><B>FKTABLE_NAME</B> String => foreign key table name
1859 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
1861 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
1862 <LI><B>UPDATE_RULE</B> short => What happens to
1863 foreign key when primary is updated:
1865 <LI> importedNoAction - do not allow update of primary
1866 key if it has been imported
1867 <LI> importedKeyCascade - change imported key to agree
1868 with primary key update
1869 <LI> importedKeySetNull - change imported key to NULL if
1870 its primary key has been updated
1871 <LI> importedKeySetDefault - change imported key to default values
1872 if its primary key has been updated
1873 <LI> importedKeyRestrict - same as importedKeyNoAction
1874 (for ODBC 2.x compatibility)
1876 <LI><B>DELETE_RULE</B> short => What happens to
1877 the foreign key when primary is deleted.
1879 <LI> importedKeyNoAction - do not allow delete of primary
1880 key if it has been imported
1881 <LI> importedKeyCascade - delete rows that import a deleted key
1882 <LI> importedKeySetNull - change imported key to NULL if
1883 its primary key has been deleted
1884 <LI> importedKeyRestrict - same as importedKeyNoAction
1885 (for ODBC 2.x compatibility)
1886 <LI> importedKeySetDefault - change imported key to default if
1887 its primary key has been deleted
1889 <LI><B>FK_NAME</B> String => foreign key name (may be null)
1890 <LI><B>PK_NAME</B> String => primary key name (may be null)
1891 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
1892 constraints be deferred until commit
1894 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
1895 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
1896 <LI> importedKeyNotDeferrable - see SQL92 for definition
1900 @param primaryCatalog a catalog name; "" retrieves those without a
1901 catalog; null means drop catalog name from the selection criteria
1902 @param primarySchema a schema name; "" retrieves those
1904 @param primaryTable the table name that exports the key
1905 @param foreignCatalog a catalog name; "" retrieves those without a
1906 catalog; null means drop catalog name from the selection criteria
1907 @param foreignSchema a schema name; "" retrieves those
1909 @param foreignTable the table name that imports the key
1910 @return <code>ResultSet</code> - each row is a foreign key column description
1911 @see #getImportedKeys
1913 function TZMySQLDatabaseMetadata.UncachedGetCrossReference(const PrimaryCatalog: string;
1914 const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
1915 const ForeignSchema: string; const ForeignTable: string): IZResultSet;
1919 LForeignCatalog: string;
1920 TableType, Comment, Keys: string;
1921 CommentList, KeyList: TStrings;
1922 ColumnIndexes : Array[1..3] of integer;
1924 if PrimaryTable = '' then
1925 raise Exception.Create(STableIsNotSpecified); //CHANGE IT!
1927 Result:=inherited UncachedGetCrossReference(PrimaryCatalog, PrimarySchema, PrimaryTable,
1928 ForeignCatalog, ForeignSchema, ForeignTable);
1930 if ForeignCatalog = '' then
1931 LForeignCatalog := FDatabase
1933 LForeignCatalog := ForeignCatalog;
1935 KeyList := TStringList.Create;
1936 CommentList := TStringList.Create;
1938 with GetConnection.CreateStatement.ExecuteQuery(
1939 Format('SHOW TABLE STATUS FROM %s',
1940 [IC.Quote(LForeignCatalog)])) do
1942 ColumnIndexes[1] := FindColumn('Type');
1943 ColumnIndexes[2] := FindColumn('Comment');
1944 ColumnIndexes[3] := FindColumn('Name');
1947 TableType := GetString(ColumnIndexes[1]);
1948 if (TableType <> '') and (LowerCase(TableType) = 'innodb') then
1950 Comment := GetString(ColumnIndexes[2]);
1951 if Comment = '' then
1953 PutSplitString(CommentList, Comment, ';');
1955 if CommentList.Count > 4 then
1957 for I := 0 to CommentList.Count-1 do
1959 Keys := CommentList.Strings[1];
1960 Result.MoveToInsertRow;
1961 PutSplitString(KeyList, Keys, '() /');
1963 Result.UpdateString(5, LForeignCatalog);
1964 if ForeignSchema = '' then
1965 Result.UpdateNull(6) // FKTABLE_SCHEM
1967 Result.UpdateString(6, ForeignSchema);
1968 if ForeignTable <> GetString(ColumnIndexes[3]) then
1971 Result.UpdateString(7, GetString(ColumnIndexes[3])); // FKTABLE_NAME
1973 Result.UpdateString(8, KeyList.Strings[0]); // PKTABLE_CAT
1975 Result.UpdateString(1, KeyList.Strings[2]); // PKTABLE_CAT
1976 if PrimarySchema = '' then
1977 Result.UpdateNull(2) // PKTABLE_SCHEM
1979 Result.UpdateString(2, PrimarySchema); // PKTABLE_SCHEM
1981 if PrimaryTable = KeyList.Strings[3] then
1984 Result.UpdateString(3, PrimaryTable); // PKTABLE_NAME
1985 Result.UpdateString(4, KeyList.Strings[4]); // PKCOLUMN_NAME
1986 Result.UpdateInt(9, KeySeq); // KEY_SEQ
1987 Result.UpdateInt(10, Ord(ikSetDefault)); // UPDATE_RULE
1988 Result.UpdateInt(11, Ord(ikSetDefault)); // DELETE_RULE
1989 Result.UpdateNull(12); // FK_NAME
1990 Result.UpdateNull(13); // PK_NAME
1991 Result.UpdateInt(14, Ord(ikSetDefault)); // DEFERRABILITY
2008 Gets a description of all the standard SQL types supported by
2009 this database. They are ordered by DATA_TYPE and then by how
2010 closely the data type maps to the corresponding JDBC SQL type.
2012 <P>Each type description has the following columns:
2014 <LI><B>TYPE_NAME</B> String => Type name
2015 <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2016 <LI><B>PRECISION</B> int => maximum precision
2017 <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
2019 <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
2021 <LI><B>CREATE_PARAMS</B> String => parameters used in creating
2022 the type (may be null)
2023 <LI><B>NULLABLE</B> short => can you use NULL for this type?
2025 <LI> typeNoNulls - does not allow NULL values
2026 <LI> typeNullable - allows NULL values
2027 <LI> typeNullableUnknown - nullability unknown
2029 <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
2030 <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
2032 <LI> typePredNone - No support
2033 <LI> typePredChar - Only supported with WHERE .. LIKE
2034 <LI> typePredBasic - Supported except for WHERE .. LIKE
2035 <LI> typeSearchable - Supported for all WHERE ..
2037 <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
2038 <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
2039 <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
2040 auto-increment value?
2041 <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
2043 <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
2044 <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
2045 <LI><B>SQL_DATA_TYPE</B> int => unused
2046 <LI><B>SQL_DATETIME_SUB</B> int => unused
2047 <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
2050 @return <code>ResultSet</code> - each row is an SQL type description
2052 function TZMySQLDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
2055 TypeNames: array[1..MaxTypeCount] of string = (
2056 'BIT', 'BOOL', 'TINYINT', 'BIGINT', 'MEDIUMBLOB', 'LONG VARBINARY',
2057 'LONGBLOB', 'BLOB', 'TINYBLOB', 'VARBINARY', 'BINARY',
2058 'LONG VARCHAR', 'MEDIUMTEXT', 'LONGTEXT', 'TEXT', 'TINYTEXT',
2059 'CHAR', 'VARCHAR', 'NUMERIC', 'DECIMAL', 'INTEGER', 'INT',
2060 'MEDIUMINT', 'SMALLINT', 'DOUBLE', 'FLOAT', 'REAL', 'ENUM', 'SET',
2061 'DATE', 'TIME', 'DATETIME', 'TIMESTAMP');
2062 TypeCodes: array[1..MaxTypeCount] of TZSQLType = (
2063 stByte, stBoolean, stShort, stLong, stBinaryStream, stBinaryStream,
2064 stBinaryStream, stBinaryStream, stBinaryStream, stBytes, stBytes,
2065 stString, stAsciiStream, stAsciiStream, stAsciiStream, stAsciiStream,
2066 stString, stString, stBigDecimal, stBigDecimal, stInteger, stInteger,
2067 stInteger, stShort, stDouble, stFloat, stFloat, stString, stString,
2068 stDate, stTime, stTimestamp, stTimestamp);
2069 TypePrecision: array[1..MaxTypeCount] of Integer = (
2070 1, -1, 4, 16, 16777215, 16777215, MAXBUF, 65535, 255, 255, 255,
2071 16777215, 16777215, 2147483647, 65535, 255, 255, 255, 17, 17, 10, 10,
2072 7, 4, 17, 10, 10, 65535, 64, -1, -1, -1, -1);
2076 Result:=inherited UncachedGetTypeInfo;
2078 for I := 1 to MaxTypeCount do
2080 Result.MoveToInsertRow;
2082 Result.UpdateString(1, TypeNames[I]);
2083 Result.UpdateInt(2, Ord(TypeCodes[I]));
2084 if TypePrecision[I] >= 0 then
2085 Result.UpdateInt(3, TypePrecision[I])
2087 Result.UpdateNull(3);
2088 if TypeCodes[I] in [stString, stBytes, stDate, stTime,
2089 stTimeStamp, stBinaryStream, stAsciiStream] then
2091 Result.UpdateString(4, '''');
2092 Result.UpdateString(5, '''');
2096 Result.UpdateNull(4);
2097 Result.UpdateNull(5);
2099 Result.UpdateNull(6);
2100 Result.UpdateInt(7, Ord(ntNullable));
2101 Result.UpdateBoolean(8, False);
2102 Result.UpdateBoolean(9, False);
2103 Result.UpdateBoolean(11, False);
2104 Result.UpdateBoolean(12, False);
2105 Result.UpdateBoolean(12, TypeNames[I] = 'INTEGER');
2106 Result.UpdateNull(13);
2107 Result.UpdateNull(14);
2108 Result.UpdateNull(15);
2109 Result.UpdateNull(16);
2110 Result.UpdateNull(17);
2111 Result.UpdateInt(18, 10);
2118 Gets a description of a table's indices and statistics. They are
2119 ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
2121 <P>Each index column description has the following columns:
2123 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2124 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2125 <LI><B>TABLE_NAME</B> String => table name
2126 <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
2127 false when TYPE is tableIndexStatistic
2128 <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
2129 null when TYPE is tableIndexStatistic
2130 <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
2132 <LI><B>TYPE</B> short => index type:
2134 <LI> tableIndexStatistic - this identifies table statistics that are
2135 returned in conjuction with a table's index descriptions
2136 <LI> tableIndexClustered - this is a clustered index
2137 <LI> tableIndexHashed - this is a hashed index
2138 <LI> tableIndexOther - this is some other style of index
2140 <LI><B>ORDINAL_POSITION</B> short => column sequence number
2141 within index; zero when TYPE is tableIndexStatistic
2142 <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
2144 <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
2145 "D" => descending, may be null if sort sequence is not supported;
2146 null when TYPE is tableIndexStatistic
2147 <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
2148 this is the number of rows in the table; otherwise, it is the
2149 number of unique values in the index.
2150 <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
2151 this is the number of pages used for the table, otherwise it
2152 is the number of pages used for the current index.
2153 <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
2157 @param catalog a catalog name; "" retrieves those without a
2158 catalog; null means drop catalog name from the selection criteria
2159 @param schema a schema name; "" retrieves those without a schema
2160 @param table a table name
2161 @param unique when true, return only indices for unique values;
2162 when false, return indices regardless of whether unique or not
2163 @param approximate when true, result is allowed to reflect approximate
2164 or out of data values; when false, results are requested to be
2166 @return <code>ResultSet</code> - each row is an index column description
2168 function TZMySQLDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
2169 const Schema: string; const Table: string; Unique: Boolean;
2170 Approximate: Boolean): IZResultSet;
2172 LCatalog, LTable: string;
2173 ColumnIndexes : Array[1..7] of integer;
2176 raise Exception.Create(STableIsNotSpecified); //CHANGE IT!
2178 Result:=inherited UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
2180 GetCatalogAndNamePattern(Catalog, Schema, Table,
2183 with GetConnection.CreateStatement.ExecuteQuery(
2184 Format('SHOW INDEX FROM %s.%s',
2185 [IC.Quote(LCatalog),
2186 IC.Quote(LTable)])) do
2188 ColumnIndexes[1] := FindColumn('Table');
2189 ColumnIndexes[2] := FindColumn('Non_unique');
2190 ColumnIndexes[3] := FindColumn('Key_name');
2191 ColumnIndexes[4] := FindColumn('Seq_in_index');
2192 ColumnIndexes[5] := FindColumn('Column_name');
2193 ColumnIndexes[6] := FindColumn('Collation');
2194 ColumnIndexes[7] := FindColumn('Cardinality');
2197 Result.MoveToInsertRow;
2198 Result.UpdateString(1, LCatalog);
2199 Result.UpdateNull(2);
2200 Result.UpdateString(3, GetString(ColumnIndexes[1]));
2201 if GetInt(ColumnIndexes[2]) = 0 then
2202 Result.UpdateString(4, 'true')
2204 Result.UpdateString(4, 'false');
2205 Result.UpdateNull(5);
2206 Result.UpdateString(6, GetString(ColumnIndexes[3]));
2207 Result.UpdateInt(7, Ord(tiOther));
2208 Result.UpdateInt(8, GetInt(ColumnIndexes[4]));
2209 Result.UpdateString(9, GetString(ColumnIndexes[5]));
2210 Result.UpdateString(10, GetString(ColumnIndexes[6]));
2211 Result.UpdateString(11, GetString(ColumnIndexes[7]));
2212 Result.UpdateInt(12, 0);
2213 Result.UpdateNull(13);
2221 Gets a description of the stored procedures available in a
2224 <P>Only procedure descriptions matching the schema and
2225 procedure name criteria are returned. They are ordered by
2226 PROCEDURE_SCHEM, and PROCEDURE_NAME.
2228 <P>Each procedure description has the the following columns:
2230 <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2231 <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2232 <LI><B>PROCEDURE_NAME</B> String => procedure name
2233 <LI> reserved for future use
2234 <LI> reserved for future use
2235 <LI> reserved for future use
2236 <LI><B>REMARKS</B> String => explanatory comment on the procedure
2237 <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
2239 <LI> procedureResultUnknown - May return a result
2240 <LI> procedureNoResult - Does not return a result
2241 <LI> procedureReturnsResult - Returns a result
2245 @param catalog a catalog name; "" retrieves those without a
2246 catalog; null means drop catalog name from the selection criteria
2247 @param schemaPattern a schema name pattern; "" retrieves those
2249 @param procedureNamePattern a procedure name pattern
2250 @return <code>ResultSet</code> - each row is a procedure description
2251 @see #getSearchStringEscape
2253 function TZMySQLDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
2254 const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
2257 ProcedureNameCondition, SchemaCondition: string;
2259 If Catalog = '' then
2260 If SchemaPattern <> '' then
2261 SchemaCondition := ConstructNameCondition(SchemaPattern,'p.db')
2263 SchemaCondition := ConstructNameCondition(FDatabase,'p.db')
2265 SchemaCondition := ConstructNameCondition(Catalog,'p.db');
2266 ProcedureNameCondition := ConstructNameCondition(ProcedureNamePattern,'p.name');
2267 If SchemaCondition <> '' then
2268 SchemaCondition := ' and ' + SchemaCondition;
2269 If ProcedureNameCondition <> '' then
2270 ProcedureNameCondition := ' and ' + ProcedureNameCondition;
2272 SQL := 'SELECT NULL AS PROCEDURE_CAT, p.db AS PROCEDURE_SCHEM, '+
2273 'p.name AS PROCEDURE_NAME, NULL AS RESERVED1, NULL AS RESERVED2, '+
2274 'NULL AS RESERVED3, p.comment AS REMARKS, '+
2275 IntToStr(ProcedureReturnsResult)+' AS PROCEDURE_TYPE from mysql.proc p '+
2276 'WHERE 1=1' + SchemaCondition + ProcedureNameCondition+
2277 ' ORDER BY p.db, p.name';
2278 Result := CopyToVirtualResultSet(
2279 GetConnection.CreateStatement.ExecuteQuery(SQL),
2280 ConstructVirtualResultSet(ProceduresColumnsDynArray));
2284 Gets a description of a catalog's stored procedure parameters
2287 <P>Only descriptions matching the schema, procedure and
2288 parameter name criteria are returned. They are ordered by
2289 PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
2290 if any, is first. Next are the parameter descriptions in call
2291 order. The column descriptions follow in column number order.
2293 <P>Each row in the <code>ResultSet</code> is a parameter description or
2294 column description with the following fields:
2296 <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2297 <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2298 <LI><B>PROCEDURE_NAME</B> String => procedure name
2299 <LI><B>COLUMN_NAME</B> String => column/parameter name
2300 <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
2302 <LI> procedureColumnUnknown - nobody knows
2303 <LI> procedureColumnIn - IN parameter
2304 <LI> procedureColumnInOut - INOUT parameter
2305 <LI> procedureColumnOut - OUT parameter
2306 <LI> procedureColumnReturn - procedure return value
2307 <LI> procedureColumnResult - result column in <code>ResultSet</code>
2309 <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2310 <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
2311 type name is fully qualified
2312 <LI><B>PRECISION</B> int => precision
2313 <LI><B>LENGTH</B> int => length in bytes of data
2314 <LI><B>SCALE</B> short => scale
2315 <LI><B>RADIX</B> short => radix
2316 <LI><B>NULLABLE</B> short => can it contain NULL?
2318 <LI> procedureNoNulls - does not allow NULL values
2319 <LI> procedureNullable - allows NULL values
2320 <LI> procedureNullableUnknown - nullability unknown
2322 <LI><B>REMARKS</B> String => comment describing parameter/column
2325 <P><B>Note:</B> Some databases may not return the column
2326 descriptions for a procedure. Additional columns beyond
2327 REMARKS can be defined by the database.
2329 @param catalog a catalog name; "" retrieves those without a
2330 catalog; null means drop catalog name from the selection criteria
2331 @param schemaPattern a schema name pattern; "" retrieves those
2333 @param procedureNamePattern a procedure name pattern
2334 @param columnNamePattern a column name pattern
2335 @return <code>ResultSet</code> - each row describes a stored procedure parameter or
2337 @see #getSearchStringEscape
2339 function TZMySQLDatabaseMetadata.UncachedGetProcedureColumns(const Catalog: string;
2340 const SchemaPattern: string; const ProcedureNamePattern: string;
2341 const ColumnNamePattern: string): IZResultSet;
2343 SQL, TypeName, Temp: string;
2344 ParamList, Params, Names, Returns: TStrings;
2345 I, ColumnSize, Precision: Integer;
2346 FieldType: TZSQLType;
2347 ProcedureNameCondition, SchemaCondition: string;
2349 function GetNextName(const AName: String; NameEmpty: Boolean = False): String;
2352 if (Names.IndexOf(AName) = -1) and not NameEmpty then
2358 for N := 1 to MaxInt do
2359 if Names.IndexOf(AName+IntToStr(N)) = -1 then
2361 Names.Add(AName+IntToStr(N));
2362 Result := AName+IntToStr(N);
2367 function DecomposeParamFromList(AList: TStrings): String;
2371 procedure AddTempString(Const Value: String);
2376 Temp := Temp + LineEnding+ Trim(Value);
2382 for I := 0 to AList.Count -1 do
2383 if J < AList.Count then
2385 if (Pos('(', (AList[J])) > 0) and (Pos(')', (AList[J])) = 0) then
2386 if ( Pos('real', LowerCase(AList[J])) > 0 ) or
2387 ( Pos('float', LowerCase(AList[J])) > 0 ) or
2388 ( Pos('decimal', LowerCase(AList[J])) > 0 ) or
2389 ( Pos('numeric', LowerCase(AList[J])) > 0 ) or
2390 ( Pos('double', LowerCase(AList[J])) > 0 ) then
2392 AddTempString(AList[j]+','+AList[j+1]);
2396 if ( Pos('set', LowerCase(AList[J])) > 0 ) and
2397 ( Pos(')', LowerCase(AList[J])) = 0 ) then
2399 TypeName := AList[J];
2400 for N := J+1 to AList.Count-1 do
2402 TypeName := TypeName +','+AList[N];
2403 if Pos(')', AList[N]) > 0 then
2406 AddTempString(TypeName);
2410 AddTempString(AList[j])
2412 if not (AList[j] = '') then
2413 AddTempString(AList[j]);
2419 If Catalog = '' then
2420 If SchemaPattern <> '' then
2421 SchemaCondition := ConstructNameCondition(SchemaPattern,'p.db')
2423 SchemaCondition := ConstructNameCondition(FDatabase,'p.db')
2425 SchemaCondition := ConstructNameCondition(Catalog,'p.db');
2426 ProcedureNameCondition := ConstructNameCondition(ProcedureNamePattern,'p.name');
2427 If SchemaCondition <> '' then
2428 SchemaCondition := ' and ' + SchemaCondition;
2429 If ProcedureNameCondition <> '' then
2430 ProcedureNameCondition := ' and ' + ProcedureNameCondition;
2432 Result := inherited UncachedGetProcedureColumns(Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern);
2434 SQL := 'SELECT p.db AS PROCEDURE_CAT, NULL AS PROCEDURE_SCHEM, '+
2435 'p.name AS PROCEDURE_NAME, p.param_list AS PARAMS, p.comment AS REMARKS, '+
2436 IntToStr(ProcedureReturnsResult)+' AS PROCEDURE_TYPE, p.returns AS RETURN_VALUES '+
2437 ' from mysql.proc p where 1 = 1'+SchemaCondition+ProcedureNameCondition+
2438 ' ORDER BY p.db, p.name';
2441 with GetConnection.CreateStatement.ExecuteQuery(SQL) do
2443 ParamList := TStringList.Create;
2444 Params := TStringList.Create;
2445 Names := TStringList.Create;
2446 Returns := TStringList.Create;
2449 PutSplitString(ParamList, Trim(GetString(4)), ',');
2450 PutSplitString(ParamList, DecomposeParamFromList(ParamList), LineEnding);
2452 PutSplitString(Returns, Trim(GetString(7)), ',');
2453 PutSplitString(Returns, DecomposeParamFromList(Returns), LineEnding);
2455 for I := 0 to Returns.Count-1 do
2457 Returns[i] := 'RETURNS '+Returns[i];
2458 ParamList.Add(Returns[i]);
2461 for i := 0 to ParamList.Count -1 do
2463 PutSplitString(Params, ParamList[i], ' ');
2464 if Params.Count = 2 then {no name available}
2465 if Params[0] = 'RETURNS' then
2468 if (UpperCase(Params[1]) = 'IN') or
2469 (UpperCase(Params[1]) = 'INOUT') or
2470 (UpperCase(Params[1]) = 'OUT') then
2473 Params.Insert(0,'IN'); //Function in value
2475 Result.MoveToInsertRow;
2476 Result.UpdateString(1, GetString(1)); //PROCEDURE_CAT
2477 Result.UpdateString(2, GetString(2)); //PROCEDURE_SCHEM
2478 Result.UpdateString(3, GetString(3)); //PROCEDURE_NAME
2479 ConvertMySQLColumnInfoFromString(Params[2],
2480 ConSettings, TypeName, Temp,
2481 FieldType, ColumnSize, Precision);
2482 { process COLUMN_NAME }
2483 if Params[1] = '' then
2484 if Params[0] = 'RETURNS' then
2485 Result.UpdateString(4, 'ReturnValue')
2487 Result.UpdateString(4, GetNextName('$', True))
2489 if IC.IsQuoted(Params[1]) then
2490 Result.UpdateString(4, GetNextName(Copy(Params[1], 2, Length(Params[1])-2), (Length(Params[1])=2)))
2492 Result.UpdateString(4, GetNextName(Params[1]));
2494 if UpperCase(Params[0]) = 'OUT' then
2495 Result.UpdateInt(5, Ord(pctOut))
2497 if UpperCase(Params[0]) = 'INOUT' then
2498 Result.UpdateInt(5, Ord(pctInOut))
2500 if UpperCase(Params[0]) = 'IN' then
2501 Result.UpdateInt(5, Ord(pctIn))
2503 if UpperCase(Params[0]) = 'RETURNS' then
2504 Result.UpdateInt(5, Ord(pctReturn))
2506 Result.UpdateInt(5, Ord(pctUnknown));
2509 Result.UpdateInt(6, Ord(FieldType));
2511 Result.UpdateString(7, TypeName);
2513 Result.UpdateInt(8, ColumnSize);
2515 Result.UpdateInt(9, Precision);
2517 Result.UpdateNull(10);
2518 Result.UpdateNull(11);
2519 Result.UpdateInt(12, Ord(ntNullableUnknown));
2520 Result.UpdateNull(13);
2529 FreeAndNil(ParamList);
2530 FreeAndNil(Returns);
2535 Gets a description of a table's columns that are automatically
2536 updated when any value in a row is updated. They are
2539 <P>Each column description has the following columns:
2541 <LI><B>SCOPE</B> short => is not used
2542 <LI><B>COLUMN_NAME</B> String => column name
2543 <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
2544 <LI><B>TYPE_NAME</B> String => Data source dependent type name
2545 <LI><B>COLUMN_SIZE</B> int => precision
2546 <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
2547 <LI><B>DECIMAL_DIGITS</B> short => scale
2548 <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2549 like an Oracle ROWID
2551 <LI> versionColumnUnknown - may or may not be pseudo column
2552 <LI> versionColumnNotPseudo - is NOT a pseudo column
2553 <LI> versionColumnPseudo - is a pseudo column
2557 @param catalog a catalog name; "" retrieves those without a
2558 catalog; null means drop catalog name from the selection criteria
2559 @param schema a schema name; "" retrieves those without a schema
2560 @param table a table name
2561 @return <code>ResultSet</code> - each row is a column description
2562 @exception SQLException if a database access error occurs
2564 function TZMySQLDatabaseMetadata.UncachedGetVersionColumns(const Catalog, Schema,
2565 Table: string): IZResultSet;
2567 Result:=inherited UncachedGetVersionColumns(Catalog, Schema, Table);
2569 Result.MoveToInsertRow;
2570 Result.UpdateNull(1);
2571 Result.UpdateString(2, 'ctid');
2572 // Result.UpdateInt(3, GetSQLType('tid')); //FIX IT
2573 Result.UpdateString(4, 'tid');
2574 Result.UpdateNull(5);
2575 Result.UpdateNull(6);
2576 Result.UpdateNull(7);
2577 Result.UpdateInt(4, Ord(vcPseudo));
2582 Gets the used Collation and CharacterSet of spezified Object.
2584 @param catalog a catalog name; "" retrieves those without a
2585 catalog; null means drop catalog name from the selection criteria
2586 @param schema a schema name; "" and Catolog "" retrieves nothing
2587 @param table a table name; "" retrieves the Schema Colloation and CharacterSet
2588 @param ColumnNamePattern ColumnPattern;"" retrieves the
2589 Table(if @param TablePattern is set) or
2590 Schema(if @param TablePattern is NULL)
2591 Colloation and CharacterSet
2592 @return <code>ResultSet</code> - each row is a Collation, CharacterSet, ID,
2593 and ByteLength per Char of speziefied Object
2595 function TZMySQLDatabaseMetadata.UncachedGetCollationAndCharSet(const Catalog, SchemaPattern,
2596 TableNamePattern, ColumnNamePattern: string): IZResultSet; //EgonHugeist
2598 SQL, LCatalog: string;
2599 ColumnNameCondition, TableNameCondition, SchemaCondition: string;
2601 if Catalog = '' then
2603 if SchemaPattern <> '' then
2604 LCatalog := SchemaPattern
2606 LCatalog := FDatabase;
2609 LCatalog := Catalog;
2610 If Catalog = '' then
2611 If SchemaPattern <> '' then
2612 SchemaCondition := ConstructNameCondition(SchemaPattern,'TABLE_SCHEMA')
2614 SchemaCondition := ConstructNameCondition(FDatabase,'TABLE_SCHEMA')
2616 SchemaCondition := ConstructNameCondition(Catalog,'TABLE_SCHEMA');
2617 TableNameCondition := ConstructNameCondition(TableNamePattern,'TABLE_NAME');
2618 ColumnNameCondition := ConstructNameCondition(ColumnNamePattern,'COLUMN_NAME');
2619 If SchemaCondition <> '' then
2620 SchemaCondition := ' and ' + SchemaCondition;
2621 If TableNameCondition <> '' then
2622 TableNameCondition := ' and ' + TableNameCondition;
2623 If ColumnNameCondition <> '' then
2624 ColumnNameCondition := ' and ' + ColumnNameCondition;
2626 Result:=inherited UncachedGetCollationAndCharSet(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
2628 if SchemaCondition <> '' then
2630 if TableNamePattern <> '' then
2632 if ColumnNamePattern <> '' then
2634 SQL := 'SELECT CLMS.COLLATION_NAME, CLMS.CHARACTER_SET_NAME, CS.MAXLEN '+
2635 'FROM INFORMATION_SCHEMA.COLUMNS CLMS '+
2636 'LEFT JOIN INFORMATION_SCHEMA.CHARACTER_SETS CS '+
2637 'ON CS.DEFAULT_COLLATE_NAME = CLMS.COLLATION_NAME '+
2638 'WHERE 1=1'+ SchemaCondition + TableNameCondition + ColumnNameCondition;
2639 with GetConnection.CreateStatement.ExecuteQuery(SQL) do
2643 Result.MoveToInsertRow;
2644 Result.UpdateString(1, LCatalog); //COLLATION_CATALOG
2645 Result.UpdateString(2, LCatalog); //COLLATION_SCHEMA
2646 Result.UpdateString(3, TableNamePattern); //COLLATION_TABLE
2647 Result.UpdateString(4, ColumnNamePattern);//COLLATION_COLUMN
2648 Result.UpdateString(5, GetString(FindColumn('COLLATION_NAME'))); //COLLATION_NAME
2649 Result.UpdateString(6, GetString(FindColumn('CHARACTER_SET_NAME'))); //CHARACTER_SET_NAME
2650 Result.UpdateNull(7); //CHARACTER_SET_ID
2651 Result.UpdateShort(8, GetShort(FindColumn('MAXLEN'))); //CHARACTER_SET_SIZE
2659 SQL := 'SELECT TBLS.TABLE_COLLATION, CS.CHARACTER_SET_NAME, CS.MAXLEN '+
2660 'FROM INFORMATION_SCHEMA.TABLES TBLS LEFT JOIN '+
2661 'INFORMATION_SCHEMA.CHARACTER_SETS CS ON '+
2662 'TBLS.TABLE_COLLATION = CS.DEFAULT_COLLATE_NAME '+
2663 'WHERE 1=1'+ SchemaCondition + TableNameCondition;
2664 with GetConnection.CreateStatement.ExecuteQuery(SQL) do
2668 Result.MoveToInsertRow;
2669 Result.UpdateString(1, LCatalog); //COLLATION_CATALOG
2670 Result.UpdateString(2, LCatalog); //COLLATION_SCHEMA
2671 Result.UpdateString(3, TableNamePattern); //COLLATION_TABLE
2672 Result.UpdateString(5, GetString(FindColumn('TABLE_COLLATION'))); //COLLATION_NAME
2673 Result.UpdateString(6, GetString(FindColumn('CHARACTER_SET_NAME'))); //CHARACTER_SET_NAME
2674 Result.UpdateNull(7); //CHARACTER_SET_ID
2675 Result.UpdateShort(8, GetShort(FindColumn('MAXLEN'))); //CHARACTER_SET_SIZE
2684 SchemaCondition := ConstructNameCondition(LCatalog, 'and SCHEMA_NAME');
2685 SQL := 'SELECT S.DEFAULT_COLLATION_NAME, S.DEFAULT_CHARACTER_SET_NAME, '+
2686 'CS.MAXLEN FROM INFORMATION_SCHEMA.SCHEMATA S '+
2687 'LEFT JOIN INFORMATION_SCHEMA.CHARACTER_SETS CS '+
2688 'ON CS.DEFAULT_COLLATE_NAME = S.DEFAULT_COLLATION_NAME '+
2689 'WHERE 1=1 '+ SchemaCondition;
2690 with GetConnection.CreateStatement.ExecuteQuery(SQL) do
2694 Result.MoveToInsertRow;
2695 Result.UpdateString(1, LCatalog); //COLLATION_CATALOG
2696 Result.UpdateString(2, LCatalog); //COLLATION_SCHEMA
2697 Result.UpdateNull(3); //COLLATION_TABLE
2698 Result.UpdateNull(4);//COLLATION_COLUMN
2699 Result.UpdateString(5, GetString(FindColumn('DEFAULT_COLLATION_NAME'))); //COLLATION_NAME
2700 Result.UpdateString(6, GetString(FindColumn('DEFAULT_CHARACTER_SET_NAME'))); //CHARACTER_SET_NAME
2701 Result.UpdateNull(7); //CHARACTER_SET_ID
2702 Result.UpdateShort(8, GetShort(FindColumn('MAXLEN'))); //CHARACTER_SET_SIZE
2712 Gets the supported CharacterSets:
2713 @return <code>ResultSet</code> - each row is a CharacterSetName and it's ID
2715 function TZMySQLDatabaseMetadata.UncachedGetCharacterSets: IZResultSet; //EgonHugeist
2717 Result:=inherited UncachedGetCharacterSets;
2719 with GetConnection.CreateStatement.ExecuteQuery(
2720 'SELECT CHARACTER_SET_NAME '+
2721 'FROM INFORMATION_SCHEMA.CHARACTER_SETS') do
2725 Result.MoveToInsertRow;
2726 Result.UpdateString(1, GetString(FindColumn('CHARACTER_SET_NAME'))); //CHARACTER_SET_NAME
2727 Result.UpdateNull(2); //CHARACTER_SET_ID