|
| 1 | +// Licensed to the Apache Software Foundation (ASF) under one |
| 2 | +// or more contributor license agreements. See the NOTICE file |
| 3 | +// distributed with this work for additional information |
| 4 | +// regarding copyright ownership. The ASF licenses this file |
| 5 | +// to you under the Apache License, Version 2.0 (the |
| 6 | +// "License"); you may not use this file except in compliance |
| 7 | +// with the License. You may obtain a copy of the License at |
| 8 | +// |
| 9 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +// |
| 11 | +// Unless required by applicable law or agreed to in writing, |
| 12 | +// software distributed under the License is distributed on an |
| 13 | +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 14 | +// KIND, either express or implied. See the License for the |
| 15 | +// specific language governing permissions and limitations |
| 16 | +// under the License. |
| 17 | + |
| 18 | +suite("test_lance_index_entries", "p0,external") { |
| 19 | + String enabled = context.config.otherConfigs.get("enableIcebergTest") |
| 20 | + if (enabled == null || !enabled.equalsIgnoreCase("true")) { |
| 21 | + logger.info("disable Lance index entries test because the Iceberg MinIO environment is disabled.") |
| 22 | + return |
| 23 | + } |
| 24 | + |
| 25 | + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") |
| 26 | + String minioPort = context.config.otherConfigs.get("iceberg_minio_port") |
| 27 | + String lanceRestPort = context.config.otherConfigs.get("lance_rest_port") |
| 28 | + String filesystemCatalog = "test_lance_index_entries" |
| 29 | + String restCatalog = "test_lance_index_entries_rest" |
| 30 | + String user = "test_lance_index_entries_user" |
| 31 | + String password = "C123_567p" |
| 32 | + |
| 33 | + // Index UUIDs are fixture-build artifacts; assert the shape instead of the value. |
| 34 | + String uuidShape = "'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\$'" |
| 35 | + |
| 36 | + sql """DROP CATALOG IF EXISTS `${filesystemCatalog}`""" |
| 37 | + sql """DROP CATALOG IF EXISTS `${restCatalog}`""" |
| 38 | + try_sql "DROP USER '${user}'@'%'" |
| 39 | + |
| 40 | + try { |
| 41 | + sql """ |
| 42 | + CREATE CATALOG `${filesystemCatalog}` PROPERTIES ( |
| 43 | + "type" = "lance", |
| 44 | + "lance.catalog.type" = "filesystem", |
| 45 | + "warehouse" = "s3://warehouse/lance", |
| 46 | + "s3.endpoint" = "http://${externalEnvIp}:${minioPort}", |
| 47 | + "s3.access_key" = "admin", |
| 48 | + "s3.secret_key" = "password", |
| 49 | + "s3.region" = "us-east-1", |
| 50 | + "use_path_style" = "true" |
| 51 | + ) |
| 52 | + """ |
| 53 | + |
| 54 | + order_qt_entries_vector """ |
| 55 | + SELECT CatalogName, DatabaseName, TableName, IndexName, |
| 56 | + IF(IndexUuid REGEXP ${uuidShape}, 'UUID', CONCAT('BAD:', IndexUuid)) AS UuidShape, |
| 57 | + IF(DatasetVersion >= 1, 'SET', 'BAD') AS VersionState |
| 58 | + FROM lance_index_entries("table" = "${filesystemCatalog}.doris.vs_ivf_pq_f32") |
| 59 | + """ |
| 60 | + |
| 61 | + qt_entries_vector_count """ |
| 62 | + SELECT COUNT(*), COUNT(DISTINCT IndexName), COUNT(DISTINCT IndexUuid) |
| 63 | + FROM lance_index_entries("table" = "${filesystemCatalog}.doris.vs_ivf_pq_f32") |
| 64 | + """ |
| 65 | + |
| 66 | + order_qt_entries_nested """ |
| 67 | + SELECT CatalogName, DatabaseName, TableName, IndexName, |
| 68 | + IF(IndexUuid REGEXP ${uuidShape}, 'UUID', CONCAT('BAD:', IndexUuid)) AS UuidShape, |
| 69 | + IF(DatasetVersion >= 1, 'SET', 'BAD') AS VersionState |
| 70 | + FROM lance_index_entries("table" = "${filesystemCatalog}.doris.nested_index") |
| 71 | + """ |
| 72 | + |
| 73 | + qt_entries_no_indexes """ |
| 74 | + SELECT COUNT(*) FROM lance_index_entries("table" = "${filesystemCatalog}.doris.predicate_pushdown") |
| 75 | + """ |
| 76 | + |
| 77 | + // An ordinary predicate filters the bounded result. |
| 78 | + qt_entries_predicate """ |
| 79 | + SELECT IndexName FROM lance_index_entries("table" = "${filesystemCatalog}.doris.vs_ivf_pq_f32") |
| 80 | + WHERE IndexName = "no_such_index" |
| 81 | + """ |
| 82 | + |
| 83 | + sql """ |
| 84 | + CREATE CATALOG `${restCatalog}` PROPERTIES ( |
| 85 | + "type" = "lance", |
| 86 | + "lance.catalog.type" = "rest", |
| 87 | + "lance.rest.uri" = "http://${externalEnvIp}:${lanceRestPort}", |
| 88 | + "lance.rest.security.type" = "bearer", |
| 89 | + "lance.rest.bearer-token" = "doris-lance-rest-test-token", |
| 90 | + "lance.namespace.root_database" = "default", |
| 91 | + "s3.endpoint" = "http://${externalEnvIp}:${minioPort}", |
| 92 | + "s3.region" = "us-east-1", |
| 93 | + "use_path_style" = "true", |
| 94 | + "test_connection" = "true" |
| 95 | + ) |
| 96 | + """ |
| 97 | + |
| 98 | + test { |
| 99 | + sql """SELECT * FROM lance_index_entries("table" = "${restCatalog}.`default`.all_types")""" |
| 100 | + exception "lance_index_entries is not supported for Lance REST catalogs" |
| 101 | + } |
| 102 | + |
| 103 | + sql """CREATE USER '${user}'@'%' IDENTIFIED BY '${password}'""" |
| 104 | + sql """GRANT SELECT_PRIV ON regression_test TO '${user}'@'%'""" |
| 105 | + if (isCloudMode()) { |
| 106 | + def clusters = sql "SHOW CLUSTERS" |
| 107 | + assertTrue(!clusters.isEmpty()) |
| 108 | + sql """GRANT USAGE_PRIV ON CLUSTER `${clusters[0][0]}` TO '${user}'@'%'""" |
| 109 | + } |
| 110 | + |
| 111 | + connect(user, password, context.config.jdbcUrl) { |
| 112 | + test { |
| 113 | + sql """SELECT * FROM lance_index_entries("table" = "${filesystemCatalog}.doris.vs_ivf_pq_f32")""" |
| 114 | + exception "denied" |
| 115 | + } |
| 116 | + } |
| 117 | + } finally { |
| 118 | + try_sql "DROP USER '${user}'@'%'" |
| 119 | + // Keep both catalogs for debugging when the suite fails. |
| 120 | + } |
| 121 | +} |
0 commit comments