EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.table]

COVERAGE SUMMARY FOR SOURCE FILE [MetaTable.java]

nameclass, %method, %block, %line, %
MetaTable.java100% (1/1)63%  (24/38)95%  (5744/6060)90%  (519.1/574)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MetaTable100% (1/1)63%  (24/38)95%  (5744/6060)90%  (519.1/574)
addIndex (Session, String, int, IndexColumn [], IndexType, boolean, String): ... 0%   (0/1)0%   (0/3)0%   (0/1)
addRow (Session, Row): void 0%   (0/1)0%   (0/3)0%   (0/1)
canGetRowCount (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
canReference (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
checkSupportAlter (): void 0%   (0/1)0%   (0/3)0%   (0/1)
getDiskSpaceUsed (): long 0%   (0/1)0%   (0/2)0%   (0/1)
getDropSQL (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getRowCount (Session): long 0%   (0/1)0%   (0/2)0%   (0/1)
getUniqueIndex (): Index 0%   (0/1)0%   (0/2)0%   (0/1)
isLockedExclusively (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
removeChildrenAndResources (Session): void 0%   (0/1)0%   (0/3)0%   (0/1)
removeRow (Session, Row): void 0%   (0/1)0%   (0/3)0%   (0/1)
truncate (Session): void 0%   (0/1)0%   (0/3)0%   (0/1)
unlock (Session): void 0%   (0/1)0%   (0/1)0%   (0/1)
getRefAction (int): int 100% (1/1)20%  (4/20)33%  (2/6)
hideTable (Table, Session): boolean 100% (1/1)83%  (10/12)83%  (0.8/1)
addPrivileges (ArrayList, DbObject, String, Table, String, int): void 100% (1/1)84%  (41/49)89%  (8/9)
identifier (String): String 100% (1/1)86%  (12/14)90%  (2.7/3)
generateRows (Session, SearchRow, SearchRow): ArrayList 100% (1/1)94%  (3981/4224)91%  (332.6/366)
addPrivilege (ArrayList, DbObject, String, Table, String, String): void 100% (1/1)98%  (108/110)89%  (8/9)
MetaTable (Schema, int, int): void 100% (1/1)99%  (1355/1365)99%  (108/109)
add (ArrayList, String []): void 100% (1/1)100% (52/52)100% (11/11)
canDrop (): boolean 100% (1/1)100% (2/2)100% (1/1)
checkIndex (Session, String, Value, Value): boolean 100% (1/1)100% (43/43)100% (11/11)
checkRename (): void 100% (1/1)100% (3/3)100% (1/1)
close (Session): void 100% (1/1)100% (1/1)100% (1/1)
createColumns (String []): Column [] 100% (1/1)100% (57/57)100% (11/11)
getAllTables (Session): ArrayList 100% (1/1)100% (14/14)100% (4/4)
getCreateSQL (): String 100% (1/1)100% (2/2)100% (1/1)
getIndexes (): ArrayList 100% (1/1)100% (25/25)100% (6/6)
getMaxDataModificationId (): long 100% (1/1)100% (9/9)100% (3/3)
getMetaTableTypeCount (): int 100% (1/1)100% (2/2)100% (1/1)
getRowCountApproximation (): long 100% (1/1)100% (2/2)100% (1/1)
getScanIndex (Session): Index 100% (1/1)100% (9/9)100% (1/1)
getTableType (): String 100% (1/1)100% (2/2)100% (1/1)
isDeterministic (): boolean 100% (1/1)100% (2/2)100% (1/1)
lock (Session, boolean, boolean): boolean 100% (1/1)100% (2/2)100% (1/1)
replaceNullWithEmpty (String): String 100% (1/1)100% (6/6)100% (1/1)

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 */
6package org.h2.table;
7 
8import java.io.ByteArrayInputStream;
9import java.io.IOException;
10import java.io.InputStreamReader;
11import java.io.Reader;
12import java.sql.DatabaseMetaData;
13import java.sql.ResultSet;
14import java.sql.Timestamp;
15import java.text.Collator;
16import java.util.ArrayList;
17import java.util.Collections;
18import java.util.HashMap;
19import java.util.Locale;
20import org.h2.command.Command;
21import org.h2.constraint.Constraint;
22import org.h2.constraint.ConstraintCheck;
23import org.h2.constraint.ConstraintReferential;
24import org.h2.constraint.ConstraintUnique;
25import org.h2.engine.Constants;
26import org.h2.engine.Database;
27import org.h2.engine.DbObject;
28import org.h2.engine.FunctionAlias;
29import org.h2.engine.FunctionAlias.JavaMethod;
30import org.h2.engine.QueryStatisticsData;
31import org.h2.engine.Right;
32import org.h2.engine.Role;
33import org.h2.engine.Session;
34import org.h2.engine.Setting;
35import org.h2.engine.User;
36import org.h2.engine.UserAggregate;
37import org.h2.engine.UserDataType;
38import org.h2.expression.ValueExpression;
39import org.h2.index.Index;
40import org.h2.index.IndexType;
41import org.h2.index.MetaIndex;
42import org.h2.index.MultiVersionIndex;
43import org.h2.jdbc.JdbcSQLException;
44import org.h2.message.DbException;
45import org.h2.mvstore.FileStore;
46import org.h2.mvstore.db.MVTableEngine.Store;
47import org.h2.result.Row;
48import org.h2.result.SearchRow;
49import org.h2.result.SortOrder;
50import org.h2.schema.Constant;
51import org.h2.schema.Schema;
52import org.h2.schema.SchemaObject;
53import org.h2.schema.Sequence;
54import org.h2.schema.TriggerObject;
55import org.h2.store.InDoubtTransaction;
56import org.h2.store.PageStore;
57import org.h2.tools.Csv;
58import org.h2.util.MathUtils;
59import org.h2.util.New;
60import org.h2.util.StatementBuilder;
61import org.h2.util.StringUtils;
62import org.h2.util.Utils;
63import org.h2.value.CompareMode;
64import org.h2.value.DataType;
65import org.h2.value.Value;
66import org.h2.value.ValueNull;
67import org.h2.value.ValueString;
68import org.h2.value.ValueStringIgnoreCase;
69 
70/**
71 * This class is responsible to build the database meta data pseudo tables.
72 */
73public 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}

[all classes][org.h2.table]
EMMA 2.0.5312 (C) Vladimir Roubtsov