1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.table; |
7 | |
8 | import java.io.ByteArrayInputStream; |
9 | import java.io.IOException; |
10 | import java.io.InputStreamReader; |
11 | import java.io.Reader; |
12 | import java.sql.DatabaseMetaData; |
13 | import java.sql.ResultSet; |
14 | import java.sql.Timestamp; |
15 | import java.text.Collator; |
16 | import java.util.ArrayList; |
17 | import java.util.Collections; |
18 | import java.util.HashMap; |
19 | import java.util.Locale; |
20 | import org.h2.command.Command; |
21 | import org.h2.constraint.Constraint; |
22 | import org.h2.constraint.ConstraintCheck; |
23 | import org.h2.constraint.ConstraintReferential; |
24 | import org.h2.constraint.ConstraintUnique; |
25 | import org.h2.engine.Constants; |
26 | import org.h2.engine.Database; |
27 | import org.h2.engine.DbObject; |
28 | import org.h2.engine.FunctionAlias; |
29 | import org.h2.engine.FunctionAlias.JavaMethod; |
30 | import org.h2.engine.QueryStatisticsData; |
31 | import org.h2.engine.Right; |
32 | import org.h2.engine.Role; |
33 | import org.h2.engine.Session; |
34 | import org.h2.engine.Setting; |
35 | import org.h2.engine.User; |
36 | import org.h2.engine.UserAggregate; |
37 | import org.h2.engine.UserDataType; |
38 | import org.h2.expression.ValueExpression; |
39 | import org.h2.index.Index; |
40 | import org.h2.index.IndexType; |
41 | import org.h2.index.MetaIndex; |
42 | import org.h2.index.MultiVersionIndex; |
43 | import org.h2.jdbc.JdbcSQLException; |
44 | import org.h2.message.DbException; |
45 | import org.h2.mvstore.FileStore; |
46 | import org.h2.mvstore.db.MVTableEngine.Store; |
47 | import org.h2.result.Row; |
48 | import org.h2.result.SearchRow; |
49 | import org.h2.result.SortOrder; |
50 | import org.h2.schema.Constant; |
51 | import org.h2.schema.Schema; |
52 | import org.h2.schema.SchemaObject; |
53 | import org.h2.schema.Sequence; |
54 | import org.h2.schema.TriggerObject; |
55 | import org.h2.store.InDoubtTransaction; |
56 | import org.h2.store.PageStore; |
57 | import org.h2.tools.Csv; |
58 | import org.h2.util.MathUtils; |
59 | import org.h2.util.New; |
60 | import org.h2.util.StatementBuilder; |
61 | import org.h2.util.StringUtils; |
62 | import org.h2.util.Utils; |
63 | import org.h2.value.CompareMode; |
64 | import org.h2.value.DataType; |
65 | import org.h2.value.Value; |
66 | import org.h2.value.ValueNull; |
67 | import org.h2.value.ValueString; |
68 | import org.h2.value.ValueStringIgnoreCase; |
69 | |
70 | /** |
71 | * This class is responsible to build the database meta data pseudo tables. |
72 | */ |
73 | public class MetaTable extends Table { |
74 | |
75 | /** |
76 | * The approximate number of rows of a meta table. |
77 | */ |
78 | public static final long ROW_COUNT_APPROXIMATION = 1000; |
79 | |
80 | private static final String CHARACTER_SET_NAME = "Unicode"; |
81 | |
82 | private static final int TABLES = 0; |
83 | private static final int COLUMNS = 1; |
84 | private static final int INDEXES = 2; |
85 | private static final int TABLE_TYPES = 3; |
86 | private static final int TYPE_INFO = 4; |
87 | private static final int CATALOGS = 5; |
88 | private static final int SETTINGS = 6; |
89 | private static final int HELP = 7; |
90 | private static final int SEQUENCES = 8; |
91 | private static final int USERS = 9; |
92 | private static final int ROLES = 10; |
93 | private static final int RIGHTS = 11; |
94 | private static final int FUNCTION_ALIASES = 12; |
95 | private static final int SCHEMATA = 13; |
96 | private static final int TABLE_PRIVILEGES = 14; |
97 | private static final int COLUMN_PRIVILEGES = 15; |
98 | private static final int COLLATIONS = 16; |
99 | private static final int VIEWS = 17; |
100 | private static final int IN_DOUBT = 18; |
101 | private static final int CROSS_REFERENCES = 19; |
102 | private static final int CONSTRAINTS = 20; |
103 | private static final int FUNCTION_COLUMNS = 21; |
104 | private static final int CONSTANTS = 22; |
105 | private static final int DOMAINS = 23; |
106 | private static final int TRIGGERS = 24; |
107 | private static final int SESSIONS = 25; |
108 | private static final int LOCKS = 26; |
109 | private static final int SESSION_STATE = 27; |
110 | private static final int QUERY_STATISTICS = 28; |
111 | private static final int META_TABLE_TYPE_COUNT = QUERY_STATISTICS + 1; |
112 | |
113 | private final int type; |
114 | private final int indexColumn; |
115 | private final MetaIndex metaIndex; |
116 | |
117 | /** |
118 | * Create a new metadata table. |
119 | * |
120 | * @param schema the schema |
121 | * @param id the object id |
122 | * @param type the meta table type |
123 | */ |
124 | public MetaTable(Schema schema, int id, int type) { |
125 | // tableName will be set later |
126 | super(schema, id, null, true, true); |
127 | this.type = type; |
128 | Column[] cols; |
129 | String indexColumnName = null; |
130 | switch(type) { |
131 | case TABLES: |
132 | setObjectName("TABLES"); |
133 | cols = createColumns( |
134 | "TABLE_CATALOG", |
135 | "TABLE_SCHEMA", |
136 | "TABLE_NAME", |
137 | "TABLE_TYPE", |
138 | // extensions |
139 | "STORAGE_TYPE", |
140 | "SQL", |
141 | "REMARKS", |
142 | "LAST_MODIFICATION BIGINT", |
143 | "ID INT", |
144 | "TYPE_NAME", |
145 | "TABLE_CLASS", |
146 | "ROW_COUNT_ESTIMATE BIGINT" |
147 | ); |
148 | indexColumnName = "TABLE_NAME"; |
149 | break; |
150 | case COLUMNS: |
151 | setObjectName("COLUMNS"); |
152 | cols = createColumns( |
153 | "TABLE_CATALOG", |
154 | "TABLE_SCHEMA", |
155 | "TABLE_NAME", |
156 | "COLUMN_NAME", |
157 | "ORDINAL_POSITION INT", |
158 | "COLUMN_DEFAULT", |
159 | "IS_NULLABLE", |
160 | "DATA_TYPE INT", |
161 | "CHARACTER_MAXIMUM_LENGTH INT", |
162 | "CHARACTER_OCTET_LENGTH INT", |
163 | "NUMERIC_PRECISION INT", |
164 | "NUMERIC_PRECISION_RADIX INT", |
165 | "NUMERIC_SCALE INT", |
166 | "CHARACTER_SET_NAME", |
167 | "COLLATION_NAME", |
168 | // extensions |
169 | "TYPE_NAME", |
170 | "NULLABLE INT", |
171 | "IS_COMPUTED BIT", |
172 | "SELECTIVITY INT", |
173 | "CHECK_CONSTRAINT", |
174 | "SEQUENCE_NAME", |
175 | "REMARKS", |
176 | "SOURCE_DATA_TYPE SMALLINT" |
177 | ); |
178 | indexColumnName = "TABLE_NAME"; |
179 | break; |
180 | case INDEXES: |
181 | setObjectName("INDEXES"); |
182 | cols = createColumns( |
183 | "TABLE_CATALOG", |
184 | "TABLE_SCHEMA", |
185 | "TABLE_NAME", |
186 | "NON_UNIQUE BIT", |
187 | "INDEX_NAME", |
188 | "ORDINAL_POSITION SMALLINT", |
189 | "COLUMN_NAME", |
190 | "CARDINALITY INT", |
191 | "PRIMARY_KEY BIT", |
192 | "INDEX_TYPE_NAME", |
193 | "IS_GENERATED BIT", |
194 | "INDEX_TYPE SMALLINT", |
195 | "ASC_OR_DESC", |
196 | "PAGES INT", |
197 | "FILTER_CONDITION", |
198 | "REMARKS", |
199 | "SQL", |
200 | "ID INT", |
201 | "SORT_TYPE INT", |
202 | "CONSTRAINT_NAME", |
203 | "INDEX_CLASS" |
204 | ); |
205 | indexColumnName = "TABLE_NAME"; |
206 | break; |
207 | case TABLE_TYPES: |
208 | setObjectName("TABLE_TYPES"); |
209 | cols = createColumns("TYPE"); |
210 | break; |
211 | case TYPE_INFO: |
212 | setObjectName("TYPE_INFO"); |
213 | cols = createColumns( |
214 | "TYPE_NAME", |
215 | "DATA_TYPE INT", |
216 | "PRECISION INT", |
217 | "PREFIX", |
218 | "SUFFIX", |
219 | "PARAMS", |
220 | "AUTO_INCREMENT BIT", |
221 | "MINIMUM_SCALE SMALLINT", |
222 | "MAXIMUM_SCALE SMALLINT", |
223 | "RADIX INT", |
224 | "POS INT", |
225 | "CASE_SENSITIVE BIT", |
226 | "NULLABLE SMALLINT", |
227 | "SEARCHABLE SMALLINT" |
228 | ); |
229 | break; |
230 | case CATALOGS: |
231 | setObjectName("CATALOGS"); |
232 | cols = createColumns("CATALOG_NAME"); |
233 | break; |
234 | case SETTINGS: |
235 | setObjectName("SETTINGS"); |
236 | cols = createColumns("NAME", "VALUE"); |
237 | break; |
238 | case HELP: |
239 | setObjectName("HELP"); |
240 | cols = createColumns( |
241 | "ID INT", |
242 | "SECTION", |
243 | "TOPIC", |
244 | "SYNTAX", |
245 | "TEXT" |
246 | ); |
247 | break; |
248 | case SEQUENCES: |
249 | setObjectName("SEQUENCES"); |
250 | cols = createColumns( |
251 | "SEQUENCE_CATALOG", |
252 | "SEQUENCE_SCHEMA", |
253 | "SEQUENCE_NAME", |
254 | "CURRENT_VALUE BIGINT", |
255 | "INCREMENT BIGINT", |
256 | "IS_GENERATED BIT", |
257 | "REMARKS", |
258 | "CACHE BIGINT", |
259 | "MIN_VALUE BIGINT", |
260 | "MAX_VALUE BIGINT", |
261 | "IS_CYCLE BIT", |
262 | "ID INT" |
263 | ); |
264 | break; |
265 | case USERS: |
266 | setObjectName("USERS"); |
267 | cols = createColumns( |
268 | "NAME", |
269 | "ADMIN", |
270 | "REMARKS", |
271 | "ID INT" |
272 | ); |
273 | break; |
274 | case ROLES: |
275 | setObjectName("ROLES"); |
276 | cols = createColumns( |
277 | "NAME", |
278 | "REMARKS", |
279 | "ID INT" |
280 | ); |
281 | break; |
282 | case RIGHTS: |
283 | setObjectName("RIGHTS"); |
284 | cols = createColumns( |
285 | "GRANTEE", |
286 | "GRANTEETYPE", |
287 | "GRANTEDROLE", |
288 | "RIGHTS", |
289 | "TABLE_SCHEMA", |
290 | "TABLE_NAME", |
291 | "ID INT" |
292 | ); |
293 | indexColumnName = "TABLE_NAME"; |
294 | break; |
295 | case FUNCTION_ALIASES: |
296 | setObjectName("FUNCTION_ALIASES"); |
297 | cols = createColumns( |
298 | "ALIAS_CATALOG", |
299 | "ALIAS_SCHEMA", |
300 | "ALIAS_NAME", |
301 | "JAVA_CLASS", |
302 | "JAVA_METHOD", |
303 | "DATA_TYPE INT", |
304 | "TYPE_NAME", |
305 | "COLUMN_COUNT INT", |
306 | "RETURNS_RESULT SMALLINT", |
307 | "REMARKS", |
308 | "ID INT", |
309 | "SOURCE" |
310 | ); |
311 | break; |
312 | case FUNCTION_COLUMNS: |
313 | setObjectName("FUNCTION_COLUMNS"); |
314 | cols = createColumns( |
315 | "ALIAS_CATALOG", |
316 | "ALIAS_SCHEMA", |
317 | "ALIAS_NAME", |
318 | "JAVA_CLASS", |
319 | "JAVA_METHOD", |
320 | "COLUMN_COUNT INT", |
321 | "POS INT", |
322 | "COLUMN_NAME", |
323 | "DATA_TYPE INT", |
324 | "TYPE_NAME", |
325 | "PRECISION INT", |
326 | "SCALE SMALLINT", |
327 | "RADIX SMALLINT", |
328 | "NULLABLE SMALLINT", |
329 | "COLUMN_TYPE SMALLINT", |
330 | "REMARKS", |
331 | "COLUMN_DEFAULT" |
332 | ); |
333 | break; |
334 | case SCHEMATA: |
335 | setObjectName("SCHEMATA"); |
336 | cols = createColumns( |
337 | "CATALOG_NAME", |
338 | "SCHEMA_NAME", |
339 | "SCHEMA_OWNER", |
340 | "DEFAULT_CHARACTER_SET_NAME", |
341 | "DEFAULT_COLLATION_NAME", |
342 | "IS_DEFAULT BIT", |
343 | "REMARKS", |
344 | "ID INT" |
345 | ); |
346 | break; |
347 | case TABLE_PRIVILEGES: |
348 | setObjectName("TABLE_PRIVILEGES"); |
349 | cols = createColumns( |
350 | "GRANTOR", |
351 | "GRANTEE", |
352 | "TABLE_CATALOG", |
353 | "TABLE_SCHEMA", |
354 | "TABLE_NAME", |
355 | "PRIVILEGE_TYPE", |
356 | "IS_GRANTABLE" |
357 | ); |
358 | indexColumnName = "TABLE_NAME"; |
359 | break; |
360 | case COLUMN_PRIVILEGES: |
361 | setObjectName("COLUMN_PRIVILEGES"); |
362 | cols = createColumns( |
363 | "GRANTOR", |
364 | "GRANTEE", |
365 | "TABLE_CATALOG", |
366 | "TABLE_SCHEMA", |
367 | "TABLE_NAME", |
368 | "COLUMN_NAME", |
369 | "PRIVILEGE_TYPE", |
370 | "IS_GRANTABLE" |
371 | ); |
372 | indexColumnName = "TABLE_NAME"; |
373 | break; |
374 | case COLLATIONS: |
375 | setObjectName("COLLATIONS"); |
376 | cols = createColumns( |
377 | "NAME", |
378 | "KEY" |
379 | ); |
380 | break; |
381 | case VIEWS: |
382 | setObjectName("VIEWS"); |
383 | cols = createColumns( |
384 | "TABLE_CATALOG", |
385 | "TABLE_SCHEMA", |
386 | "TABLE_NAME", |
387 | "VIEW_DEFINITION", |
388 | "CHECK_OPTION", |
389 | "IS_UPDATABLE", |
390 | "STATUS", |
391 | "REMARKS", |
392 | "ID INT" |
393 | ); |
394 | indexColumnName = "TABLE_NAME"; |
395 | break; |
396 | case IN_DOUBT: |
397 | setObjectName("IN_DOUBT"); |
398 | cols = createColumns( |
399 | "TRANSACTION", |
400 | "STATE" |
401 | ); |
402 | break; |
403 | case CROSS_REFERENCES: |
404 | setObjectName("CROSS_REFERENCES"); |
405 | cols = createColumns( |
406 | "PKTABLE_CATALOG", |
407 | "PKTABLE_SCHEMA", |
408 | "PKTABLE_NAME", |
409 | "PKCOLUMN_NAME", |
410 | "FKTABLE_CATALOG", |
411 | "FKTABLE_SCHEMA", |
412 | "FKTABLE_NAME", |
413 | "FKCOLUMN_NAME", |
414 | "ORDINAL_POSITION SMALLINT", |
415 | "UPDATE_RULE SMALLINT", |
416 | "DELETE_RULE SMALLINT", |
417 | "FK_NAME", |
418 | "PK_NAME", |
419 | "DEFERRABILITY SMALLINT" |
420 | ); |
421 | indexColumnName = "PKTABLE_NAME"; |
422 | break; |
423 | case CONSTRAINTS: |
424 | setObjectName("CONSTRAINTS"); |
425 | cols = createColumns( |
426 | "CONSTRAINT_CATALOG", |
427 | "CONSTRAINT_SCHEMA", |
428 | "CONSTRAINT_NAME", |
429 | "CONSTRAINT_TYPE", |
430 | "TABLE_CATALOG", |
431 | "TABLE_SCHEMA", |
432 | "TABLE_NAME", |
433 | "UNIQUE_INDEX_NAME", |
434 | "CHECK_EXPRESSION", |
435 | "COLUMN_LIST", |
436 | "REMARKS", |
437 | "SQL", |
438 | "ID INT" |
439 | ); |
440 | indexColumnName = "TABLE_NAME"; |
441 | break; |
442 | case CONSTANTS: |
443 | setObjectName("CONSTANTS"); |
444 | cols = createColumns( |
445 | "CONSTANT_CATALOG", |
446 | "CONSTANT_SCHEMA", |
447 | "CONSTANT_NAME", |
448 | "DATA_TYPE INT", |
449 | "REMARKS", |
450 | "SQL", |
451 | "ID INT" |
452 | ); |
453 | break; |
454 | case DOMAINS: |
455 | setObjectName("DOMAINS"); |
456 | cols = createColumns( |
457 | "DOMAIN_CATALOG", |
458 | "DOMAIN_SCHEMA", |
459 | "DOMAIN_NAME", |
460 | "COLUMN_DEFAULT", |
461 | "IS_NULLABLE", |
462 | "DATA_TYPE INT", |
463 | "PRECISION INT", |
464 | "SCALE INT", |
465 | "TYPE_NAME", |
466 | "SELECTIVITY INT", |
467 | "CHECK_CONSTRAINT", |
468 | "REMARKS", |
469 | "SQL", |
470 | "ID INT" |
471 | ); |
472 | break; |
473 | case TRIGGERS: |
474 | setObjectName("TRIGGERS"); |
475 | cols = createColumns( |
476 | "TRIGGER_CATALOG", |
477 | "TRIGGER_SCHEMA", |
478 | "TRIGGER_NAME", |
479 | "TRIGGER_TYPE", |
480 | "TABLE_CATALOG", |
481 | "TABLE_SCHEMA", |
482 | "TABLE_NAME", |
483 | "BEFORE BIT", |
484 | "JAVA_CLASS", |
485 | "QUEUE_SIZE INT", |
486 | "NO_WAIT BIT", |
487 | "REMARKS", |
488 | "SQL", |
489 | "ID INT" |
490 | ); |
491 | break; |
492 | case SESSIONS: { |
493 | setObjectName("SESSIONS"); |
494 | cols = createColumns( |
495 | "ID INT", |
496 | "USER_NAME", |
497 | "SESSION_START", |
498 | "STATEMENT", |
499 | "STATEMENT_START", |
500 | "CONTAINS_UNCOMMITTED" |
501 | ); |
502 | break; |
503 | } |
504 | case LOCKS: { |
505 | setObjectName("LOCKS"); |
506 | cols = createColumns( |
507 | "TABLE_SCHEMA", |
508 | "TABLE_NAME", |
509 | "SESSION_ID INT", |
510 | "LOCK_TYPE" |
511 | ); |
512 | break; |
513 | } |
514 | case SESSION_STATE: { |
515 | setObjectName("SESSION_STATE"); |
516 | cols = createColumns( |
517 | "KEY", |
518 | "SQL" |
519 | ); |
520 | break; |
521 | } |
522 | case QUERY_STATISTICS: { |
523 | setObjectName("QUERY_STATISTICS"); |
524 | cols = createColumns( |
525 | "SQL_STATEMENT", |
526 | "EXECUTION_COUNT INT", |
527 | "MIN_EXECUTION_TIME LONG", |
528 | "MAX_EXECUTION_TIME LONG", |
529 | "CUMULATIVE_EXECUTION_TIME LONG", |
530 | "AVERAGE_EXECUTION_TIME DOUBLE", |
531 | "STD_DEV_EXECUTION_TIME DOUBLE", |
532 | "MIN_ROW_COUNT INT", |
533 | "MAX_ROW_COUNT INT", |
534 | "CUMULATIVE_ROW_COUNT LONG", |
535 | "AVERAGE_ROW_COUNT DOUBLE", |
536 | "STD_DEV_ROW_COUNT DOUBLE" |
537 | ); |
538 | break; |
539 | } |
540 | default: |
541 | throw DbException.throwInternalError("type="+type); |
542 | } |
543 | setColumns(cols); |
544 | |
545 | if (indexColumnName == null) { |
546 | indexColumn = -1; |
547 | metaIndex = null; |
548 | } else { |
549 | indexColumn = getColumn(indexColumnName).getColumnId(); |
550 | IndexColumn[] indexCols = IndexColumn.wrap( |
551 | new Column[] { cols[indexColumn] }); |
552 | metaIndex = new MetaIndex(this, indexCols, false); |
553 | } |
554 | } |
555 | |
556 | private Column[] createColumns(String... names) { |
557 | Column[] cols = new Column[names.length]; |
558 | for (int i = 0; i < names.length; i++) { |
559 | String nameType = names[i]; |
560 | int idx = nameType.indexOf(' '); |
561 | int dataType; |
562 | String name; |
563 | if (idx < 0) { |
564 | dataType = database.getMode().lowerCaseIdentifiers ? |
565 | Value.STRING_IGNORECASE : Value.STRING; |
566 | name = nameType; |
567 | } else { |
568 | dataType = DataType.getTypeByName(nameType.substring(idx + 1)).type; |
569 | name = nameType.substring(0, idx); |
570 | } |
571 | cols[i] = new Column(name, dataType); |
572 | } |
573 | return cols; |
574 | } |
575 | |
576 | @Override |
577 | public String getDropSQL() { |
578 | return null; |
579 | } |
580 | |
581 | @Override |
582 | public String getCreateSQL() { |
583 | return null; |
584 | } |
585 | |
586 | @Override |
587 | public Index addIndex(Session session, String indexName, int indexId, |
588 | IndexColumn[] cols, IndexType indexType, boolean create, |
589 | String indexComment) { |
590 | throw DbException.getUnsupportedException("META"); |
591 | } |
592 | |
593 | @Override |
594 | public boolean lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) { |
595 | // nothing to do |
596 | return false; |
597 | } |
598 | |
599 | @Override |
600 | public boolean isLockedExclusively() { |
601 | return false; |
602 | } |
603 | |
604 | private String identifier(String s) { |
605 | if (database.getMode().lowerCaseIdentifiers) { |
606 | s = s == null ? null : StringUtils.toLowerEnglish(s); |
607 | } |
608 | return s; |
609 | } |
610 | |
611 | private ArrayList<Table> getAllTables(Session session) { |
612 | ArrayList<Table> tables = database.getAllTablesAndViews(true); |
613 | ArrayList<Table> tempTables = session.getLocalTempTables(); |
614 | tables.addAll(tempTables); |
615 | return tables; |
616 | } |
617 | |
618 | private boolean checkIndex(Session session, String value, Value indexFrom, |
619 | Value indexTo) { |
620 | if (value == null || (indexFrom == null && indexTo == null)) { |
621 | return true; |
622 | } |
623 | Database db = session.getDatabase(); |
624 | Value v; |
625 | if (database.getMode().lowerCaseIdentifiers) { |
626 | v = ValueStringIgnoreCase.get(value); |
627 | } else { |
628 | v = ValueString.get(value); |
629 | } |
630 | if (indexFrom != null && db.compare(v, indexFrom) < 0) { |
631 | return false; |
632 | } |
633 | if (indexTo != null && db.compare(v, indexTo) > 0) { |
634 | return false; |
635 | } |
636 | return true; |
637 | } |
638 | |
639 | private static String replaceNullWithEmpty(String s) { |
640 | return s == null ? "" : s; |
641 | } |
642 | |
643 | private boolean hideTable(Table table, Session session) { |
644 | return table.isHidden() && session != database.getSystemSession(); |
645 | } |
646 | |
647 | /** |
648 | * Generate the data for the given metadata table using the given first and |
649 | * last row filters. |
650 | * |
651 | * @param session the session |
652 | * @param first the first row to return |
653 | * @param last the last row to return |
654 | * @return the generated rows |
655 | */ |
656 | public ArrayList<Row> generateRows(Session session, SearchRow first, |
657 | SearchRow last) { |
658 | Value indexFrom = null, indexTo = null; |
659 | |
660 | if (indexColumn >= 0) { |
661 | if (first != null) { |
662 | indexFrom = first.getValue(indexColumn); |
663 | } |
664 | if (last != null) { |
665 | indexTo = last.getValue(indexColumn); |
666 | } |
667 | } |
668 | |
669 | ArrayList<Row> rows = New.arrayList(); |
670 | String catalog = identifier(database.getShortName()); |
671 | boolean admin = session.getUser().isAdmin(); |
672 | switch (type) { |
673 | case TABLES: { |
674 | for (Table table : getAllTables(session)) { |
675 | String tableName = identifier(table.getName()); |
676 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
677 | continue; |
678 | } |
679 | if (hideTable(table, session)) { |
680 | continue; |
681 | } |
682 | String storageType; |
683 | if (table.isTemporary()) { |
684 | if (table.isGlobalTemporary()) { |
685 | storageType = "GLOBAL TEMPORARY"; |
686 | } else { |
687 | storageType = "LOCAL TEMPORARY"; |
688 | } |
689 | } else { |
690 | storageType = table.isPersistIndexes() ? |
691 | "CACHED" : "MEMORY"; |
692 | } |
693 | String sql = table.getCreateSQL(); |
694 | if (!admin) { |
695 | if (sql != null && sql.contains(JdbcSQLException.HIDE_SQL)) { |
696 | // hide the password of linked tables |
697 | sql = "-"; |
698 | } |
699 | } |
700 | add(rows, |
701 | // TABLE_CATALOG |
702 | catalog, |
703 | // TABLE_SCHEMA |
704 | identifier(table.getSchema().getName()), |
705 | // TABLE_NAME |
706 | tableName, |
707 | // TABLE_TYPE |
708 | table.getTableType(), |
709 | // STORAGE_TYPE |
710 | storageType, |
711 | // SQL |
712 | sql, |
713 | // REMARKS |
714 | replaceNullWithEmpty(table.getComment()), |
715 | // LAST_MODIFICATION |
716 | "" + table.getMaxDataModificationId(), |
717 | // ID |
718 | "" + table.getId(), |
719 | // TYPE_NAME |
720 | null, |
721 | // TABLE_CLASS |
722 | table.getClass().getName(), |
723 | // ROW_COUNT_ESTIMATE |
724 | "" + table.getRowCountApproximation() |
725 | ); |
726 | } |
727 | break; |
728 | } |
729 | case COLUMNS: { |
730 | for (Table table : getAllTables(session)) { |
731 | String tableName = identifier(table.getName()); |
732 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
733 | continue; |
734 | } |
735 | if (hideTable(table, session)) { |
736 | continue; |
737 | } |
738 | Column[] cols = table.getColumns(); |
739 | String collation = database.getCompareMode().getName(); |
740 | for (int j = 0; j < cols.length; j++) { |
741 | Column c = cols[j]; |
742 | Sequence sequence = c.getSequence(); |
743 | add(rows, |
744 | // TABLE_CATALOG |
745 | catalog, |
746 | // TABLE_SCHEMA |
747 | identifier(table.getSchema().getName()), |
748 | // TABLE_NAME |
749 | tableName, |
750 | // COLUMN_NAME |
751 | identifier(c.getName()), |
752 | // ORDINAL_POSITION |
753 | String.valueOf(j + 1), |
754 | // COLUMN_DEFAULT |
755 | c.getDefaultSQL(), |
756 | // IS_NULLABLE |
757 | c.isNullable() ? "YES" : "NO", |
758 | // DATA_TYPE |
759 | "" + DataType.convertTypeToSQLType(c.getType()), |
760 | // CHARACTER_MAXIMUM_LENGTH |
761 | "" + c.getPrecisionAsInt(), |
762 | // CHARACTER_OCTET_LENGTH |
763 | "" + c.getPrecisionAsInt(), |
764 | // NUMERIC_PRECISION |
765 | "" + c.getPrecisionAsInt(), |
766 | // NUMERIC_PRECISION_RADIX |
767 | "10", |
768 | // NUMERIC_SCALE |
769 | "" + c.getScale(), |
770 | // CHARACTER_SET_NAME |
771 | CHARACTER_SET_NAME, |
772 | // COLLATION_NAME |
773 | collation, |
774 | // TYPE_NAME |
775 | identifier(DataType.getDataType(c.getType()).name), |
776 | // NULLABLE |
777 | "" + (c.isNullable() ? |
778 | DatabaseMetaData.columnNullable : |
779 | DatabaseMetaData.columnNoNulls) , |
780 | // IS_COMPUTED |
781 | "" + (c.getComputed() ? "TRUE" : "FALSE"), |
782 | // SELECTIVITY |
783 | "" + (c.getSelectivity()), |
784 | // CHECK_CONSTRAINT |
785 | c.getCheckConstraintSQL(session, c.getName()), |
786 | // SEQUENCE_NAME |
787 | sequence == null ? null : sequence.getName(), |
788 | // REMARKS |
789 | replaceNullWithEmpty(c.getComment()), |
790 | // SOURCE_DATA_TYPE |
791 | null |
792 | ); |
793 | } |
794 | } |
795 | break; |
796 | } |
797 | case INDEXES: { |
798 | for (Table table : getAllTables(session)) { |
799 | String tableName = identifier(table.getName()); |
800 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
801 | continue; |
802 | } |
803 | if (hideTable(table, session)) { |
804 | continue; |
805 | } |
806 | ArrayList<Index> indexes = table.getIndexes(); |
807 | ArrayList<Constraint> constraints = table.getConstraints(); |
808 | for (int j = 0; indexes != null && j < indexes.size(); j++) { |
809 | Index index = indexes.get(j); |
810 | if (index.getCreateSQL() == null) { |
811 | continue; |
812 | } |
813 | String constraintName = null; |
814 | for (int k = 0; constraints != null && k < constraints.size(); k++) { |
815 | Constraint constraint = constraints.get(k); |
816 | if (constraint.usesIndex(index)) { |
817 | if (index.getIndexType().isPrimaryKey()) { |
818 | if (constraint.getConstraintType().equals( |
819 | Constraint.PRIMARY_KEY)) { |
820 | constraintName = constraint.getName(); |
821 | } |
822 | } else { |
823 | constraintName = constraint.getName(); |
824 | } |
825 | } |
826 | } |
827 | IndexColumn[] cols = index.getIndexColumns(); |
828 | String indexClass; |
829 | if (index instanceof MultiVersionIndex) { |
830 | indexClass = ((MultiVersionIndex) index). |
831 | getBaseIndex().getClass().getName(); |
832 | } else { |
833 | indexClass = index.getClass().getName(); |
834 | } |
835 | for (int k = 0; k < cols.length; k++) { |
836 | IndexColumn idxCol = cols[k]; |
837 | Column column = idxCol.column; |
838 | add(rows, |
839 | // TABLE_CATALOG |
840 | catalog, |
841 | // TABLE_SCHEMA |
842 | identifier(table.getSchema().getName()), |
843 | // TABLE_NAME |
844 | tableName, |
845 | // NON_UNIQUE |
846 | index.getIndexType().isUnique() ? |
847 | "FALSE" : "TRUE", |
848 | // INDEX_NAME |
849 | identifier(index.getName()), |
850 | // ORDINAL_POSITION |
851 | "" + (k+1), |
852 | // COLUMN_NAME |
853 | identifier(column.getName()), |
854 | // CARDINALITY |
855 | "0", |
856 | // PRIMARY_KEY |
857 | index.getIndexType().isPrimaryKey() ? |
858 | "TRUE" : "FALSE", |
859 | // INDEX_TYPE_NAME |
860 | index.getIndexType().getSQL(), |
861 | // IS_GENERATED |
862 | index.getIndexType().getBelongsToConstraint() ? |
863 | "TRUE" : "FALSE", |
864 | // INDEX_TYPE |
865 | "" + DatabaseMetaData.tableIndexOther, |
866 | // ASC_OR_DESC |
867 | (idxCol.sortType & SortOrder.DESCENDING) != 0 ? |
868 | "D" : "A", |
869 | // PAGES |
870 | "0", |
871 | // FILTER_CONDITION |
872 | "", |
873 | // REMARKS |
874 | replaceNullWithEmpty(index.getComment()), |
875 | // SQL |
876 | index.getCreateSQL(), |
877 | // ID |
878 | "" + index.getId(), |
879 | // SORT_TYPE |
880 | "" + idxCol.sortType, |
881 | // CONSTRAINT_NAME |
882 | constraintName, |
883 | // INDEX_CLASS |
884 | indexClass |
885 | ); |
886 | } |
887 | } |
888 | } |
889 | break; |
890 | } |
891 | case TABLE_TYPES: { |
892 | add(rows, Table.TABLE); |
893 | add(rows, Table.TABLE_LINK); |
894 | add(rows, Table.SYSTEM_TABLE); |
895 | add(rows, Table.VIEW); |
896 | break; |
897 | } |
898 | case CATALOGS: { |
899 | add(rows, catalog); |
900 | break; |
901 | } |
902 | case SETTINGS: { |
903 | for (Setting s : database.getAllSettings()) { |
904 | String value = s.getStringValue(); |
905 | if (value == null) { |
906 | value = "" + s.getIntValue(); |
907 | } |
908 | add(rows, |
909 | identifier(s.getName()), |
910 | value |
911 | ); |
912 | } |
913 | add(rows, "info.BUILD_ID", "" + Constants.BUILD_ID); |
914 | add(rows, "info.VERSION_MAJOR", "" + Constants.VERSION_MAJOR); |
915 | add(rows, "info.VERSION_MINOR", "" + Constants.VERSION_MINOR); |
916 | add(rows, "info.VERSION", "" + Constants.getFullVersion()); |
917 | if (admin) { |
918 | String[] settings = { |
919 | "java.runtime.version", "java.vm.name", |
920 | "java.vendor", "os.name", "os.arch", "os.version", |
921 | "sun.os.patch.level", "file.separator", |
922 | "path.separator", "line.separator", "user.country", |
923 | "user.language", "user.variant", "file.encoding" }; |
924 | for (String s : settings) { |
925 | add(rows, "property." + s, Utils.getProperty(s, "")); |
926 | } |
927 | } |
928 | add(rows, "EXCLUSIVE", database.getExclusiveSession() == null ? |
929 | "FALSE" : "TRUE"); |
930 | add(rows, "MODE", database.getMode().getName()); |
931 | add(rows, "MULTI_THREADED", database.isMultiThreaded() ? "1" : "0"); |
932 | add(rows, "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE"); |
933 | add(rows, "QUERY_TIMEOUT", "" + session.getQueryTimeout()); |
934 | add(rows, "RETENTION_TIME", "" + database.getRetentionTime()); |
935 | add(rows, "LOG", "" + database.getLogMode()); |
936 | // database settings |
937 | ArrayList<String> settingNames = New.arrayList(); |
938 | HashMap<String, String> s = database.getSettings().getSettings(); |
939 | for (String k : s.keySet()) { |
940 | settingNames.add(k); |
941 | } |
942 | Collections.sort(settingNames); |
943 | for (String k : settingNames) { |
944 | add(rows, k, s.get(k)); |
945 | } |
946 | if (database.isPersistent()) { |
947 | PageStore store = database.getPageStore(); |
948 | if (store != null) { |
949 | add(rows, "info.FILE_WRITE_TOTAL", |
950 | "" + store.getWriteCountTotal()); |
951 | add(rows, "info.FILE_WRITE", |
952 | "" + store.getWriteCount()); |
953 | add(rows, "info.FILE_READ", |
954 | "" + store.getReadCount()); |
955 | add(rows, "info.PAGE_COUNT", |
956 | "" + store.getPageCount()); |
957 | add(rows, "info.PAGE_SIZE", |
958 | "" + store.getPageSize()); |
959 | add(rows, "info.CACHE_MAX_SIZE", |
960 | "" + store.getCache().getMaxMemory()); |
961 | add(rows, "info.CACHE_SIZE", |
962 | "" + store.getCache().getMemory()); |
963 | } |
964 | Store mvStore = database.getMvStore(); |
965 | if (mvStore != null) { |
966 | FileStore fs = mvStore.getStore().getFileStore(); |
967 | add(rows, "info.FILE_WRITE", "" + |
968 | fs.getWriteCount()); |
969 | add(rows, "info.FILE_READ", "" + |
970 | fs.getReadCount()); |
971 | long size; |
972 | try { |
973 | size = fs.getFile().size(); |
974 | } catch (IOException e) { |
975 | throw DbException.convertIOException(e, "Can not get size"); |
976 | } |
977 | int pageSize = 4 * 1024; |
978 | long pageCount = size / pageSize; |
979 | add(rows, "info.PAGE_COUNT", "" + |
980 | pageCount); |
981 | add(rows, "info.PAGE_SIZE", "" + |
982 | pageSize); |
983 | add(rows, "info.CACHE_MAX_SIZE", "" + |
984 | mvStore.getStore().getCacheSize()); |
985 | add(rows, "info.CACHE_SIZE", "" + |
986 | mvStore.getStore().getCacheSizeUsed()); |
987 | } |
988 | } |
989 | break; |
990 | } |
991 | case TYPE_INFO: { |
992 | for (DataType t : DataType.getTypes()) { |
993 | if (t.hidden || t.sqlType == Value.NULL) { |
994 | continue; |
995 | } |
996 | add(rows, |
997 | // TYPE_NAME |
998 | t.name, |
999 | // DATA_TYPE |
1000 | String.valueOf(t.sqlType), |
1001 | // PRECISION |
1002 | String.valueOf(MathUtils.convertLongToInt(t.maxPrecision)), |
1003 | // PREFIX |
1004 | t.prefix, |
1005 | // SUFFIX |
1006 | t.suffix, |
1007 | // PARAMS |
1008 | t.params, |
1009 | // AUTO_INCREMENT |
1010 | String.valueOf(t.autoIncrement), |
1011 | // MINIMUM_SCALE |
1012 | String.valueOf(t.minScale), |
1013 | // MAXIMUM_SCALE |
1014 | String.valueOf(t.maxScale), |
1015 | // RADIX |
1016 | t.decimal ? "10" : null, |
1017 | // POS |
1018 | String.valueOf(t.sqlTypePos), |
1019 | // CASE_SENSITIVE |
1020 | String.valueOf(t.caseSensitive), |
1021 | // NULLABLE |
1022 | "" + DatabaseMetaData.typeNullable, |
1023 | // SEARCHABLE |
1024 | "" + DatabaseMetaData.typeSearchable |
1025 | ); |
1026 | } |
1027 | break; |
1028 | } |
1029 | case HELP: { |
1030 | String resource = "/org/h2/res/help.csv"; |
1031 | try { |
1032 | byte[] data = Utils.getResource(resource); |
1033 | Reader reader = new InputStreamReader( |
1034 | new ByteArrayInputStream(data)); |
1035 | Csv csv = new Csv(); |
1036 | csv.setLineCommentCharacter('#'); |
1037 | ResultSet rs = csv.read(reader, null); |
1038 | for (int i = 0; rs.next(); i++) { |
1039 | add(rows, |
1040 | // ID |
1041 | String.valueOf(i), |
1042 | // SECTION |
1043 | rs.getString(1).trim(), |
1044 | // TOPIC |
1045 | rs.getString(2).trim(), |
1046 | // SYNTAX |
1047 | rs.getString(3).trim(), |
1048 | // TEXT |
1049 | rs.getString(4).trim() |
1050 | ); |
1051 | } |
1052 | } catch (Exception e) { |
1053 | throw DbException.convert(e); |
1054 | } |
1055 | break; |
1056 | } |
1057 | case SEQUENCES: { |
1058 | for (SchemaObject obj : database.getAllSchemaObjects( |
1059 | DbObject.SEQUENCE)) { |
1060 | Sequence s = (Sequence) obj; |
1061 | add(rows, |
1062 | // SEQUENCE_CATALOG |
1063 | catalog, |
1064 | // SEQUENCE_SCHEMA |
1065 | identifier(s.getSchema().getName()), |
1066 | // SEQUENCE_NAME |
1067 | identifier(s.getName()), |
1068 | // CURRENT_VALUE |
1069 | String.valueOf(s.getCurrentValue()), |
1070 | // INCREMENT |
1071 | String.valueOf(s.getIncrement()), |
1072 | // IS_GENERATED |
1073 | s.getBelongsToTable() ? "TRUE" : "FALSE", |
1074 | // REMARKS |
1075 | replaceNullWithEmpty(s.getComment()), |
1076 | // CACHE |
1077 | String.valueOf(s.getCacheSize()), |
1078 | // MIN_VALUE |
1079 | String.valueOf(s.getMinValue()), |
1080 | // MAX_VALUE |
1081 | String.valueOf(s.getMaxValue()), |
1082 | // IS_CYCLE |
1083 | s.getCycle() ? "TRUE" : "FALSE", |
1084 | // ID |
1085 | "" + s.getId() |
1086 | ); |
1087 | } |
1088 | break; |
1089 | } |
1090 | case USERS: { |
1091 | for (User u : database.getAllUsers()) { |
1092 | if (admin || session.getUser() == u) { |
1093 | add(rows, |
1094 | // NAME |
1095 | identifier(u.getName()), |
1096 | // ADMIN |
1097 | String.valueOf(u.isAdmin()), |
1098 | // REMARKS |
1099 | replaceNullWithEmpty(u.getComment()), |
1100 | // ID |
1101 | "" + u.getId() |
1102 | ); |
1103 | } |
1104 | } |
1105 | break; |
1106 | } |
1107 | case ROLES: { |
1108 | for (Role r : database.getAllRoles()) { |
1109 | if (admin || session.getUser().isRoleGranted(r)) { |
1110 | add(rows, |
1111 | // NAME |
1112 | identifier(r.getName()), |
1113 | // REMARKS |
1114 | replaceNullWithEmpty(r.getComment()), |
1115 | // ID |
1116 | "" + r.getId() |
1117 | ); |
1118 | } |
1119 | } |
1120 | break; |
1121 | } |
1122 | case RIGHTS: { |
1123 | if (admin) { |
1124 | for (Right r : database.getAllRights()) { |
1125 | Role role = r.getGrantedRole(); |
1126 | DbObject grantee = r.getGrantee(); |
1127 | String rightType = grantee.getType() == DbObject.USER ? |
1128 | "USER" : "ROLE"; |
1129 | if (role == null) { |
1130 | Table granted = r.getGrantedTable(); |
1131 | String tableName = identifier(granted.getName()); |
1132 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1133 | continue; |
1134 | } |
1135 | add(rows, |
1136 | // GRANTEE |
1137 | identifier(grantee.getName()), |
1138 | // GRANTEETYPE |
1139 | rightType, |
1140 | // GRANTEDROLE |
1141 | "", |
1142 | // RIGHTS |
1143 | r.getRights(), |
1144 | // TABLE_SCHEMA |
1145 | identifier(granted.getSchema().getName()), |
1146 | // TABLE_NAME |
1147 | identifier(granted.getName()), |
1148 | // ID |
1149 | "" + r.getId() |
1150 | ); |
1151 | } else { |
1152 | add(rows, |
1153 | // GRANTEE |
1154 | identifier(grantee.getName()), |
1155 | // GRANTEETYPE |
1156 | rightType, |
1157 | // GRANTEDROLE |
1158 | identifier(role.getName()), |
1159 | // RIGHTS |
1160 | "", |
1161 | // TABLE_SCHEMA |
1162 | "", |
1163 | // TABLE_NAME |
1164 | "", |
1165 | // ID |
1166 | "" + r.getId() |
1167 | ); |
1168 | } |
1169 | } |
1170 | } |
1171 | break; |
1172 | } |
1173 | case FUNCTION_ALIASES: { |
1174 | for (SchemaObject aliasAsSchemaObject : |
1175 | database.getAllSchemaObjects(DbObject.FUNCTION_ALIAS)) { |
1176 | FunctionAlias alias = (FunctionAlias) aliasAsSchemaObject; |
1177 | JavaMethod[] methods; |
1178 | try { |
1179 | methods = alias.getJavaMethods(); |
1180 | } catch (DbException e) { |
1181 | methods = new JavaMethod[0]; |
1182 | } |
1183 | for (FunctionAlias.JavaMethod method : methods) { |
1184 | int returnsResult = method.getDataType() == Value.NULL ? |
1185 | DatabaseMetaData.procedureNoResult : |
1186 | DatabaseMetaData.procedureReturnsResult; |
1187 | add(rows, |
1188 | // ALIAS_CATALOG |
1189 | catalog, |
1190 | // ALIAS_SCHEMA |
1191 | alias.getSchema().getName(), |
1192 | // ALIAS_NAME |
1193 | identifier(alias.getName()), |
1194 | // JAVA_CLASS |
1195 | alias.getJavaClassName(), |
1196 | // JAVA_METHOD |
1197 | alias.getJavaMethodName(), |
1198 | // DATA_TYPE |
1199 | "" + DataType.convertTypeToSQLType(method.getDataType()), |
1200 | // TYPE_NAME |
1201 | DataType.getDataType(method.getDataType()).name, |
1202 | // COLUMN_COUNT INT |
1203 | "" + method.getParameterCount(), |
1204 | // RETURNS_RESULT SMALLINT |
1205 | "" + returnsResult, |
1206 | // REMARKS |
1207 | replaceNullWithEmpty(alias.getComment()), |
1208 | // ID |
1209 | "" + alias.getId(), |
1210 | // SOURCE |
1211 | alias.getSource() |
1212 | // when adding more columns, see also below |
1213 | ); |
1214 | } |
1215 | } |
1216 | for (UserAggregate agg : database.getAllAggregates()) { |
1217 | int returnsResult = DatabaseMetaData.procedureReturnsResult; |
1218 | add(rows, |
1219 | // ALIAS_CATALOG |
1220 | catalog, |
1221 | // ALIAS_SCHEMA |
1222 | Constants.SCHEMA_MAIN, |
1223 | // ALIAS_NAME |
1224 | identifier(agg.getName()), |
1225 | // JAVA_CLASS |
1226 | agg.getJavaClassName(), |
1227 | // JAVA_METHOD |
1228 | "", |
1229 | // DATA_TYPE |
1230 | "" + DataType.convertTypeToSQLType(Value.NULL), |
1231 | // TYPE_NAME |
1232 | DataType.getDataType(Value.NULL).name, |
1233 | // COLUMN_COUNT INT |
1234 | "1", |
1235 | // RETURNS_RESULT SMALLINT |
1236 | "" + returnsResult, |
1237 | // REMARKS |
1238 | replaceNullWithEmpty(agg.getComment()), |
1239 | // ID |
1240 | "" + agg.getId(), |
1241 | // SOURCE |
1242 | "" |
1243 | // when adding more columns, see also below |
1244 | ); |
1245 | } |
1246 | break; |
1247 | } |
1248 | case FUNCTION_COLUMNS: { |
1249 | for (SchemaObject aliasAsSchemaObject : |
1250 | database.getAllSchemaObjects(DbObject.FUNCTION_ALIAS)) { |
1251 | FunctionAlias alias = (FunctionAlias) aliasAsSchemaObject; |
1252 | JavaMethod[] methods; |
1253 | try { |
1254 | methods = alias.getJavaMethods(); |
1255 | } catch (DbException e) { |
1256 | methods = new JavaMethod[0]; |
1257 | } |
1258 | for (FunctionAlias.JavaMethod method : methods) { |
1259 | // Add return column index 0 |
1260 | if (method.getDataType() != Value.NULL) { |
1261 | DataType dt = DataType.getDataType(method.getDataType()); |
1262 | add(rows, |
1263 | // ALIAS_CATALOG |
1264 | catalog, |
1265 | // ALIAS_SCHEMA |
1266 | alias.getSchema().getName(), |
1267 | // ALIAS_NAME |
1268 | identifier(alias.getName()), |
1269 | // JAVA_CLASS |
1270 | alias.getJavaClassName(), |
1271 | // JAVA_METHOD |
1272 | alias.getJavaMethodName(), |
1273 | // COLUMN_COUNT |
1274 | "" + method.getParameterCount(), |
1275 | // POS INT |
1276 | "0", |
1277 | // COLUMN_NAME |
1278 | "P0", |
1279 | // DATA_TYPE |
1280 | "" + DataType.convertTypeToSQLType(method.getDataType()), |
1281 | // TYPE_NAME |
1282 | dt.name, |
1283 | // PRECISION INT |
1284 | "" + MathUtils.convertLongToInt(dt.defaultPrecision), |
1285 | // SCALE |
1286 | "" + dt.defaultScale, |
1287 | // RADIX |
1288 | "10", |
1289 | // NULLABLE SMALLINT |
1290 | "" + DatabaseMetaData.columnNullableUnknown, |
1291 | // COLUMN_TYPE |
1292 | "" + DatabaseMetaData.procedureColumnReturn, |
1293 | // REMARKS |
1294 | "", |
1295 | // COLUMN_DEFAULT |
1296 | null |
1297 | ); |
1298 | } |
1299 | Class<?>[] columnList = method.getColumnClasses(); |
1300 | for (int k = 0; k < columnList.length; k++) { |
1301 | if (method.hasConnectionParam() && k == 0) { |
1302 | continue; |
1303 | } |
1304 | Class<?> clazz = columnList[k]; |
1305 | int dataType = DataType.getTypeFromClass(clazz); |
1306 | DataType dt = DataType.getDataType(dataType); |
1307 | int nullable = clazz.isPrimitive() ? DatabaseMetaData.columnNoNulls |
1308 | : DatabaseMetaData.columnNullable; |
1309 | add(rows, |
1310 | // ALIAS_CATALOG |
1311 | catalog, |
1312 | // ALIAS_SCHEMA |
1313 | alias.getSchema().getName(), |
1314 | // ALIAS_NAME |
1315 | identifier(alias.getName()), |
1316 | // JAVA_CLASS |
1317 | alias.getJavaClassName(), |
1318 | // JAVA_METHOD |
1319 | alias.getJavaMethodName(), |
1320 | // COLUMN_COUNT |
1321 | "" + method.getParameterCount(), |
1322 | // POS INT |
1323 | "" + (k + (method.hasConnectionParam() ? 0 : 1)), |
1324 | // COLUMN_NAME |
1325 | "P" + (k + 1), |
1326 | // DATA_TYPE |
1327 | "" + DataType.convertTypeToSQLType(dt.type), |
1328 | // TYPE_NAME |
1329 | dt.name, |
1330 | // PRECISION INT |
1331 | "" + MathUtils.convertLongToInt(dt.defaultPrecision), |
1332 | // SCALE |
1333 | "" + dt.defaultScale, |
1334 | // RADIX |
1335 | "10", |
1336 | // NULLABLE SMALLINT |
1337 | "" + nullable, |
1338 | // COLUMN_TYPE |
1339 | "" + DatabaseMetaData.procedureColumnIn, |
1340 | // REMARKS |
1341 | "", |
1342 | // COLUMN_DEFAULT |
1343 | null |
1344 | ); |
1345 | } |
1346 | } |
1347 | } |
1348 | break; |
1349 | } |
1350 | case SCHEMATA: { |
1351 | String collation = database.getCompareMode().getName(); |
1352 | for (Schema schema : database.getAllSchemas()) { |
1353 | add(rows, |
1354 | // CATALOG_NAME |
1355 | catalog, |
1356 | // SCHEMA_NAME |
1357 | identifier(schema.getName()), |
1358 | // SCHEMA_OWNER |
1359 | identifier(schema.getOwner().getName()), |
1360 | // DEFAULT_CHARACTER_SET_NAME |
1361 | CHARACTER_SET_NAME, |
1362 | // DEFAULT_COLLATION_NAME |
1363 | collation, |
1364 | // IS_DEFAULT |
1365 | Constants.SCHEMA_MAIN.equals( |
1366 | schema.getName()) ? "TRUE" : "FALSE", |
1367 | // REMARKS |
1368 | replaceNullWithEmpty(schema.getComment()), |
1369 | // ID |
1370 | "" + schema.getId() |
1371 | ); |
1372 | } |
1373 | break; |
1374 | } |
1375 | case TABLE_PRIVILEGES: { |
1376 | for (Right r : database.getAllRights()) { |
1377 | Table table = r.getGrantedTable(); |
1378 | if (table == null || hideTable(table, session)) { |
1379 | continue; |
1380 | } |
1381 | String tableName = identifier(table.getName()); |
1382 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1383 | continue; |
1384 | } |
1385 | addPrivileges(rows, r.getGrantee(), catalog, table, null, |
1386 | r.getRightMask()); |
1387 | } |
1388 | break; |
1389 | } |
1390 | case COLUMN_PRIVILEGES: { |
1391 | for (Right r : database.getAllRights()) { |
1392 | Table table = r.getGrantedTable(); |
1393 | if (table == null || hideTable(table, session)) { |
1394 | continue; |
1395 | } |
1396 | String tableName = identifier(table.getName()); |
1397 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1398 | continue; |
1399 | } |
1400 | DbObject grantee = r.getGrantee(); |
1401 | int mask = r.getRightMask(); |
1402 | for (Column column : table.getColumns()) { |
1403 | addPrivileges(rows, grantee, catalog, table, |
1404 | column.getName(), mask); |
1405 | } |
1406 | } |
1407 | break; |
1408 | } |
1409 | case COLLATIONS: { |
1410 | for (Locale l : Collator.getAvailableLocales()) { |
1411 | add(rows, |
1412 | // NAME |
1413 | CompareMode.getName(l), |
1414 | // KEY |
1415 | l.toString() |
1416 | ); |
1417 | } |
1418 | break; |
1419 | } |
1420 | case VIEWS: { |
1421 | for (Table table : getAllTables(session)) { |
1422 | if (!table.getTableType().equals(Table.VIEW)) { |
1423 | continue; |
1424 | } |
1425 | String tableName = identifier(table.getName()); |
1426 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1427 | continue; |
1428 | } |
1429 | TableView view = (TableView) table; |
1430 | add(rows, |
1431 | // TABLE_CATALOG |
1432 | catalog, |
1433 | // TABLE_SCHEMA |
1434 | identifier(table.getSchema().getName()), |
1435 | // TABLE_NAME |
1436 | tableName, |
1437 | // VIEW_DEFINITION |
1438 | table.getCreateSQL(), |
1439 | // CHECK_OPTION |
1440 | "NONE", |
1441 | // IS_UPDATABLE |
1442 | "NO", |
1443 | // STATUS |
1444 | view.isInvalid() ? "INVALID" : "VALID", |
1445 | // REMARKS |
1446 | replaceNullWithEmpty(view.getComment()), |
1447 | // ID |
1448 | "" + view.getId() |
1449 | ); |
1450 | } |
1451 | break; |
1452 | } |
1453 | case IN_DOUBT: { |
1454 | ArrayList<InDoubtTransaction> prepared = database.getInDoubtTransactions(); |
1455 | if (prepared != null && admin) { |
1456 | for (InDoubtTransaction prep : prepared) { |
1457 | add(rows, |
1458 | // TRANSACTION |
1459 | prep.getTransactionName(), |
1460 | // STATE |
1461 | prep.getState() |
1462 | ); |
1463 | } |
1464 | } |
1465 | break; |
1466 | } |
1467 | case CROSS_REFERENCES: { |
1468 | for (SchemaObject obj : database.getAllSchemaObjects( |
1469 | DbObject.CONSTRAINT)) { |
1470 | Constraint constraint = (Constraint) obj; |
1471 | if (!(constraint.getConstraintType().equals(Constraint.REFERENTIAL))) { |
1472 | continue; |
1473 | } |
1474 | ConstraintReferential ref = (ConstraintReferential) constraint; |
1475 | IndexColumn[] cols = ref.getColumns(); |
1476 | IndexColumn[] refCols = ref.getRefColumns(); |
1477 | Table tab = ref.getTable(); |
1478 | Table refTab = ref.getRefTable(); |
1479 | String tableName = identifier(refTab.getName()); |
1480 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1481 | continue; |
1482 | } |
1483 | int update = getRefAction(ref.getUpdateAction()); |
1484 | int delete = getRefAction(ref.getDeleteAction()); |
1485 | for (int j = 0; j < cols.length; j++) { |
1486 | add(rows, |
1487 | // PKTABLE_CATALOG |
1488 | catalog, |
1489 | // PKTABLE_SCHEMA |
1490 | identifier(refTab.getSchema().getName()), |
1491 | // PKTABLE_NAME |
1492 | identifier(refTab.getName()), |
1493 | // PKCOLUMN_NAME |
1494 | identifier(refCols[j].column.getName()), |
1495 | // FKTABLE_CATALOG |
1496 | catalog, |
1497 | // FKTABLE_SCHEMA |
1498 | identifier(tab.getSchema().getName()), |
1499 | // FKTABLE_NAME |
1500 | identifier(tab.getName()), |
1501 | // FKCOLUMN_NAME |
1502 | identifier(cols[j].column.getName()), |
1503 | // ORDINAL_POSITION |
1504 | String.valueOf(j + 1), |
1505 | // UPDATE_RULE SMALLINT |
1506 | String.valueOf(update), |
1507 | // DELETE_RULE SMALLINT |
1508 | String.valueOf(delete), |
1509 | // FK_NAME |
1510 | identifier(ref.getName()), |
1511 | // PK_NAME |
1512 | identifier(ref.getUniqueIndex().getName()), |
1513 | // DEFERRABILITY |
1514 | "" + DatabaseMetaData.importedKeyNotDeferrable |
1515 | ); |
1516 | } |
1517 | } |
1518 | break; |
1519 | } |
1520 | case CONSTRAINTS: { |
1521 | for (SchemaObject obj : database.getAllSchemaObjects( |
1522 | DbObject.CONSTRAINT)) { |
1523 | Constraint constraint = (Constraint) obj; |
1524 | String constraintType = constraint.getConstraintType(); |
1525 | String checkExpression = null; |
1526 | IndexColumn[] indexColumns = null; |
1527 | Table table = constraint.getTable(); |
1528 | if (hideTable(table, session)) { |
1529 | continue; |
1530 | } |
1531 | Index index = constraint.getUniqueIndex(); |
1532 | String uniqueIndexName = null; |
1533 | if (index != null) { |
1534 | uniqueIndexName = index.getName(); |
1535 | } |
1536 | String tableName = identifier(table.getName()); |
1537 | if (!checkIndex(session, tableName, indexFrom, indexTo)) { |
1538 | continue; |
1539 | } |
1540 | if (constraintType.equals(Constraint.CHECK)) { |
1541 | checkExpression = ((ConstraintCheck) constraint).getExpression().getSQL(); |
1542 | } else if (constraintType.equals(Constraint.UNIQUE) || |
1543 | constraintType.equals(Constraint.PRIMARY_KEY)) { |
1544 | indexColumns = ((ConstraintUnique) constraint).getColumns(); |
1545 | } else if (constraintType.equals(Constraint.REFERENTIAL)) { |
1546 | indexColumns = ((ConstraintReferential) constraint).getColumns(); |
1547 | } |
1548 | String columnList = null; |
1549 | if (indexColumns != null) { |
1550 | StatementBuilder buff = new StatementBuilder(); |
1551 | for (IndexColumn col : indexColumns) { |
1552 | buff.appendExceptFirst(","); |
1553 | buff.append(col.column.getName()); |
1554 | } |
1555 | columnList = buff.toString(); |
1556 | } |
1557 | add(rows, |
1558 | // CONSTRAINT_CATALOG |
1559 | catalog, |
1560 | // CONSTRAINT_SCHEMA |
1561 | identifier(constraint.getSchema().getName()), |
1562 | // CONSTRAINT_NAME |
1563 | identifier(constraint.getName()), |
1564 | // CONSTRAINT_TYPE |
1565 | constraintType, |
1566 | // TABLE_CATALOG |
1567 | catalog, |
1568 | // TABLE_SCHEMA |
1569 | identifier(table.getSchema().getName()), |
1570 | // TABLE_NAME |
1571 | tableName, |
1572 | // UNIQUE_INDEX_NAME |
1573 | uniqueIndexName, |
1574 | // CHECK_EXPRESSION |
1575 | checkExpression, |
1576 | // COLUMN_LIST |
1577 | columnList, |
1578 | // REMARKS |
1579 | replaceNullWithEmpty(constraint.getComment()), |
1580 | // SQL |
1581 | constraint.getCreateSQL(), |
1582 | // ID |
1583 | "" + constraint.getId() |
1584 | ); |
1585 | } |
1586 | break; |
1587 | } |
1588 | case CONSTANTS: { |
1589 | for (SchemaObject obj : database.getAllSchemaObjects( |
1590 | DbObject.CONSTANT)) { |
1591 | Constant constant = (Constant) obj; |
1592 | ValueExpression expr = constant.getValue(); |
1593 | add(rows, |
1594 | // CONSTANT_CATALOG |
1595 | catalog, |
1596 | // CONSTANT_SCHEMA |
1597 | identifier(constant.getSchema().getName()), |
1598 | // CONSTANT_NAME |
1599 | identifier(constant.getName()), |
1600 | // CONSTANT_TYPE |
1601 | "" + DataType.convertTypeToSQLType(expr.getType()), |
1602 | // REMARKS |
1603 | replaceNullWithEmpty(constant.getComment()), |
1604 | // SQL |
1605 | expr.getSQL(), |
1606 | // ID |
1607 | "" + constant.getId() |
1608 | ); |
1609 | } |
1610 | break; |
1611 | } |
1612 | case DOMAINS: { |
1613 | for (UserDataType dt : database.getAllUserDataTypes()) { |
1614 | Column col = dt.getColumn(); |
1615 | add(rows, |
1616 | // DOMAIN_CATALOG |
1617 | catalog, |
1618 | // DOMAIN_SCHEMA |
1619 | Constants.SCHEMA_MAIN, |
1620 | // DOMAIN_NAME |
1621 | identifier(dt.getName()), |
1622 | // COLUMN_DEFAULT |
1623 | col.getDefaultSQL(), |
1624 | // IS_NULLABLE |
1625 | col.isNullable() ? "YES" : "NO", |
1626 | // DATA_TYPE |
1627 | "" + col.getDataType().sqlType, |
1628 | // PRECISION INT |
1629 | "" + col.getPrecisionAsInt(), |
1630 | // SCALE INT |
1631 | "" + col.getScale(), |
1632 | // TYPE_NAME |
1633 | col.getDataType().name, |
1634 | // SELECTIVITY INT |
1635 | "" + col.getSelectivity(), |
1636 | // CHECK_CONSTRAINT |
1637 | "" + col.getCheckConstraintSQL(session, "VALUE"), |
1638 | // REMARKS |
1639 | replaceNullWithEmpty(dt.getComment()), |
1640 | // SQL |
1641 | "" + dt.getCreateSQL(), |
1642 | // ID |
1643 | "" + dt.getId() |
1644 | ); |
1645 | } |
1646 | break; |
1647 | } |
1648 | case TRIGGERS: { |
1649 | for (SchemaObject obj : database.getAllSchemaObjects( |
1650 | DbObject.TRIGGER)) { |
1651 | TriggerObject trigger = (TriggerObject) obj; |
1652 | Table table = trigger.getTable(); |
1653 | add(rows, |
1654 | // TRIGGER_CATALOG |
1655 | catalog, |
1656 | // TRIGGER_SCHEMA |
1657 | identifier(trigger.getSchema().getName()), |
1658 | // TRIGGER_NAME |
1659 | identifier(trigger.getName()), |
1660 | // TRIGGER_TYPE |
1661 | trigger.getTypeNameList(), |
1662 | // TABLE_CATALOG |
1663 | catalog, |
1664 | // TABLE_SCHEMA |
1665 | identifier(table.getSchema().getName()), |
1666 | // TABLE_NAME |
1667 | identifier(table.getName()), |
1668 | // BEFORE BIT |
1669 | "" + trigger.isBefore(), |
1670 | // JAVA_CLASS |
1671 | trigger.getTriggerClassName(), |
1672 | // QUEUE_SIZE INT |
1673 | "" + trigger.getQueueSize(), |
1674 | // NO_WAIT BIT |
1675 | "" + trigger.isNoWait(), |
1676 | // REMARKS |
1677 | replaceNullWithEmpty(trigger.getComment()), |
1678 | // SQL |
1679 | trigger.getCreateSQL(), |
1680 | // ID |
1681 | "" + trigger.getId() |
1682 | ); |
1683 | } |
1684 | break; |
1685 | } |
1686 | case SESSIONS: { |
1687 | long now = System.currentTimeMillis(); |
1688 | for (Session s : database.getSessions(false)) { |
1689 | if (admin || s == session) { |
1690 | Command command = s.getCurrentCommand(); |
1691 | long start = s.getCurrentCommandStart(); |
1692 | if (start == 0) { |
1693 | start = now; |
1694 | } |
1695 | add(rows, |
1696 | // ID |
1697 | "" + s.getId(), |
1698 | // USER_NAME |
1699 | s.getUser().getName(), |
1700 | // SESSION_START |
1701 | new Timestamp(s.getSessionStart()).toString(), |
1702 | // STATEMENT |
1703 | command == null ? null : command.toString(), |
1704 | // STATEMENT_START |
1705 | new Timestamp(start).toString(), |
1706 | // CONTAINS_UNCOMMITTED |
1707 | "" + s.containsUncommitted() |
1708 | ); |
1709 | } |
1710 | } |
1711 | break; |
1712 | } |
1713 | case LOCKS: { |
1714 | for (Session s : database.getSessions(false)) { |
1715 | if (admin || s == session) { |
1716 | for (Table table : s.getLocks()) { |
1717 | add(rows, |
1718 | // TABLE_SCHEMA |
1719 | table.getSchema().getName(), |
1720 | // TABLE_NAME |
1721 | table.getName(), |
1722 | // SESSION_ID |
1723 | "" + s.getId(), |
1724 | // LOCK_TYPE |
1725 | table.isLockedExclusivelyBy(s) ? "WRITE" : "READ" |
1726 | ); |
1727 | } |
1728 | } |
1729 | } |
1730 | break; |
1731 | } |
1732 | case SESSION_STATE: { |
1733 | for (String name : session.getVariableNames()) { |
1734 | Value v = session.getVariable(name); |
1735 | add(rows, |
1736 | // KEY |
1737 | "@" + name, |
1738 | // SQL |
1739 | "SET @" + name + " " + v.getSQL() |
1740 | ); |
1741 | } |
1742 | for (Table table : session.getLocalTempTables()) { |
1743 | add(rows, |
1744 | // KEY |
1745 | "TABLE " + table.getName(), |
1746 | // SQL |
1747 | table.getCreateSQL() |
1748 | ); |
1749 | } |
1750 | String[] path = session.getSchemaSearchPath(); |
1751 | if (path != null && path.length > 0) { |
1752 | StatementBuilder buff = new StatementBuilder( |
1753 | "SET SCHEMA_SEARCH_PATH "); |
1754 | for (String p : path) { |
1755 | buff.appendExceptFirst(", "); |
1756 | buff.append(StringUtils.quoteIdentifier(p)); |
1757 | } |
1758 | add(rows, |
1759 | // KEY |
1760 | "SCHEMA_SEARCH_PATH", |
1761 | // SQL |
1762 | buff.toString() |
1763 | ); |
1764 | } |
1765 | String schema = session.getCurrentSchemaName(); |
1766 | if (schema != null) { |
1767 | add(rows, |
1768 | // KEY |
1769 | "SCHEMA", |
1770 | // SQL |
1771 | "SET SCHEMA " + StringUtils.quoteIdentifier(schema) |
1772 | ); |
1773 | } |
1774 | break; |
1775 | } |
1776 | case QUERY_STATISTICS: { |
1777 | QueryStatisticsData control = database.getQueryStatisticsData(); |
1778 | if (control != null) { |
1779 | for (QueryStatisticsData.QueryEntry entry : control.getQueries()) { |
1780 | add(rows, |
1781 | // SQL_STATEMENT |
1782 | entry.sqlStatement, |
1783 | // EXECUTION_COUNT |
1784 | "" + entry.count, |
1785 | // MIN_EXECUTION_TIME |
1786 | "" + entry.executionTimeMin, |
1787 | // MAX_EXECUTION_TIME |
1788 | "" + entry.executionTimeMax, |
1789 | // CUMULATIVE_EXECUTION_TIME |
1790 | "" + entry.executionTimeCumulative, |
1791 | // AVERAGE_EXECUTION_TIME |
1792 | "" + entry.executionTimeMean, |
1793 | // STD_DEV_EXECUTION_TIME |
1794 | "" + entry.getExecutionTimeStandardDeviation(), |
1795 | // MIN_ROW_COUNT |
1796 | "" + entry.rowCountMin, |
1797 | // MAX_ROW_COUNT |
1798 | "" + entry.rowCountMax, |
1799 | // CUMULATIVE_ROW_COUNT |
1800 | "" + entry.rowCountCumulative, |
1801 | // AVERAGE_ROW_COUNT |
1802 | "" + entry.rowCountMean, |
1803 | // STD_DEV_ROW_COUNT |
1804 | "" + entry.getRowCountStandardDeviation() |
1805 | ); |
1806 | } |
1807 | } |
1808 | break; |
1809 | } |
1810 | default: |
1811 | DbException.throwInternalError("type="+type); |
1812 | } |
1813 | return rows; |
1814 | } |
1815 | |
1816 | private static int getRefAction(int action) { |
1817 | switch(action) { |
1818 | case ConstraintReferential.CASCADE: |
1819 | return DatabaseMetaData.importedKeyCascade; |
1820 | case ConstraintReferential.RESTRICT: |
1821 | return DatabaseMetaData.importedKeyRestrict; |
1822 | case ConstraintReferential.SET_DEFAULT: |
1823 | return DatabaseMetaData.importedKeySetDefault; |
1824 | case ConstraintReferential.SET_NULL: |
1825 | return DatabaseMetaData.importedKeySetNull; |
1826 | default: |
1827 | throw DbException.throwInternalError("action="+action); |
1828 | } |
1829 | } |
1830 | |
1831 | @Override |
1832 | public void removeRow(Session session, Row row) { |
1833 | throw DbException.getUnsupportedException("META"); |
1834 | } |
1835 | |
1836 | @Override |
1837 | public void addRow(Session session, Row row) { |
1838 | throw DbException.getUnsupportedException("META"); |
1839 | } |
1840 | |
1841 | @Override |
1842 | public void removeChildrenAndResources(Session session) { |
1843 | throw DbException.getUnsupportedException("META"); |
1844 | } |
1845 | |
1846 | @Override |
1847 | public void close(Session session) { |
1848 | // nothing to do |
1849 | } |
1850 | |
1851 | @Override |
1852 | public void unlock(Session s) { |
1853 | // nothing to do |
1854 | } |
1855 | |
1856 | private void addPrivileges(ArrayList<Row> rows, DbObject grantee, |
1857 | String catalog, Table table, String column, int rightMask) { |
1858 | if ((rightMask & Right.SELECT) != 0) { |
1859 | addPrivilege(rows, grantee, catalog, table, column, "SELECT"); |
1860 | } |
1861 | if ((rightMask & Right.INSERT) != 0) { |
1862 | addPrivilege(rows, grantee, catalog, table, column, "INSERT"); |
1863 | } |
1864 | if ((rightMask & Right.UPDATE) != 0) { |
1865 | addPrivilege(rows, grantee, catalog, table, column, "UPDATE"); |
1866 | } |
1867 | if ((rightMask & Right.DELETE) != 0) { |
1868 | addPrivilege(rows, grantee, catalog, table, column, "DELETE"); |
1869 | } |
1870 | } |
1871 | |
1872 | private void addPrivilege(ArrayList<Row> rows, DbObject grantee, |
1873 | String catalog, Table table, String column, String right) { |
1874 | String isGrantable = "NO"; |
1875 | if (grantee.getType() == DbObject.USER) { |
1876 | User user = (User) grantee; |
1877 | if (user.isAdmin()) { |
1878 | // the right is grantable if the grantee is an admin |
1879 | isGrantable = "YES"; |
1880 | } |
1881 | } |
1882 | if (column == null) { |
1883 | add(rows, |
1884 | // GRANTOR |
1885 | null, |
1886 | // GRANTEE |
1887 | identifier(grantee.getName()), |
1888 | // TABLE_CATALOG |
1889 | catalog, |
1890 | // TABLE_SCHEMA |
1891 | identifier(table.getSchema().getName()), |
1892 | // TABLE_NAME |
1893 | identifier(table.getName()), |
1894 | // PRIVILEGE_TYPE |
1895 | right, |
1896 | // IS_GRANTABLE |
1897 | isGrantable |
1898 | ); |
1899 | } else { |
1900 | add(rows, |
1901 | // GRANTOR |
1902 | null, |
1903 | // GRANTEE |
1904 | identifier(grantee.getName()), |
1905 | // TABLE_CATALOG |
1906 | catalog, |
1907 | // TABLE_SCHEMA |
1908 | identifier(table.getSchema().getName()), |
1909 | // TABLE_NAME |
1910 | identifier(table.getName()), |
1911 | // COLUMN_NAME |
1912 | identifier(column), |
1913 | // PRIVILEGE_TYPE |
1914 | right, |
1915 | // IS_GRANTABLE |
1916 | isGrantable |
1917 | ); |
1918 | } |
1919 | } |
1920 | |
1921 | private void add(ArrayList<Row> rows, String... strings) { |
1922 | Value[] values = new Value[strings.length]; |
1923 | for (int i = 0; i < strings.length; i++) { |
1924 | String s = strings[i]; |
1925 | Value v = (s == null) ? (Value) ValueNull.INSTANCE : ValueString.get(s); |
1926 | Column col = columns[i]; |
1927 | v = col.convert(v); |
1928 | values[i] = v; |
1929 | } |
1930 | Row row = new Row(values, 1); |
1931 | row.setKey(rows.size()); |
1932 | rows.add(row); |
1933 | } |
1934 | |
1935 | @Override |
1936 | public void checkRename() { |
1937 | throw DbException.getUnsupportedException("META"); |
1938 | } |
1939 | |
1940 | @Override |
1941 | public void checkSupportAlter() { |
1942 | throw DbException.getUnsupportedException("META"); |
1943 | } |
1944 | |
1945 | @Override |
1946 | public void truncate(Session session) { |
1947 | throw DbException.getUnsupportedException("META"); |
1948 | } |
1949 | |
1950 | @Override |
1951 | public long getRowCount(Session session) { |
1952 | throw DbException.throwInternalError(); |
1953 | } |
1954 | |
1955 | @Override |
1956 | public boolean canGetRowCount() { |
1957 | return false; |
1958 | } |
1959 | |
1960 | @Override |
1961 | public boolean canDrop() { |
1962 | return false; |
1963 | } |
1964 | |
1965 | @Override |
1966 | public String getTableType() { |
1967 | return Table.SYSTEM_TABLE; |
1968 | } |
1969 | |
1970 | @Override |
1971 | public Index getScanIndex(Session session) { |
1972 | return new MetaIndex(this, IndexColumn.wrap(columns), true); |
1973 | } |
1974 | |
1975 | @Override |
1976 | public ArrayList<Index> getIndexes() { |
1977 | ArrayList<Index> list = New.arrayList(); |
1978 | if (metaIndex == null) { |
1979 | return list; |
1980 | } |
1981 | list.add(new MetaIndex(this, IndexColumn.wrap(columns), true)); |
1982 | // TODO re-use the index |
1983 | list.add(metaIndex); |
1984 | return list; |
1985 | } |
1986 | |
1987 | @Override |
1988 | public long getMaxDataModificationId() { |
1989 | switch (type) { |
1990 | case SETTINGS: |
1991 | case IN_DOUBT: |
1992 | case SESSIONS: |
1993 | case LOCKS: |
1994 | case SESSION_STATE: |
1995 | return Long.MAX_VALUE; |
1996 | } |
1997 | return database.getModificationDataId(); |
1998 | } |
1999 | |
2000 | @Override |
2001 | public Index getUniqueIndex() { |
2002 | return null; |
2003 | } |
2004 | |
2005 | /** |
2006 | * Get the number of meta table types. Supported meta table |
2007 | * types are 0 .. this value - 1. |
2008 | * |
2009 | * @return the number of meta table types |
2010 | */ |
2011 | public static int getMetaTableTypeCount() { |
2012 | return META_TABLE_TYPE_COUNT; |
2013 | } |
2014 | |
2015 | @Override |
2016 | public long getRowCountApproximation() { |
2017 | return ROW_COUNT_APPROXIMATION; |
2018 | } |
2019 | |
2020 | @Override |
2021 | public long getDiskSpaceUsed() { |
2022 | return 0; |
2023 | } |
2024 | |
2025 | @Override |
2026 | public boolean isDeterministic() { |
2027 | return true; |
2028 | } |
2029 | |
2030 | @Override |
2031 | public boolean canReference() { |
2032 | return false; |
2033 | } |
2034 | |
2035 | } |