Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java @ 649:060347aa81ea
By fixing methods getPrimaryKeys(), getBestRowIdentifier() and getIndexInfo() for local temporary tables, it also caused it to fail for global temporary tables in schema tmp.
Corrected this, such that it now works for local and global temporary tables. Added tests.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Wed, 11 May 2022 17:34:00 +0200 (2022-05-11) |
parents | fbed03097738 |
children | 6a34d2c36dec |
comparison
equal
deleted
inserted
replaced
648:03e0f577db00 | 649:060347aa81ea |
---|---|
2407 final String table, | 2407 final String table, |
2408 final int scope, | 2408 final int scope, |
2409 final boolean nullable | 2409 final boolean nullable |
2410 ) throws SQLException | 2410 ) throws SQLException |
2411 { | 2411 { |
2412 final String sysORtmp = (schema != null && "tmp".equals(schema)) ? "\"tmp\"" : "\"sys\""; | |
2413 | |
2414 // first find out if the table has a Primary Key. If it does, we should return only those columns | 2412 // first find out if the table has a Primary Key. If it does, we should return only those columns |
2415 boolean hasPK = false; | 2413 boolean hasPK = false; |
2416 ResultSet pkey = null; | 2414 ResultSet pkey = null; |
2417 try { | 2415 try { |
2418 pkey = getPrimaryKeys(catalog, schema, table); | 2416 pkey = getPrimaryKeys(catalog, schema, table); |
2421 } | 2419 } |
2422 } catch (SQLException e) { | 2420 } catch (SQLException e) { |
2423 // ignore | 2421 // ignore |
2424 } finally { | 2422 } finally { |
2425 MonetConnection.closeResultsetStatement(pkey, null); | 2423 MonetConnection.closeResultsetStatement(pkey, null); |
2424 pkey = null; | |
2426 } | 2425 } |
2427 | 2426 |
2428 // TODO: when there is No PK and there are multiple unique constraints, pick only the unique constraint which has a) the least number of columns and b) the smallest total(size in bytes) | 2427 // TODO: when there is No PK and there are multiple unique constraints, pick only the unique constraint which has a) the least number of columns and b) the smallest total(size in bytes) |
2429 // TODO: when there is No PK and No unique constraints, we potentially should return all columns of the table (else in SQuirreL no header is shown in the "Row IDs" tab) | 2428 // TODO: when there is No PK and No unique constraints, we potentially should return all columns of the table (else in SQuirreL no header is shown in the "Row IDs" tab) |
2430 | 2429 |
2431 final StringBuilder query = new StringBuilder(1500); | 2430 final StringBuilder query = new StringBuilder(3000); |
2432 query.append("SELECT "); | 2431 query.append("SELECT "); |
2433 if (!hasPK) { | 2432 if (!hasPK) { |
2434 // Note: currently DISTINCT is needed to filter out possible duplicate column names when there are multiple unique constraints !! | 2433 // Note: currently DISTINCT is needed to filter out possible duplicate column names when there are multiple unique constraints !! |
2435 // TODO: when no PK and there are multiple unique constraints determine which one to select such that DISTINCT keyword is not needed anymore | 2434 // TODO: when no PK and there are multiple unique constraints determine which one to select such that DISTINCT keyword is not needed anymore |
2436 query.append("DISTINCT "); | 2435 query.append("DISTINCT "); |
2441 "c.\"type\" AS \"TYPE_NAME\", " + | 2440 "c.\"type\" AS \"TYPE_NAME\", " + |
2442 "c.\"type_digits\" AS \"COLUMN_SIZE\", " + | 2441 "c.\"type_digits\" AS \"COLUMN_SIZE\", " + |
2443 "cast(0 as int) AS \"BUFFER_LENGTH\", " + | 2442 "cast(0 as int) AS \"BUFFER_LENGTH\", " + |
2444 "cast(c.\"type_scale\" AS smallint) AS \"DECIMAL_DIGITS\", " + | 2443 "cast(c.\"type_scale\" AS smallint) AS \"DECIMAL_DIGITS\", " + |
2445 "cast(").append(DatabaseMetaData.bestRowNotPseudo).append(" AS smallint) AS \"PSEUDO_COLUMN\" " + | 2444 "cast(").append(DatabaseMetaData.bestRowNotPseudo).append(" AS smallint) AS \"PSEUDO_COLUMN\" " + |
2446 "FROM ").append(sysORtmp).append(".\"keys\" k " + | 2445 "FROM \"sys\".\"keys\" k " + |
2447 "JOIN ").append(sysORtmp).append(".\"objects\" o ON k.\"id\" = o.\"id\" " + | 2446 "JOIN \"sys\".\"objects\" o ON k.\"id\" = o.\"id\" " + |
2448 "JOIN ").append(sysORtmp).append(".\"_columns\" c ON (k.\"table_id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + | 2447 "JOIN \"sys\".\"_columns\" c ON (k.\"table_id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + |
2449 "JOIN ").append(sysORtmp).append(".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + | 2448 "JOIN \"sys\".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + |
2450 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | 2449 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + |
2451 "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) | 2450 "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) |
2452 | 2451 |
2453 if (catalog != null && !catalog.isEmpty()) { | 2452 if (catalog != null && !catalog.isEmpty()) { |
2454 // non-empty catalog selection. | 2453 // non-empty catalog selection. |
2472 } else { | 2471 } else { |
2473 query.append(" AND 1=0"); | 2472 query.append(" AND 1=0"); |
2474 } | 2473 } |
2475 } | 2474 } |
2476 | 2475 |
2476 final boolean includetmp = (schema == null) | |
2477 || (schema != null && ("tmp".equals(schema) || schema.contains("%") || schema.contains("_"))); | |
2478 if (includetmp) { | |
2479 // we must also include the primary key or unique constraint of local temporary tables which are stored in tmp.keys, tmp.objects, tmp._tables and tmp._columns | |
2480 query.append(" UNION ALL "); | |
2481 query.append("SELECT "); | |
2482 if (!hasPK) { | |
2483 // Note: currently DISTINCT is needed to filter out possible duplicate column names when there are multiple unique constraints !! | |
2484 // TODO: when no PK and there are multiple unique constraints determine which one to select such that DISTINCT keyword is not needed anymore | |
2485 query.append("DISTINCT "); | |
2486 } | |
2487 query.append("cast(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + | |
2488 "c.\"name\" AS \"COLUMN_NAME\", " + | |
2489 "cast(").append(MonetDriver.getSQLTypeMap("c.\"type\"")).append(" AS int) AS \"DATA_TYPE\", " + | |
2490 "c.\"type\" AS \"TYPE_NAME\", " + | |
2491 "c.\"type_digits\" AS \"COLUMN_SIZE\", " + | |
2492 "cast(0 as int) AS \"BUFFER_LENGTH\", " + | |
2493 "cast(c.\"type_scale\" AS smallint) AS \"DECIMAL_DIGITS\", " + | |
2494 "cast(").append(DatabaseMetaData.bestRowNotPseudo).append(" AS smallint) AS \"PSEUDO_COLUMN\" " + | |
2495 "FROM \"tmp\".\"keys\" k " + | |
2496 "JOIN \"tmp\".\"objects\" o ON k.\"id\" = o.\"id\" " + | |
2497 "JOIN \"tmp\".\"_columns\" c ON (k.\"table_id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + | |
2498 "JOIN \"tmp\".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + | |
2499 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | |
2500 "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) | |
2501 | |
2502 if (catalog != null && !catalog.isEmpty()) { | |
2503 // non-empty catalog selection. | |
2504 // as we do not support catalogs this always results in no rows returned | |
2505 query.append(" AND 1=0"); | |
2506 } else { | |
2507 if (scope == DatabaseMetaData.bestRowSession | |
2508 || scope == DatabaseMetaData.bestRowTransaction | |
2509 || scope == DatabaseMetaData.bestRowTemporary) { | |
2510 if (schema != null) { | |
2511 // do not allow wildcard matching with LIKE, as the resultset does not include the schema info | |
2512 query.append(" AND s.\"name\" = ").append(MonetWrapper.sq(schema)); | |
2513 } | |
2514 if (table != null) { | |
2515 // do not allow wildcard matching with LIKE, as the resultset does not include the table info | |
2516 query.append(" AND t.\"name\" = ").append(MonetWrapper.sq(table)); | |
2517 } | |
2518 if (!nullable) { | |
2519 query.append(" AND c.\"null\" = false"); | |
2520 } | |
2521 } else { | |
2522 query.append(" AND 1=0"); | |
2523 } | |
2524 } | |
2525 } | |
2526 | |
2477 // was: query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); | 2527 // was: query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); |
2478 // But as of Jan2022 this ordering returns error: SELECT: with DISTINCT ORDER BY expressions must appear in select list | 2528 // But as of Jan2022 this ordering returns error: SELECT: with DISTINCT ORDER BY expressions must appear in select list |
2479 // so had to remove the o.\"nr\", part when there is No PKey. This means the columns are than ordered on names instead of creation order in their unique constraint definition | 2529 // so had to remove the o.\"nr\", part when there is No PKey. This means the columns are than ordered on names instead of creation order in their unique constraint definition |
2480 query.append(" ORDER BY \"SCOPE\", "); | 2530 query.append(" ORDER BY \"SCOPE\", "); |
2481 if (hasPK) | 2531 if (hasPK && !includetmp) |
2482 query.append("o.\"nr\", "); | 2532 query.append("o.\"nr\", "); |
2483 query.append("\"COLUMN_NAME\""); | 2533 query.append("\"COLUMN_NAME\""); |
2484 | 2534 |
2485 return executeMetaDataQuery(query.toString()); | 2535 return executeMetaDataQuery(query.toString()); |
2486 } | 2536 } |
2561 final String catalog, | 2611 final String catalog, |
2562 final String schema, | 2612 final String schema, |
2563 final String table | 2613 final String table |
2564 ) throws SQLException | 2614 ) throws SQLException |
2565 { | 2615 { |
2566 final String sysORtmp = (schema != null && "tmp".equals(schema)) ? "\"tmp\"" : "\"sys\""; | 2616 final StringBuilder query = new StringBuilder(1200); |
2567 final StringBuilder query = new StringBuilder(600); | |
2568 query.append("SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + | 2617 query.append("SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + |
2569 "s.\"name\" AS \"TABLE_SCHEM\", " + | 2618 "s.\"name\" AS \"TABLE_SCHEM\", " + |
2570 "t.\"name\" AS \"TABLE_NAME\", " + | 2619 "t.\"name\" AS \"TABLE_NAME\", " + |
2571 "o.\"name\" AS \"COLUMN_NAME\", " + | 2620 "o.\"name\" AS \"COLUMN_NAME\", " + |
2572 "cast(1 + o.\"nr\" AS smallint) AS \"KEY_SEQ\", " + | 2621 "cast(1 + o.\"nr\" AS smallint) AS \"KEY_SEQ\", " + |
2573 " k.\"name\" AS \"PK_NAME\" " + | 2622 "k.\"name\" AS \"PK_NAME\" " + |
2574 "FROM ").append(sysORtmp).append(".\"keys\" k " + | 2623 "FROM \"sys\".\"keys\" k " + |
2575 "JOIN ").append(sysORtmp).append(".\"objects\" o ON k.\"id\" = o.\"id\" " + | 2624 "JOIN \"sys\".\"objects\" o ON k.\"id\" = o.\"id\" " + |
2576 "JOIN ").append(sysORtmp).append(".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + | 2625 "JOIN \"sys\".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + |
2577 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | 2626 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + |
2578 "WHERE k.\"type\" = 0"); // only primary keys (type = 0) | 2627 "WHERE k.\"type\" = 0"); // only primary keys (type = 0) |
2579 | 2628 |
2580 if (catalog != null && !catalog.isEmpty()) { | 2629 if (catalog != null && !catalog.isEmpty()) { |
2581 // non-empty catalog selection. | 2630 // non-empty catalog selection. |
2585 if (schema != null && !schema.equals("%")) { | 2634 if (schema != null && !schema.equals("%")) { |
2586 query.append(" AND s.\"name\" ").append(composeMatchPart(schema)); | 2635 query.append(" AND s.\"name\" ").append(composeMatchPart(schema)); |
2587 } | 2636 } |
2588 if (table != null && !table.equals("%")) { | 2637 if (table != null && !table.equals("%")) { |
2589 query.append(" AND t.\"name\" ").append(composeMatchPart(table)); | 2638 query.append(" AND t.\"name\" ").append(composeMatchPart(table)); |
2639 } | |
2640 } | |
2641 | |
2642 final boolean includetmp = (schema == null) | |
2643 || (schema != null && ("tmp".equals(schema) || schema.contains("%") || schema.contains("_"))); | |
2644 if (includetmp) { | |
2645 // we must also include the keys of local temporary tables which are stored in tmp.keys, tmp.objects and tmp._tables | |
2646 query.append(" UNION ALL "); | |
2647 query.append("SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + | |
2648 "s.\"name\" AS \"TABLE_SCHEM\", " + | |
2649 "t.\"name\" AS \"TABLE_NAME\", " + | |
2650 "o.\"name\" AS \"COLUMN_NAME\", " + | |
2651 "cast(1 + o.\"nr\" AS smallint) AS \"KEY_SEQ\", " + | |
2652 "k.\"name\" AS \"PK_NAME\" " + | |
2653 "FROM \"tmp\".\"keys\" k " + | |
2654 "JOIN \"tmp\".\"objects\" o ON k.\"id\" = o.\"id\" " + | |
2655 "JOIN \"tmp\".\"_tables\" t ON k.\"table_id\" = t.\"id\" " + | |
2656 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | |
2657 "WHERE k.\"type\" = 0"); // only primary keys (type = 0) | |
2658 | |
2659 if (catalog != null && !catalog.isEmpty()) { | |
2660 // non-empty catalog selection. | |
2661 // as we do not support catalogs this always results in no rows returned | |
2662 query.append(" AND 1=0"); | |
2663 } else { | |
2664 if (schema != null && !schema.equals("%")) { | |
2665 query.append(" AND s.\"name\" ").append(composeMatchPart(schema)); | |
2666 } | |
2667 if (table != null && !table.equals("%")) { | |
2668 query.append(" AND t.\"name\" ").append(composeMatchPart(table)); | |
2669 } | |
2590 } | 2670 } |
2591 } | 2671 } |
2592 | 2672 |
2593 query.append(" ORDER BY \"TABLE_SCHEM\", \"TABLE_NAME\", \"COLUMN_NAME\""); | 2673 query.append(" ORDER BY \"TABLE_SCHEM\", \"TABLE_NAME\", \"COLUMN_NAME\""); |
2594 | 2674 |
3079 } finally { | 3159 } finally { |
3080 MonetConnection.closeResultsetStatement(count, null); | 3160 MonetConnection.closeResultsetStatement(count, null); |
3081 } | 3161 } |
3082 } | 3162 } |
3083 | 3163 |
3084 final String sysORtmp = (schema != null && "tmp".equals(schema)) ? "\"tmp\"" : "\"sys\""; | 3164 final StringBuilder query = new StringBuilder(2500); |
3085 final StringBuilder query = new StringBuilder(1250); | |
3086 query.append( | 3165 query.append( |
3087 "SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + | 3166 "SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + |
3088 "s.\"name\" AS \"TABLE_SCHEM\", " + | 3167 "s.\"name\" AS \"TABLE_SCHEM\", " + |
3089 "t.\"name\" AS \"TABLE_NAME\", " + | 3168 "t.\"name\" AS \"TABLE_NAME\", " + |
3090 "CASE WHEN k.\"name\" IS NULL THEN true ELSE false END AS \"NON_UNIQUE\", " + | 3169 "CASE WHEN k.\"name\" IS NULL THEN true ELSE false END AS \"NON_UNIQUE\", " + |
3095 "c.\"name\" AS \"COLUMN_NAME\", " + | 3174 "c.\"name\" AS \"COLUMN_NAME\", " + |
3096 "cast(null AS char(1)) AS \"ASC_OR_DESC\", " + // sort sequence currently not supported in keys or indexes in MonetDB | 3175 "cast(null AS char(1)) AS \"ASC_OR_DESC\", " + // sort sequence currently not supported in keys or indexes in MonetDB |
3097 "cast(").append(table_row_count).append(" AS int) AS \"CARDINALITY\", " + | 3176 "cast(").append(table_row_count).append(" AS int) AS \"CARDINALITY\", " + |
3098 "cast(0 AS int) AS \"PAGES\", " + | 3177 "cast(0 AS int) AS \"PAGES\", " + |
3099 "cast(null AS char(1)) AS \"FILTER_CONDITION\" " + | 3178 "cast(null AS char(1)) AS \"FILTER_CONDITION\" " + |
3100 "FROM ").append(sysORtmp).append(".\"idxs\" i " + | 3179 "FROM \"sys\".\"idxs\" i " + |
3101 "JOIN ").append(sysORtmp).append(".\"_tables\" t ON i.\"table_id\" = t.\"id\" " + | 3180 "JOIN \"sys\".\"_tables\" t ON i.\"table_id\" = t.\"id\" " + |
3102 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | 3181 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + |
3103 "JOIN ").append(sysORtmp).append(".\"objects\" o ON i.\"id\" = o.\"id\" " + | 3182 "JOIN \"sys\".\"objects\" o ON i.\"id\" = o.\"id\" " + |
3104 "JOIN ").append(sysORtmp).append(".\"_columns\" c ON (t.\"id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + | 3183 "JOIN \"sys\".\"_columns\" c ON (t.\"id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + |
3105 "LEFT OUTER JOIN ").append(sysORtmp).append(".\"keys\" k ON (i.\"name\" = k.\"name\" AND i.\"table_id\" = k.\"table_id\" AND k.\"type\" IN (0,1)) "); // primary (0) and unique keys (1) only | 3184 "LEFT OUTER JOIN \"sys\".\"keys\" k ON (i.\"name\" = k.\"name\" AND i.\"table_id\" = k.\"table_id\" AND k.\"type\" IN (0,1)) "); // primary (0) and unique keys (1) only |
3106 | 3185 |
3107 if (catalog != null && !catalog.isEmpty()) { | 3186 if (catalog != null && !catalog.isEmpty()) { |
3108 // non-empty catalog selection. | 3187 // non-empty catalog selection. |
3109 // as we do not support catalogs this always results in no rows returned | 3188 // as we do not support catalogs this always results in no rows returned |
3110 query.append("WHERE 1=0"); | 3189 query.append("WHERE 1=0"); |
3120 needWhere = false; | 3199 needWhere = false; |
3121 } | 3200 } |
3122 if (unique) { | 3201 if (unique) { |
3123 query.append(needWhere ? "WHERE" : " AND") | 3202 query.append(needWhere ? "WHERE" : " AND") |
3124 .append(" k.\"name\" IS NOT NULL"); | 3203 .append(" k.\"name\" IS NOT NULL"); |
3204 } | |
3205 } | |
3206 | |
3207 final boolean includetmp = (schema == null) | |
3208 || (schema != null && ("tmp".equals(schema) || schema.contains("%") || schema.contains("_"))); | |
3209 if (includetmp) { | |
3210 // we must also include the indexes of local temporary tables which are stored in tmp.idxs, tmp._tables, tmp._columns, tmp.objects and tmp.keys | |
3211 query.append(" UNION ALL "); | |
3212 query.append( | |
3213 "SELECT cast(null AS char(1)) AS \"TABLE_CAT\", " + | |
3214 "s.\"name\" AS \"TABLE_SCHEM\", " + | |
3215 "t.\"name\" AS \"TABLE_NAME\", " + | |
3216 "CASE WHEN k.\"name\" IS NULL THEN true ELSE false END AS \"NON_UNIQUE\", " + | |
3217 "cast(null AS char(1)) AS \"INDEX_QUALIFIER\", " + | |
3218 "i.\"name\" AS \"INDEX_NAME\", " + | |
3219 "CASE i.\"type\" WHEN 0 THEN ").append(DatabaseMetaData.tableIndexHashed).append(" ELSE ").append(DatabaseMetaData.tableIndexOther).append(" END AS \"TYPE\", " + | |
3220 "cast(o.\"nr\" +1 AS smallint) AS \"ORDINAL_POSITION\", "+ | |
3221 "c.\"name\" AS \"COLUMN_NAME\", " + | |
3222 "cast(null AS char(1)) AS \"ASC_OR_DESC\", " + // sort sequence currently not supported in keys or indexes in MonetDB | |
3223 "cast(").append(table_row_count).append(" AS int) AS \"CARDINALITY\", " + | |
3224 "cast(0 AS int) AS \"PAGES\", " + | |
3225 "cast(null AS char(1)) AS \"FILTER_CONDITION\" " + | |
3226 "FROM \"tmp\".\"idxs\" i " + | |
3227 "JOIN \"tmp\".\"_tables\" t ON i.\"table_id\" = t.\"id\" " + | |
3228 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | |
3229 "JOIN \"tmp\".\"objects\" o ON i.\"id\" = o.\"id\" " + | |
3230 "JOIN \"tmp\".\"_columns\" c ON (t.\"id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + | |
3231 "LEFT OUTER JOIN \"tmp\".\"keys\" k ON (i.\"name\" = k.\"name\" AND i.\"table_id\" = k.\"table_id\" AND k.\"type\" IN (0,1)) "); // primary (0) and unique keys (1) only | |
3232 | |
3233 if (catalog != null && !catalog.isEmpty()) { | |
3234 // non-empty catalog selection. | |
3235 // as we do not support catalogs this always results in no rows returned | |
3236 query.append("WHERE 1=0"); | |
3237 } else { | |
3238 boolean needWhere = true; | |
3239 if (schema != null && !schema.equals("%")) { | |
3240 query.append("WHERE s.\"name\" ").append(composeMatchPart(schema)); | |
3241 needWhere = false; | |
3242 } | |
3243 if (table != null && !table.equals("%")) { | |
3244 query.append(needWhere ? "WHERE" : " AND") | |
3245 .append(" t.\"name\" ").append(composeMatchPart(table)); | |
3246 needWhere = false; | |
3247 } | |
3248 if (unique) { | |
3249 query.append(needWhere ? "WHERE" : " AND") | |
3250 .append(" k.\"name\" IS NOT NULL"); | |
3251 } | |
3125 } | 3252 } |
3126 } | 3253 } |
3127 | 3254 |
3128 query.append(" ORDER BY \"NON_UNIQUE\", \"TYPE\", \"INDEX_NAME\", \"ORDINAL_POSITION\""); | 3255 query.append(" ORDER BY \"NON_UNIQUE\", \"TYPE\", \"INDEX_NAME\", \"ORDINAL_POSITION\""); |
3129 | 3256 |