File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\table\MetaTable.java.html

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