You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by th...@apache.org on 2021/07/30 16:28:12 UTC
[lucene-solr] branch branch_8x updated: SOLR-15570: Include fields
declared in the schema in table metadata (SQL) even if they are empty
(#2539)
This is an automated email from the ASF dual-hosted git repository.
thelabdude pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8x by this push:
new 1acb347 SOLR-15570: Include fields declared in the schema in table metadata (SQL) even if they are empty (#2539)
1acb347 is described below
commit 1acb34753bcb771586b8b4010417e79f80952205
Author: Timothy Potter <th...@gmail.com>
AuthorDate: Fri Jul 30 10:27:53 2021 -0600
SOLR-15570: Include fields declared in the schema in table metadata (SQL) even if they are empty (#2539)
---
solr/CHANGES.txt | 2 ++
.../org/apache/solr/handler/sql/SolrSchema.java | 29 +++++++++++++---------
.../org/apache/solr/handler/TestSQLHandler.java | 16 ++++++++++++
3 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6fbcbf5..dcd6dd3 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -37,6 +37,8 @@ Improvements
* SOLR-15549: ZkStateReader now supports connecting to 9.0 Solr Clouds (Houston Putman)
+* SOLR-15570: Include fields declared in the schema in table metadata (SQL) even if they are empty (Timothy Potter)
+
Optimizations
---------------------
* SOLR-15433: Replace transient core cache LRU by Caffeine cache. (Bruno Roustant)
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
index 413bbf7..d527018 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
@@ -23,6 +23,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import com.google.common.collect.ImmutableMap;
import org.apache.calcite.rel.type.RelDataType;
@@ -111,33 +113,40 @@ class SolrSchema extends AbstractSchema implements Closeable {
}
}
- private Map<String, LukeResponse.FieldTypeInfo> getFieldTypeInfo(final String collection) {
+ private LukeResponse getSchema(final String collection) {
final String zk = this.properties.getProperty("zk");
PKIAuthenticationPlugin.withServerIdentity(true);
try {
LukeRequest lukeRequest = new LukeRequest();
- lukeRequest.setShowSchema(true); // for custom type info ...
+ lukeRequest.setShowSchema(true); // for empty fields and custom type info ...
lukeRequest.setNumTerms(0);
- return lukeRequest.process(solrClientCache.getCloudSolrClient(zk), collection).getFieldTypeInfo();
+ return lukeRequest.process(solrClientCache.getCloudSolrClient(zk), collection);
} catch (SolrServerException | IOException e) {
throw new RuntimeException(e);
} finally {
PKIAuthenticationPlugin.withServerIdentity(false);
}
}
-
+
RelProtoDataType getRelDataType(String collection) {
// Temporary type factory, just for the duration of this method. Allowable
// because we're creating a proto-type, not a type; before being used, the
// proto-type will be copied into a real type factory.
final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
final RelDataTypeFactory.Builder fieldInfo = typeFactory.builder();
- Map<String, LukeResponse.FieldInfo> luceneFieldInfoMap = getFieldInfo(collection);
+
+ // Get fields that have data, including dynamic field instances
+ Map<String, LukeResponse.FieldInfo> fieldsInUseMap = getFieldInfo(collection);
+
+ LukeResponse schema = getSchema(collection);
+ // merge the actual fields in use returned by Luke with the declared fields in the schema that are empty
+ Map<String, LukeResponse.FieldInfo> combinedFields = Stream.of(fieldsInUseMap, schema.getFieldInfo())
+ .flatMap(map -> map.entrySet().stream())
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1));
- Map<String, LukeResponse.FieldTypeInfo> fieldTypeInfoMap = null; // loaded lazily if needed
Map<String, Class<?>> javaClassForTypeMap = new HashMap<>(); // local cache for custom field types we've already resolved
- for (Map.Entry<String, LukeResponse.FieldInfo> entry : luceneFieldInfoMap.entrySet()) {
+ for (Map.Entry<String, LukeResponse.FieldInfo> entry : combinedFields.entrySet()) {
LukeResponse.FieldInfo luceneFieldInfo = entry.getValue();
String luceneFieldType = luceneFieldInfo.getType();
@@ -173,11 +182,7 @@ class SolrSchema extends AbstractSchema implements Closeable {
default:
Class<?> javaClass = javaClassForTypeMap.get(luceneFieldType);
if (javaClass == null) {
- if (fieldTypeInfoMap == null) {
- // lazily go to luke for the field type info ...
- fieldTypeInfoMap = getFieldTypeInfo(collection);
- }
- javaClass = guessJavaClassForFieldType(fieldTypeInfoMap.get(luceneFieldType));
+ javaClass = guessJavaClassForFieldType(schema.getFieldTypeInfo().get(luceneFieldType));
javaClassForTypeMap.put(luceneFieldType, javaClass);
}
type = typeFactory.createJavaType(javaClass);
diff --git a/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java b/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
index 06c9edd..136ebce 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
@@ -2281,4 +2281,20 @@ public class TestSQLHandler extends SolrCloudTestCase {
// select * w/o limit is not supported by Solr SQL
expectThrows(IOException.class, () -> expectResults("SELECT * FROM $ALIAS", -1));
}
+
+ @Test
+ public void testSelectEmptyField() throws Exception {
+ new UpdateRequest()
+ .add("id", "01")
+ .add("id", "02")
+ .add("id", "03")
+ .add("id", "04")
+ .add("id", "05")
+ .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+
+ // stringx is declared in the schema but has no docs
+ expectResults("SELECT id, stringx FROM $ALIAS", 5);
+ // notafield_i matches a dynamic field pattern but has no docs, so don't allow this
+ expectThrows(IOException.class, () -> expectResults("SELECT id, stringx, notafield_i FROM $ALIAS", 5));
+ }
}