1 5 package org.h2.table; 6 7 import java.io.ByteArrayInputStream ; 8 import java.io.IOException ; 9 import java.io.InputStreamReader ; 10 import java.io.Reader ; 11 import java.sql.DatabaseMetaData ; 12 import java.sql.ResultSet ; 13 import java.sql.SQLException ; 14 import java.text.Collator ; 15 import java.util.Locale ; 16 17 import org.h2.constraint.Constraint; 18 import org.h2.constraint.ConstraintCheck; 19 import org.h2.constraint.ConstraintReferential; 20 import org.h2.constraint.ConstraintUnique; 21 import org.h2.engine.Constants; 22 import org.h2.engine.Database; 23 import org.h2.engine.DbObject; 24 import org.h2.engine.FunctionAlias; 25 import org.h2.engine.Mode; 26 import org.h2.engine.Right; 27 import org.h2.engine.Role; 28 import org.h2.engine.Session; 29 import org.h2.engine.Setting; 30 import org.h2.engine.User; 31 import org.h2.engine.UserDataType; 32 import org.h2.expression.ValueExpression; 33 import org.h2.index.Index; 34 import org.h2.index.IndexType; 35 import org.h2.index.MetaIndex; 36 import org.h2.message.Message; 37 import org.h2.result.Row; 38 import org.h2.result.SearchRow; 39 import org.h2.schema.Constant; 40 import org.h2.schema.Schema; 41 import org.h2.schema.Sequence; 42 import org.h2.schema.TriggerObject; 43 import org.h2.store.DiskFile; 44 import org.h2.store.InDoubtTransaction; 45 import org.h2.tools.Csv; 46 import org.h2.util.ObjectArray; 47 import org.h2.util.Resources; 48 import org.h2.util.StringUtils; 49 import org.h2.value.CompareMode; 50 import org.h2.value.DataType; 51 import org.h2.value.Value; 52 import org.h2.value.ValueNull; 53 import org.h2.value.ValueString; 54 55 58 59 public class MetaTable extends Table { 60 61 63 public static final int TABLES = 0, COLUMNS = 1, INDEXES = 2, TABLE_TYPES=3, 64 TYPE_INFO=4, CATALOGS=5, SETTINGS=6, HELP=7, SEQUENCES=8, USERS=9, 65 ROLES=10, RIGHTS=11, FUNCTION_ALIASES = 12, SCHEMATA = 13, TABLE_PRIVILEGES = 14, 66 COLUMN_PRIVILEGES = 15, COLLATIONS = 16, VIEWS = 17, IN_DOUBT = 18, CROSS_REFERENCES = 19, 67 CONSTRAINTS = 20, FUNCTION_COLUMNS = 21, CONSTANTS = 22, DOMAINS = 23, TRIGGERS = 24; 68 69 private int type; 70 private MetaIndex index; 71 private int indexColumn; 72 73 public MetaTable(Schema schema, int type) throws SQLException { 74 super(schema, 0, null, true); 76 this.type = type; 77 Column[] cols; 78 String indexColumnName = null; 79 switch(type) { 80 case TABLES: 81 setObjectName("TABLES"); 82 cols = createColumns(new String []{ 83 "TABLE_CATALOG", 84 "TABLE_SCHEMA", 85 "TABLE_NAME", 86 "TABLE_TYPE", 87 "STORAGE_TYPE", 89 "SQL", 90 "REMARKS" 91 }); 92 indexColumnName = "TABLE_NAME"; 93 break; 94 case COLUMNS: 95 setObjectName("COLUMNS"); 96 cols = createColumns(new String []{ 97 "TABLE_CATALOG", 98 "TABLE_SCHEMA", 99 "TABLE_NAME", 100 "COLUMN_NAME", 101 "ORDINAL_POSITION INT", 102 "COLUMN_DEFAULT", 103 "IS_NULLABLE", 104 "DATA_TYPE SMALLINT", 105 "CHARACTER_MAXIMUM_LENGTH INT", 106 "CHARACTER_OCTET_LENGTH INT", 107 "NUMERIC_PRECISION INT", 108 "NUMERIC_PRECISION_RADIX INT", 109 "NUMERIC_SCALE INT", 110 "CHARACTER_SET_NAME", 111 "COLLATION_NAME", 112 "TYPE_NAME", 114 "NULLABLE SMALLINT", 115 "IS_COMPUTED BIT", 116 "SELECTIVITY INT", 117 "CHECK_CONSTRAINT", 118 "REMARKS" 119 }); 120 indexColumnName = "TABLE_NAME"; 121 break; 122 case INDEXES: 123 setObjectName("INDEXES"); 124 cols = createColumns(new String []{ 125 "TABLE_CATALOG", 126 "TABLE_SCHEMA", 127 "TABLE_NAME", 128 "NON_UNIQUE BIT", 129 "INDEX_NAME", 130 "ORDINAL_POSITION SMALLINT", 131 "COLUMN_NAME", 132 "CARDINALITY INT", 133 "PRIMARY_KEY BIT", 134 "INDEX_TYPE_NAME", 135 "IS_GENERATED BIT", 136 "INDEX_TYPE SMALLINT", 137 "ASC_OR_DESC", 138 "PAGES INT", 139 "FILTER_CONDITION", 140 "REMARKS" 141 }); 142 indexColumnName = "TABLE_NAME"; 143 break; 144 case TABLE_TYPES: 145 setObjectName("TABLE_TYPES"); 146 cols = createColumns( 147 new String []{"TYPE"}); 148 break; 149 case TYPE_INFO: 150 setObjectName("TYPE_INFO"); 151 cols = createColumns(new String []{ 152 "TYPE_NAME", 153 "DATA_TYPE SMALLINT", 154 "PRECISION INT", 155 "PREFIX", 156 "SUFFIX", 157 "PARAMS", 158 "AUTO_INCREMENT BIT", 159 "MINIMUM_SCALE SMALLINT", 160 "MAXIMUM_SCALE SMALLINT", 161 "RADIX INT", 162 "POS INT", 163 "CASE_SENSITIVE BIT", 164 "NULLABLE SMALLINT", 165 "SEARCHABLE SMALLINT" 166 }); 167 break; 168 case CATALOGS: 169 setObjectName("CATALOGS"); 170 cols = createColumns( 171 new String []{"CATALOG_NAME"}); 172 break; 173 case SETTINGS: 174 setObjectName("SETTINGS"); 175 cols = createColumns( 176 new String []{"NAME", "VALUE"}); 177 break; 178 case HELP: 179 setObjectName("HELP"); 180 cols = createColumns(new String []{ 181 "ID INT", 182 "SECTION", 183 "TOPIC", 184 "SYNTAX", 185 "TEXT", 186 "EXAMPLE" 187 }); 188 break; 189 case SEQUENCES: 190 setObjectName("SEQUENCES"); 191 cols = createColumns(new String []{ 192 "SEQUENCE_CATALOG", 193 "SEQUENCE_SCHEMA", 194 "SEQUENCE_NAME", 195 "CURRENT_VALUE BIGINT", 196 "INCREMENT BIGINT", 197 "IS_GENERATED BIT", 198 "REMARKS" 199 }); 200 break; 201 case USERS: 202 setObjectName("USERS"); 203 cols = createColumns(new String []{ 204 "NAME", 205 "ADMIN", 206 "REMARKS" 207 }); 208 break; 209 case ROLES: 210 setObjectName("ROLES"); 211 cols = createColumns(new String []{ 212 "NAME", 213 "REMARKS" 214 }); 215 break; 216 case RIGHTS: 217 setObjectName("RIGHTS"); 218 cols = createColumns(new String []{ 219 "GRANTEE", 220 "GRANTEETYPE", 221 "GRANTEDROLE", 222 "RIGHTS", 223 "TABLE_SCHEMA", 224 "TABLE_NAME" 225 }); 226 indexColumnName = "TABLE_NAME"; 227 break; 228 case FUNCTION_ALIASES: 229 setObjectName("FUNCTION_ALIASES"); 230 cols = createColumns(new String []{ 231 "ALIAS_CATALOG", 232 "ALIAS_SCHEMA", 233 "ALIAS_NAME", 234 "JAVA_CLASS", 235 "JAVA_METHOD", 236 "DATA_TYPE INT", 237 "COLUMN_COUNT INT", 238 "RETURNS_RESULT SMALLINT", 239 "REMARKS" 240 }); 241 break; 242 case FUNCTION_COLUMNS: 243 setObjectName("FUNCTION_COLUMNS"); 244 cols = createColumns(new String []{ 245 "ALIAS_CATALOG", 246 "ALIAS_SCHEMA", 247 "ALIAS_NAME", 248 "JAVA_CLASS", 249 "JAVA_METHOD", 250 "POS INT", 251 "COLUMN_NAME", 252 "DATA_TYPE INT", 253 "TYPE_NAME", 254 "PRECISION INT", 255 "SCALE SMALLINT", 256 "RADIX SMALLINT", 257 "NULLABLE SMALLINT", 258 "COLUMN_TYPE SMALLINT", 259 "REMARKS" 260 }); 261 break; 262 case SCHEMATA: 263 setObjectName("SCHEMATA"); 264 cols = createColumns(new String []{ 265 "CATALOG_NAME", 266 "SCHEMA_NAME", 267 "SCHEMA_OWNER", 268 "DEFAULT_CHARACTER_SET_NAME", 269 "DEFAULT_COLLATION_NAME", 270 "IS_DEFAULT BIT", 271 "REMARKS" 272 }); 273 break; 274 case TABLE_PRIVILEGES: 275 setObjectName("TABLE_PRIVILEGES"); 276 cols = createColumns(new String []{ 277 "GRANTOR", 278 "GRANTEE", 279 "TABLE_CATALOG", 280 "TABLE_SCHEMA", 281 "TABLE_NAME", 282 "PRIVILEGE_TYPE", 283 "IS_GRANTABLE", 284 }); 285 indexColumnName = "TABLE_NAME"; 286 break; 287 case COLUMN_PRIVILEGES: 288 setObjectName("COLUMN_PRIVILEGES"); 289 cols = createColumns(new String []{ 290 "GRANTOR", 291 "GRANTEE", 292 "TABLE_CATALOG", 293 "TABLE_SCHEMA", 294 "TABLE_NAME", 295 "COLUMN_NAME", 296 "PRIVILEGE_TYPE", 297 "IS_GRANTABLE", 298 }); 299 indexColumnName = "TABLE_NAME"; 300 break; 301 case COLLATIONS: 302 setObjectName("COLLATIONS"); 303 cols = createColumns(new String []{ 304 "NAME", 305 "KEY" 306 }); 307 break; 308 case VIEWS: 309 setObjectName("VIEWS"); 310 cols = createColumns(new String []{ 311 "TABLE_CATALOG", 312 "TABLE_SCHEMA", 313 "TABLE_NAME", 314 "VIEW_DEFINITION", 315 "CHECK_OPTION", 316 "IS_UPDATABLE", 317 "STATUS", 318 "REMARKS" 319 }); 320 indexColumnName = "TABLE_NAME"; 321 break; 322 case IN_DOUBT: 323 setObjectName("IN_DOUBT"); 324 cols = createColumns(new String []{ 325 "TRANSACTION", 326 "STATE", 327 }); 328 break; 329 case CROSS_REFERENCES: 330 setObjectName("CROSS_REFERENCES"); 331 cols = createColumns(new String []{ 332 "PKTABLE_CATALOG", 333 "PKTABLE_SCHEMA", 334 "PKTABLE_NAME", 335 "PKCOLUMN_NAME", 336 "FKTABLE_CATALOG", 337 "FKTABLE_SCHEMA", 338 "FKTABLE_NAME", 339 "FKCOLUMN_NAME", 340 "ORDINAL_POSITION SMALLINT", 341 "UPDATE_RULE SMALLINT", 342 "DELETE_RULE SMALLINT", 343 "FK_NAME", 344 "PK_NAME", 345 "DEFERRABILITY SMALLINT" 346 }); 347 indexColumnName = "PKTABLE_NAME"; 348 break; 349 case CONSTRAINTS: 350 setObjectName("CONSTRAINTS"); 351 cols = createColumns(new String []{ 352 "CONSTRAINT_CATALOG", 353 "CONSTRAINT_SCHEMA", 354 "CONSTRAINT_NAME", 355 "CONSTRAINT_TYPE", 356 "TABLE_CATALOG", 357 "TABLE_SCHEMA", 358 "TABLE_NAME", 359 "CHECK_EXPRESSION", 360 "COLUMN_LIST", 361 "REMARKS", 362 "SQL", 363 }); 364 indexColumnName = "TABLE_NAME"; 365 break; 366 case CONSTANTS: 367 setObjectName("CONSTANTS"); 368 cols = createColumns(new String []{ 369 "CONSTANT_CATALOG", 370 "CONSTANT_SCHEMA", 371 "CONSTANT_NAME", 372 "DATA_TYPE SMALLINT", 373 "REMARKS", 374 "SQL", 375 }); 376 break; 377 case DOMAINS: 378 setObjectName("DOMAINS"); 379 cols = createColumns(new String []{ 380 "DOMAIN_CATALOG", 381 "DOMAIN_SCHEMA", 382 "DOMAIN_NAME", 383 "COLUMN_DEFAULT", 384 "IS_NULLABLE", 385 "DATA_TYPE SMALLINT", 386 "PRECISION INT", 387 "SCALE INT", 388 "TYPE_NAME", 389 "SELECTIVITY INT", 390 "CHECK_CONSTRAINT", 391 "REMARKS", 392 "SQL", 393 }); 394 break; 395 case TRIGGERS: 396 setObjectName("TRIGGERS"); 397 cols = createColumns(new String []{ 398 "TRIGGER_CATALOG", 399 "TRIGGER_SCHEMA", 400 "TRIGGER_NAME", 401 "TRIGGER_TYPE", 402 "TABLE_CATALOG", 403 "TABLE_SCHEMA", 404 "TABLE_NAME", 405 "BEFORE BIT", 406 "JAVA_CLASS", 407 "QUEUE_SIZE INT", 408 "NO_WAIT BIT", 409 "REMARKS", 410 "SQL", 411 }); 412 break; 413 default: 414 throw Message.getInternalError("type="+type); 415 } 416 setColumns(cols); 417 418 if(indexColumnName == null) { 419 indexColumn = -1; 420 } else { 421 indexColumn = getColumn(indexColumnName).getColumnId(); 422 Column[] indexCols = new Column[]{cols[indexColumn]}; 423 index = new MetaIndex(this, indexCols, false); 424 } 425 } 426 427 private Column[] createColumns(String [] names) { 428 Column[] cols = new Column[names.length]; 429 for(int i=0; i<names.length; i++) { 430 String nameType = names[i]; 431 int idx = nameType.indexOf(' '); 432 int type; 433 String name; 434 if(idx < 0) { 435 type = Value.STRING; 436 name = nameType; 437 } else { 438 type = DataType.getTypeByName(nameType.substring(idx+1)).type; 439 name = nameType.substring(0, idx); 440 } 441 cols[i] = new Column(name, type, 0, 0); 442 } 443 return cols; 444 } 445 446 public String getCreateSQL() { 447 return null; 448 } 449 450 public Index addIndex(Session session, String indexName, int indexId, Column[] cols, IndexType indexType, int headPos, String comment) throws SQLException { 451 throw Message.getUnsupportedException(); 452 } 453 454 public void lock(Session session, boolean exclusive) throws SQLException { 455 } 457 458 public boolean isLockedExclusively() { 459 return false; 460 } 461 462 private String identifier(String s) { 463 if(Mode.getCurrentMode().lowerCaseIdentifiers) { 464 s = (s==null ? null : StringUtils.toLowerEnglish(s)); 465 } 466 return s; 467 } 468 469 private ObjectArray getAllTables(Session session) { 470 ObjectArray tables = database.getAllSchemaObjects(DbObject.TABLE_OR_VIEW); 471 ObjectArray tempTables = session.getLocalTempTables(); 472 tables.addAll(tempTables); 473 return tables; 474 } 475 476 private boolean checkIndex(Session session, String value, Value indexFrom, Value indexTo) throws SQLException { 477 if(value == null || (indexFrom == null && indexTo == null)) { 478 return true; 479 } 480 Database db = session.getDatabase(); 481 Value v = ValueString.get(value); 482 if(indexFrom != null && db.compare(v, indexFrom) < 0) { 483 return false; 484 } 485 if(indexTo != null && db.compare(v, indexTo) > 0) { 486 return false; 487 } 488 return true; 489 } 490 491 private String replaceNullWithEmpty(String s) { 492 return s == null ? "" : s; 493 } 494 495 public ObjectArray generateRows(Session session, SearchRow first, SearchRow last) throws SQLException { 496 Value indexFrom = null, indexTo = null; 497 if(indexColumn >= 0) { 498 if(first != null) { 499 indexFrom = first.getValue(indexColumn); 500 } 501 if(last != null) { 502 indexTo = last.getValue(indexColumn); 503 } 504 } 505 ObjectArray rows = new ObjectArray(); 506 String catalog = identifier(database.getShortName()); 507 switch(type) { 508 case TABLES: { 509 ObjectArray tables = getAllTables(session); 510 for(int i=0; i<tables.size(); i++) { 511 Table table = (Table) tables.get(i); 512 String tableName = identifier(table.getName()); 513 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 514 continue; 515 } 516 String storageType; 517 if(table.getTemporary()) { 518 if(table.getGlobalTemporary()) { 519 storageType = "GLOBAL TEMPORARY"; 520 } else { 521 storageType = "LOCAL TEMPORARY"; 522 } 523 } else { 524 storageType = table.isPersistent() ? "CACHED" : "MEMORY"; 525 } 526 add(rows, new String []{ 527 catalog, identifier(table.getSchema().getName()), tableName, table.getTableType(), storageType, table.getCreateSQL(), replaceNullWithEmpty(table.getComment()) }); 535 } 536 break; 537 } 538 case COLUMNS: { 539 ObjectArray tables = getAllTables(session); 540 for(int i=0; i<tables.size(); i++) { 541 Table table = (Table) tables.get(i); 542 String tableName = identifier(table.getName()); 543 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 544 continue; 545 } 546 Column[] cols = table.getColumns(); 547 String collation = database.getCompareMode().getName(); 548 for(int j=0; j<cols.length; j++) { 549 Column c = cols[j]; 550 add(rows, new String []{ 551 catalog, identifier(table.getSchema().getName()), tableName, identifier(c.getName()), String.valueOf(j + 1), c.getDefaultSQL(), c.getNullable() ? "YES" : "NO", "" + DataType.convertTypeToSQLType(c.getType()), "" + c.getPrecisionAsInt(), "" + c.getPrecisionAsInt(), "" + c.getPrecisionAsInt(), "10", "" + c.getScale(), Constants.CHARACTER_SET_NAME, collation, identifier(DataType.getDataType(c.getType()).name), "" + (c.getNullable() ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls) , "" + (c.getComputed() ? "TRUE" : "FALSE"), "" + (c.getSelectivity()), c.getCheckConstraintSQL(session, c.getName()), replaceNullWithEmpty(c.getComment()) }); 573 } 574 } 575 break; 576 } 577 case INDEXES: { 578 ObjectArray tables = getAllTables(session); 579 for(int i=0; i<tables.size(); i++) { 580 Table table = (Table) tables.get(i); 581 String tableName = identifier(table.getName()); 582 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 583 continue; 584 } 585 ObjectArray idx = table.getIndexes(); 586 for(int j=0; idx != null && j<idx.size(); j++) { 587 Index index = (Index) idx.get(j); 588 if(index.getCreateSQL() == null) { 589 continue; 590 } 591 Column[] cols = index.getColumns(); 592 for(int k=0; k<cols.length; k++) { 593 Column column = cols[k]; 594 add(rows,new String []{ 595 catalog, identifier(table.getSchema().getName()), tableName, index.getIndexType().isUnique() ? "FALSE" : "TRUE", identifier(index.getName()), "" + (k+1), identifier(column.getName()), "0", index.getIndexType().isPrimaryKey() ? "TRUE" : "FALSE", index.getIndexType().getSQL(), index.getIndexType().belongsToConstraint() ? "TRUE" : "FALSE", "" + DatabaseMetaData.tableIndexOther, "A", "0", "", replaceNullWithEmpty(index.getComment()) }); 612 } 613 } 614 } 615 break; 616 } 617 case TABLE_TYPES: { 618 add(rows,new String []{Table.TABLE}); 619 add(rows,new String []{Table.TABLE_LINK}); 620 add(rows,new String []{Table.SYSTEM_TABLE}); 621 add(rows,new String []{Table.VIEW}); 622 break; 623 } 624 case CATALOGS: { 625 add(rows,new String []{catalog}); 626 break; 627 } 628 case SETTINGS: { 629 ObjectArray list = database.getAllSettings(); 630 for(int i=0; i<list.size(); i++) { 631 Setting s = (Setting)list.get(i); 632 String value = s.getStringValue(); 633 if(value == null) { 634 value = "" + s.getIntValue(); 635 } 636 add(rows,new String []{ 637 identifier(s.getName()), 638 value 639 }); 640 } 641 add(rows, new String []{"MODE", Mode.getCurrentMode().getName()}); 642 DiskFile dataFile = database.getDataFile(); 643 if(dataFile != null) { 644 add(rows, new String []{"CACHE_TYPE", dataFile.getCache().getTypeName()}); 645 if(session.getUser().getAdmin()) { 646 add(rows, new String []{"FILE_DISK_WRITE", "" + dataFile.getWriteCount()}); 647 add(rows, new String []{"FILE_DISK_READ", "" + dataFile.getReadCount()}); 648 add(rows, new String []{"FILE_INDEX_WRITE", "" + database.getIndexFile().getWriteCount()}); 649 add(rows, new String []{"FILE_INDEX_READ", "" + database.getIndexFile().getReadCount()}); 650 } 651 } 652 add(rows, new String []{"h2.check", "" + Constants.CHECK}); 653 add(rows, new String []{"h2.check2", "" + Constants.CHECK2}); 654 add(rows, new String []{"h2.lobFilesInDirectories", "" + Constants.LOB_FILES_IN_DIRECTORIES}); 655 add(rows, new String []{"h2.lobFilesPerDirectory", "" + Constants.LOB_FILES_PER_DIRECTORY}); 656 add(rows, new String []{"h2.multiThreadedKernel", "" + Constants.MULTI_THREADED_KERNEL}); 657 add(rows, new String []{"h2.runFinalizers", "" + Constants.RUN_FINALIZERS}); 658 add(rows, new String []{"h2.optimizeMinMax", "" + Constants.OPTIMIZE_MIN_MAX}); 659 add(rows, new String []{"h2.optimizeIn", "" + Constants.OPTIMIZE_IN}); 660 add(rows, new String []{"h2.redoBufferSize", "" + Constants.REDO_BUFFER_SIZE}); 661 add(rows, new String []{"h2.recompileAlways", "" + Constants.RECOMPILE_ALWAYS}); 662 add(rows, new String []{"h2.optimizeSubqueryCache", "" + Constants.OPTIMIZE_SUBQUERY_CACHE}); 663 add(rows, new String []{"h2.overflowExceptions", "" + Constants.OVERFLOW_EXCEPTIONS}); 664 add(rows, new String []{"h2.logAllErrors", "" + Constants.LOG_ALL_ERRORS}); 665 add(rows, new String []{"h2.logAllErrorsFile", "" + Constants.LOG_ALL_ERRORS_FILE}); 666 add(rows, new String []{"h2.serverCachedObjects", "" + Constants.SERVER_CACHED_OBJECTS}); 667 add(rows, new String []{"h2.serverSmallResultSetSize", "" + Constants.SERVER_SMALL_RESULTSET_SIZE}); 668 add(rows, new String []{"h2.emergencySpaceInitial", "" + Constants.EMERGENCY_SPACE_INITIAL}); 669 add(rows, new String []{"h2.emergencySpaceMin", "" + Constants.EMERGENCY_SPACE_MIN}); 670 add(rows, new String []{"h2.objectCache", "" + Constants.OBJECT_CACHE}); 671 add(rows, new String []{"h2.objectCacheSize", "" + Constants.OBJECT_CACHE_SIZE}); 672 add(rows, new String []{"h2.objectCacheMaxPerElementSize", "" + Constants.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE}); 673 add(rows, new String []{"h2.clientTraceDirectory", Constants.CLIENT_TRACE_DIRECTORY}); 674 add(rows, new String []{"h2.scriptDirectory", Constants.SCRIPT_DIRECTORY}); 675 break; 676 } 677 case TYPE_INFO: { 678 ObjectArray types = DataType.getTypes(); 679 for(int i=0; i<types.size(); i++) { 680 DataType t = (DataType) types.get(i); 681 if(t.hidden || t.sqlType == Value.NULL) { 682 continue; 683 } 684 add(rows,new String []{ 685 t.name, String.valueOf(t.sqlType), String.valueOf(t.maxPrecision), t.prefix, t.suffix, t.params, String.valueOf(t.autoInc), String.valueOf(t.minScale), String.valueOf(t.maxScale), t.decimal ? "10" : null, String.valueOf(t.order), String.valueOf(t.caseSensitive), "" + DatabaseMetaData.typeNullable, "" + DatabaseMetaData.typeSearchable }); 700 } 701 break; 702 } 703 case HELP: { 704 try { 705 byte[] data = Resources.get("/org/h2/res/help.csv"); 706 Reader reader = new InputStreamReader (new ByteArrayInputStream (data)); 707 ResultSet rs = Csv.getInstance().read(reader, null); 708 for(int i=0; rs.next(); i++) { 709 add(rows, new String []{ 710 String.valueOf(i), rs.getString(1).trim(), rs.getString(2).trim(), rs.getString(3).trim(), rs.getString(4).trim(), rs.getString(5).trim(), }); 717 } 718 } catch (IOException e) { 719 throw Message.convert(e); 720 } 721 break; 722 } 723 case SEQUENCES: { 724 ObjectArray sequences = database.getAllSchemaObjects(DbObject.SEQUENCE); 725 for(int i=0; i<sequences.size(); i++) { 726 Sequence s = (Sequence) sequences.get(i); 727 add(rows,new String []{ 728 catalog, identifier(s.getSchema().getName()), identifier(s.getName()), String.valueOf(s.getCurrentValue()), String.valueOf(s.getIncrement()), s.getBelongsToTable() ? "TRUE" : "FALSE", replaceNullWithEmpty(s.getComment()) }); 736 } 737 break; 738 } 739 case USERS: { 740 ObjectArray users = database.getAllUsers(); 741 for(int i=0; i<users.size(); i++) { 742 User u = (User) users.get(i); 743 add(rows,new String []{ 744 identifier(u.getName()), String.valueOf(u.getAdmin()), replaceNullWithEmpty(u.getComment()) }); 748 } 749 break; 750 } 751 case ROLES: { 752 ObjectArray roles = database.getAllRoles(); 753 for(int i=0; i<roles.size(); i++) { 754 Role r = (Role) roles.get(i); 755 add(rows,new String []{ 756 identifier(r.getName()), replaceNullWithEmpty(r.getComment()) }); 759 } 760 break; 761 } 762 case RIGHTS: { 763 ObjectArray rights = database.getAllRights(); 764 for(int i=0; i<rights.size(); i++) { 765 Right r = (Right) rights.get(i); 766 Role role = r.getGrantedRole(); 768 DbObject grantee = r.getGrantee(); 769 String type = grantee.getType() == DbObject.USER ? "USER" : "ROLE"; 770 if(role == null) { 771 Table granted = r.getGrantedTable(); 772 String tableName = identifier(granted.getName()); 773 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 774 continue; 775 } 776 add(rows,new String []{ 777 identifier(grantee.getName()), 778 type, 779 "", 780 r.getRights(), 781 identifier(granted.getSchema().getName()), 782 identifier(granted.getName()) 783 }); 784 } else { 785 add(rows,new String []{ 786 identifier(grantee.getName()), 787 type, 788 identifier(role.getName()), 789 "", 790 "", 791 "" 792 }); 793 } 794 } 795 break; 796 } 797 case FUNCTION_ALIASES: { 798 ObjectArray aliases = database.getAllFunctionAliases(); 799 for(int i=0; i<aliases.size(); i++) { 800 FunctionAlias alias = (FunctionAlias) aliases.get(i); 801 int returnsResult = alias.getDataType() == Value.NULL ? DatabaseMetaData.procedureNoResult : DatabaseMetaData.procedureReturnsResult; 802 add(rows,new String []{ 803 catalog, Constants.SCHEMA_MAIN, identifier(alias.getName()), alias.getJavaClassName(), alias.getJavaMethodName(), ""+DataType.convertTypeToSQLType(alias.getDataType()), ""+ alias.getColumnClasses().length, ""+ returnsResult, replaceNullWithEmpty(alias.getComment()) }); 813 } 814 break; 815 } 816 case FUNCTION_COLUMNS: { 817 ObjectArray aliases = database.getAllFunctionAliases(); 818 for(int i=0; i<aliases.size(); i++) { 819 FunctionAlias alias = (FunctionAlias) aliases.get(i); 820 Class [] columns = alias.getColumnClasses(); 821 for(int j=0; j<columns.length; j++) { 822 Class clazz = columns[j]; 823 int type = DataType.getTypeFromClass(clazz); 824 DataType dt = DataType.getDataType(type); 825 int nullable = clazz.isPrimitive() ? DatabaseMetaData.columnNoNulls : DatabaseMetaData.columnNullable; 826 add(rows,new String []{ 827 catalog, Constants.SCHEMA_MAIN, identifier(alias.getName()), alias.getJavaClassName(), alias.getJavaMethodName(), "" + j, "P" + (j+1), "" + DataType.convertTypeToSQLType(dt.type), dt.name, "" + dt.defaultPrecision, "" + dt.defaultScale, "10", "" + nullable, "" + DatabaseMetaData.procedureColumnIn, "" }); 843 } 844 } 845 break; 846 } 847 case SCHEMATA: { 848 ObjectArray schemas = database.getAllSchemas(); 849 String collation = database.getCompareMode().getName(); 850 for(int i=0; i<schemas.size(); i++) { 851 Schema schema = (Schema) schemas.get(i); 852 add(rows,new String []{ 853 catalog, identifier(schema.getName()), identifier(schema.getOwner().getName()), Constants.CHARACTER_SET_NAME, collation, Constants.SCHEMA_MAIN.equals(schema.getName()) ? "TRUE" : "FALSE", replaceNullWithEmpty(schema.getComment()) }); 861 } 862 break; 863 } 864 case TABLE_PRIVILEGES: { 865 ObjectArray rights = database.getAllRights(); 866 for(int i=0; i<rights.size(); i++) { 867 Right r = (Right) rights.get(i); 868 Table table = r.getGrantedTable(); 869 if(table == null) { 870 continue; 871 } 872 String tableName = identifier(table.getName()); 873 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 874 continue; 875 } 876 addPrivileges(rows, r.getGrantee(), catalog, table, null, r.getRightMask()); 877 } 878 break; 879 } 880 case COLUMN_PRIVILEGES: { 881 ObjectArray rights = database.getAllRights(); 882 for(int i=0; i<rights.size(); i++) { 883 Right r = (Right) rights.get(i); 884 Table table = r.getGrantedTable(); 885 if(table == null) { 886 continue; 887 } 888 String tableName = identifier(table.getName()); 889 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 890 continue; 891 } 892 DbObject grantee = r.getGrantee(); 893 int mask = r.getRightMask(); 894 Column[] columns = table.getColumns(); 895 for(int j=0; j<columns.length; j++) { 896 String column = columns[j].getName(); 897 addPrivileges(rows, grantee, catalog, table, column, mask); 898 } 899 } 900 break; 901 } 902 case COLLATIONS: { 903 Locale [] locales = Collator.getAvailableLocales(); 904 for(int i=0; i<locales.length; i++) { 905 Locale l = locales[i]; 906 add(rows,new String []{ 907 CompareMode.getName(l), l.toString(), }); 910 } 911 break; 912 } 913 case VIEWS: { 914 ObjectArray tables = getAllTables(session); 915 for(int i=0; i<tables.size(); i++) { 916 Table table = (Table) tables.get(i); 917 if(!table.getTableType().equals(Table.VIEW)) { 918 continue; 919 } 920 String tableName = identifier(table.getName()); 921 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 922 continue; 923 } 924 TableView view = (TableView)table; 925 add(rows, new String []{ 926 catalog, identifier(table.getSchema().getName()), tableName, table.getCreateSQL(), "NONE", "NO", view.getInvalid() ? "INVALID" : "VALID", replaceNullWithEmpty(view.getComment()) }); 935 } 936 break; 937 } 938 case IN_DOUBT: { 939 ObjectArray prepared = database.getLog().getInDoubtTransactions(); 940 for(int i=0; prepared != null && i<prepared.size(); i++) { 941 InDoubtTransaction prep = (InDoubtTransaction) prepared.get(i); 942 add(rows, new String [] { 943 prep.getTransaction(), prep.getState(), }); 946 } 947 break; 948 } 949 case CROSS_REFERENCES: { 950 ObjectArray constraints = database.getAllSchemaObjects(DbObject.CONSTRAINT); 951 for(int i=0; i<constraints.size(); i++) { 952 Constraint constraint = (Constraint) constraints.get(i); 953 if(!(constraint.getConstraintType().equals(Constraint.REFERENTIAL))) { 954 continue; 955 } 956 ConstraintReferential ref = (ConstraintReferential) constraint; 957 Column[] cols = ref.getColumns(); 958 Column[] refCols = ref.getRefColumns(); 959 Table tab = ref.getTable(); 960 Table refTab = ref.getRefTable(); 961 String tableName = identifier(refTab.getName()); 962 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 963 continue; 964 } 965 int upd = getRefAction(ref.getUpdateAction()); 966 int del = getRefAction(ref.getDeleteAction()); 967 for(int j=0; j<cols.length; j++) { 968 add(rows, new String [] { 969 catalog, identifier(refTab.getSchema().getName()), identifier(refTab.getName()), identifier(refCols[j].getName()), catalog, identifier(tab.getSchema().getName()), identifier(tab.getName()), identifier(cols[j].getName()), String.valueOf(j + 1), String.valueOf(upd), String.valueOf(del), identifier(ref.getName()), null, "" + DatabaseMetaData.importedKeyNotDeferrable, }); 984 } 985 } 986 break; 987 } 988 case CONSTRAINTS: { 989 ObjectArray constraints = database.getAllSchemaObjects(DbObject.CONSTRAINT); 990 for(int i=0; i<constraints.size(); i++) { 991 Constraint constraint = (Constraint) constraints.get(i); 992 String type = constraint.getConstraintType(); 993 String checkExpression = null; 994 Column[] columns = null; 995 Table table = constraint.getTable(); 996 String tableName = identifier(table.getName()); 997 if(!checkIndex(session, tableName, indexFrom, indexTo)) { 998 continue; 999 } 1000 if(type.equals(Constraint.CHECK)) { 1001 checkExpression = ((ConstraintCheck)constraint).getExpression().getSQL(); 1002 } else if(type.equals(Constraint.UNIQUE)) { 1003 columns = ((ConstraintUnique)constraint).getColumns(); 1004 } else if(type.equals(Constraint.REFERENTIAL)) { 1005 columns = ((ConstraintReferential)constraint).getColumns(); 1006 } 1007 String columnList = null; 1008 if(columns != null) { 1009 columnList = ""; 1010 for(int j=0; j<columns.length; j++) { 1011 if(j>0) { 1012 columnList += ","; 1013 } 1014 columnList += columns[j].getName(); 1015 } 1016 } 1017 add(rows, new String [] { 1018 catalog, identifier(constraint.getSchema().getName()), identifier(constraint.getName()), type, catalog, identifier(table.getSchema().getName()), tableName, checkExpression, columnList, replaceNullWithEmpty(constraint.getComment()), constraint.getCreateSQL(), }); 1030 } 1031 break; 1032 } 1033 case CONSTANTS: { 1034 ObjectArray constants = database.getAllSchemaObjects(DbObject.CONSTANT); 1035 for(int i=0; i<constants.size(); i++) { 1036 Constant constant = (Constant) constants.get(i); 1037 ValueExpression expr = constant.getValue(); 1038 add(rows, new String [] { 1039 catalog, identifier(constant.getSchema().getName()), identifier(constant.getName()), "" + DataType.convertTypeToSQLType(expr.getType()), replaceNullWithEmpty(constant.getComment()), expr.getSQL(), }); 1046 } 1047 break; 1048 } 1049 case DOMAINS: { 1050 ObjectArray userDataTypes = database.getAllUserDataTypes(); 1051 for(int i=0; i<userDataTypes.size(); i++) { 1052 UserDataType dt = (UserDataType) userDataTypes.get(i); 1053 Column col = dt.getColumn(); 1054 add(rows, new String [] { 1055 catalog, Constants.SCHEMA_MAIN, identifier(dt.getName()), col.getDefaultSQL(), col.getNullable() ? "YES" : "NO", "" + col.getDataType().sqlType, "" + col.getPrecisionAsInt(), "" + col.getScale(), col.getDataType().name, "" + col.getSelectivity(), "" + col.getCheckConstraintSQL(session, "VALUE"), replaceNullWithEmpty(dt.getComment()), "" + dt.getCreateSQL() }); 1069 } 1070 break; 1071 } 1072 case TRIGGERS: { 1073 ObjectArray triggers = database.getAllSchemaObjects(DbObject.TRIGGER); 1074 for(int i=0; i<triggers.size(); i++) { 1075 TriggerObject trigger = (TriggerObject) triggers.get(i); 1076 Table table = trigger.getTable(); 1077 add(rows, new String [] { 1078 catalog, identifier(trigger.getSchema().getName()), identifier(trigger.getName()), trigger.getTypeNameList(), catalog, identifier(table.getSchema().getName()), identifier(table.getName()), "" + trigger.getBefore(), trigger.getTriggerClassName(), "" + trigger.getQueueSize(), "" + trigger.getNoWait(), replaceNullWithEmpty(trigger.getComment()), trigger.getSQL() }); 1092 } 1093 break; 1094 } 1095 default: 1096 throw Message.getInternalError("type="+type); 1097 } 1098 return rows; 1099 } 1100 1101 private int getRefAction(int action) { 1102 switch(action) { 1103 case ConstraintReferential.CASCADE: 1104 return DatabaseMetaData.importedKeyCascade; 1105 case ConstraintReferential.RESTRICT: 1106 return DatabaseMetaData.importedKeyRestrict; 1107 case ConstraintReferential.SET_DEFAULT: 1108 return DatabaseMetaData.importedKeySetDefault; 1109 case ConstraintReferential.SET_NULL: 1110 return DatabaseMetaData.importedKeySetNull; 1111 default: 1112 throw Message.getInternalError("action="+action); 1113 } 1114 } 1115 1116 public void removeRow(Session session, Row row) throws SQLException { 1117 throw Message.getUnsupportedException(); 1118 } 1119 1120 public void addRow(Session session, Row row) throws SQLException { 1121 throw Message.getUnsupportedException(); 1122 } 1123 1124 public void removeIndex(String indexName) throws SQLException { 1125 throw Message.getUnsupportedException(); 1126 } 1127 1128 public void removeChildrenAndResources(Session session) throws SQLException { 1129 throw Message.getUnsupportedException(); 1130 } 1131 1132 public void close(Session session) throws SQLException { 1133 } 1135 1136 public void unlock(Session s) { 1137 } 1139 1140 private void addPrivileges(ObjectArray rows, DbObject grantee, String catalog, Table table, String column, int rightMask) throws SQLException { 1141 if((rightMask & Right.SELECT) != 0) { 1142 addPrivileg(rows, grantee, catalog, table, column, "SELECT"); 1143 } 1144 if((rightMask & Right.INSERT) != 0) { 1145 addPrivileg(rows, grantee, catalog, table, column, "INSERT"); 1146 } 1147 if((rightMask & Right.UPDATE) != 0) { 1148 addPrivileg(rows, grantee, catalog, table, column, "UPDATE"); 1149 } 1150 if((rightMask & Right.DELETE) != 0) { 1151 addPrivileg(rows, grantee, catalog, table, column, "DELETE"); 1152 } 1153 } 1154 1155 private void addPrivileg(ObjectArray rows, DbObject grantee, String catalog, Table table, String column, String right) throws SQLException { 1156 String isGrantable = "NO"; 1157 if(grantee.getType() == DbObject.USER) { 1158 User user = (User)grantee; 1159 if(user.getAdmin()) { 1160 isGrantable = "YES"; 1162 } 1163 } 1164 if(column == null) { 1165 add(rows,new String []{ 1166 null, identifier(grantee.getName()), catalog, identifier(table.getSchema().getName()), identifier(table.getName()), right, isGrantable }); 1174 } else { 1175 add(rows,new String []{ 1176 null, identifier(grantee.getName()), catalog, identifier(table.getSchema().getName()), identifier(table.getName()), identifier(column), right, isGrantable }); 1185 } 1186 } 1187 1188 private void add(ObjectArray rows, String [] strings) throws SQLException { 1189 Value[] values = new Value[strings.length]; 1190 for(int i=0; i<strings.length; i++) { 1191 String s = strings[i]; 1192 Value v = (s == null) ? (Value)ValueNull.INSTANCE : ValueString.get(s); 1193 Column col = columns[i]; 1194 v = v.convertTo(col.getType()); 1195 values[i] = v; 1196 } 1197 Row row = new Row(values); 1198 row.setPos(rows.size()); 1199 rows.add(row); 1200 } 1201 1202 public void checkRename() throws SQLException { 1203 throw Message.getUnsupportedException(); 1204 } 1205 1206 public void checkSupportAlter() throws SQLException { 1207 throw Message.getUnsupportedException(); 1208 } 1209 1210 public void truncate(Session session) throws SQLException { 1211 throw Message.getUnsupportedException(); 1212 } 1213 1214 public int getRowCount() { 1215 throw Message.getInternalError(); 1216 } 1217 1218 public boolean canGetRowCount() { 1219 return false; 1220 } 1221 1222 public boolean canDrop() { 1223 return false; 1224 } 1225 1226 public String getTableType() { 1227 return Table.SYSTEM_TABLE; 1228 } 1229 1230 public Index getScanIndex(Session session) throws SQLException { 1231 return new MetaIndex(this, columns, true); 1232 } 1233 1234 public ObjectArray getIndexes() { 1235 if(index == null) { 1236 return null; 1237 } 1238 ObjectArray list = new ObjectArray(); 1239 list.add(new MetaIndex(this, columns, true)); 1240 list.add(index); 1242 return list; 1243 } 1244 1245 public long getMaxDataModificationId() { 1246 return database.getModificationDataId(); 1247 } 1248 1249 public Index getUniqueIndex() { 1250 return null; 1251 } 1252 1253} 1254 | Popular Tags |