clintropolis commented on code in PR #19830:
URL: https://github.com/apache/druid/pull/19830#discussion_r4029994048
##########
server/src/main/java/org/apache/druid/catalog/model/table/DatasourceDefn.java:
##########
@@ -110,6 +124,115 @@ public void validate(ResolvedTable table)
// fail fast instead of surfacing layout problems at ingest time.
baseTable.createSpec(table.spec().columns());
}
+ validateProjections(table);
+ }
+
+ /**
+ * Cross-validate the declared projections. Names must be unique, a
projection must not be coarser than the segments
+ * it lives in, and the types it groups by must agree with the types the
table declares. For a sealed table the
+ * declared columns are the whole schema, so a projection that reads a
column the table does not declare can never be
+ * built and is rejected; for a non-sealed table ingestion may add columns
the catalog has not seen, so only the
+ * projections' internal consistency is checked.
+ */
+ private void validateProjections(ResolvedTable table)
+ {
+ final List<DatasourceProjectionMetadata> projections =
table.decodeProperty(PROJECTIONS_KEYS_PROPERTY);
+ if (projections == null || projections.isEmpty()) {
+ return;
+ }
+
+ final List<AggregateProjectionSpec> specs = new
ArrayList<>(projections.size());
+ for (DatasourceProjectionMetadata projection : projections) {
+ if (projection == null || projection.getSpec() == null) {
+ throw InvalidInput.exception("Projections must each have a [spec]");
+ }
+ specs.add(projection.getSpec());
+ }
+
+ final String granularity =
table.stringProperty(SEGMENT_GRANULARITY_PROPERTY);
+ DataSchema.validateProjections(
+ specs,
+ granularity == null ? null :
CatalogUtils.asDruidGranularity(granularity)
+ );
+
+ validateProjectionGroupingTypes(table, specs);
+
+ if (!table.booleanProperty(SEALED_PROPERTY) || table.spec().columns() ==
null) {
+ return;
+ }
+ final Set<String> declared = new
HashSet<>(CatalogUtils.columnNames(table.spec().columns()));
+ declared.add(Columns.TIME_COLUMN);
+ for (AggregateProjectionSpec spec : specs) {
+ final Set<String> available = new HashSet<>(declared);
+ for (VirtualColumn virtualColumn :
spec.getVirtualColumns().getVirtualColumns()) {
+ available.add(virtualColumn.getOutputName());
+ }
+ for (String required : requiredColumns(spec)) {
+ if (!available.contains(required)) {
+ throw InvalidInput.exception(
+ "Projection [%s] references column [%s], which table [%s] does
not declare",
+ spec.getName(),
+ required,
+ table.spec().type()
Review Comment:
table name isn't actually available here but i think that is probably ok
since I think there could be at most 1 table involved in these statements
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]