-
Notifications
You must be signed in to change notification settings - Fork 3k
Core: View representation core implementation #6598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,21 +18,16 @@ | |
| */ | ||
| package org.apache.iceberg.view; | ||
|
|
||
| import java.util.Locale; | ||
| import org.immutables.value.Value; | ||
|
|
||
| @Value.Immutable | ||
| public interface ViewRepresentation { | ||
|
|
||
| enum Type { | ||
| SQL; | ||
| class Type { | ||
| private Type() {} | ||
|
|
||
| public static Type fromString(String typeName) { | ||
| return valueOf(typeName.toUpperCase(Locale.ENGLISH)); | ||
| } | ||
|
|
||
| public String typeName() { | ||
| return name().toLowerCase(Locale.ENGLISH); | ||
| } | ||
| public static final String SQL = "sql"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why change this from an enum to a String?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made the suggestion since I see some other enum like classes are also implemented directly as strings, such as
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it depends on whether we want to use this enum in switch statements in our code or if we want to extend it. For example, we could have a reference to the parser in the enum so we look up the symbol and then call something like Since we only have the parser selection right now, it doesn't seem like it matters much. |
||
| } | ||
|
|
||
| Type type(); | ||
| String type(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.iceberg.view; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonGenerator; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import java.io.IOException; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import org.apache.iceberg.catalog.Namespace; | ||
| import org.apache.iceberg.relocated.com.google.common.base.Preconditions; | ||
| import org.apache.iceberg.relocated.com.google.common.collect.Iterables; | ||
| import org.apache.iceberg.util.JsonUtil; | ||
|
|
||
| class SQLViewRepresentationParser { | ||
| private static final String SQL = "sql"; | ||
| private static final String DIALECT = "dialect"; | ||
| private static final String SCHEMA_ID = "schema-id"; | ||
| private static final String DEFAULT_CATALOG = "default-catalog"; | ||
| private static final String DEFAULT_NAMESPACE = "default-namespace"; | ||
| private static final String FIELD_ALIASES = "field-aliases"; | ||
| private static final String FIELD_COMMENTS = "field-comments"; | ||
|
|
||
| private SQLViewRepresentationParser() {} | ||
|
|
||
| static String toJson(SQLViewRepresentation sqlViewRepresentation) { | ||
| return JsonUtil.generate(gen -> toJson(sqlViewRepresentation, gen), false); | ||
| } | ||
|
|
||
| static void toJson(SQLViewRepresentation view, JsonGenerator generator) throws IOException { | ||
| Preconditions.checkArgument(view != null, "Invalid SQL view representation: null"); | ||
| generator.writeStartObject(); | ||
| generator.writeStringField(ViewRepresentationParser.TYPE, view.type()); | ||
| generator.writeStringField(SQL, view.sql()); | ||
| generator.writeStringField(DIALECT, view.dialect()); | ||
|
|
||
| if (view.schemaId() != null) { | ||
| generator.writeNumberField(SCHEMA_ID, view.schemaId()); | ||
| } | ||
|
|
||
| if (view.defaultCatalog() != null) { | ||
| generator.writeStringField(DEFAULT_CATALOG, view.defaultCatalog()); | ||
| } | ||
|
|
||
| if (view.defaultNamespace() != null) { | ||
| JsonUtil.writeStringArray( | ||
| DEFAULT_NAMESPACE, Arrays.asList(view.defaultNamespace().levels()), generator); | ||
| } | ||
|
|
||
| if (!view.fieldAliases().isEmpty()) { | ||
| JsonUtil.writeStringArray( | ||
| SQLViewRepresentationParser.FIELD_ALIASES, view.fieldAliases(), generator); | ||
| } | ||
|
|
||
| if (!view.fieldComments().isEmpty()) { | ||
| JsonUtil.writeStringArray( | ||
| SQLViewRepresentationParser.FIELD_COMMENTS, view.fieldComments(), generator); | ||
| } | ||
|
|
||
| generator.writeEndObject(); | ||
| } | ||
|
|
||
| static SQLViewRepresentation fromJson(String json) { | ||
| return JsonUtil.parse(json, SQLViewRepresentationParser::fromJson); | ||
| } | ||
|
|
||
| static SQLViewRepresentation fromJson(JsonNode node) { | ||
| Preconditions.checkArgument( | ||
amogh-jahagirdar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| node != null, "Cannot parse SQL view representation from null object"); | ||
| Preconditions.checkArgument( | ||
| node.isObject(), "Cannot parse SQL view representation from non-object: %s", node); | ||
| ImmutableSQLViewRepresentation.Builder builder = | ||
| ImmutableSQLViewRepresentation.builder() | ||
| .sql(JsonUtil.getString(SQL, node)) | ||
| .dialect(JsonUtil.getString(DIALECT, node)); | ||
| String defaultCatalog = JsonUtil.getStringOrNull(DEFAULT_CATALOG, node); | ||
| if (defaultCatalog != null) { | ||
| builder.defaultCatalog(defaultCatalog); | ||
| } | ||
|
|
||
| Integer schemaId = JsonUtil.getIntOrNull(SCHEMA_ID, node); | ||
| if (schemaId != null) { | ||
| builder.schemaId(schemaId); | ||
| } | ||
|
|
||
| List<String> namespace = JsonUtil.getStringListOrNull(DEFAULT_NAMESPACE, node); | ||
| if (namespace != null && !namespace.isEmpty()) { | ||
| builder.defaultNamespace(Namespace.of(Iterables.toArray(namespace, String.class))); | ||
| } | ||
|
|
||
| List<String> fieldAliases = JsonUtil.getStringListOrNull(FIELD_ALIASES, node); | ||
| if (fieldAliases != null) { | ||
| builder.fieldAliases(fieldAliases); | ||
| } | ||
|
|
||
| List<String> fieldComments = JsonUtil.getStringListOrNull(FIELD_COMMENTS, node); | ||
| if (fieldComments != null) { | ||
| builder.fieldComments(fieldComments); | ||
| } | ||
|
|
||
| return builder.build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.iceberg.view; | ||
|
|
||
| import org.immutables.value.Value; | ||
|
|
||
| @Value.Immutable | ||
| public interface UnknownViewRepresentation extends ViewRepresentation {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.iceberg.view; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonGenerator; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import java.io.IOException; | ||
| import java.util.Locale; | ||
| import org.apache.iceberg.relocated.com.google.common.base.Preconditions; | ||
| import org.apache.iceberg.util.JsonUtil; | ||
|
|
||
| class ViewRepresentationParser { | ||
| static final String TYPE = "type"; | ||
|
|
||
| private ViewRepresentationParser() {} | ||
|
|
||
| static void toJson(ViewRepresentation representation, JsonGenerator generator) | ||
| throws IOException { | ||
| Preconditions.checkArgument(representation != null, "Invalid view representation: null"); | ||
| switch (representation.type()) { | ||
| case ViewRepresentation.Type.SQL: | ||
| SQLViewRepresentationParser.toJson((SQLViewRepresentation) representation, generator); | ||
| break; | ||
|
|
||
| default: | ||
| throw new IllegalArgumentException( | ||
| String.format("Cannot serialize view representation type: %s", representation.type())); | ||
| } | ||
| } | ||
|
|
||
| static String toJson(ViewRepresentation entry) { | ||
| return JsonUtil.generate(gen -> toJson(entry, gen), false); | ||
| } | ||
|
|
||
| static ViewRepresentation fromJson(String json) { | ||
| return JsonUtil.parse(json, ViewRepresentationParser::fromJson); | ||
| } | ||
|
|
||
| static ViewRepresentation fromJson(JsonNode node) { | ||
| Preconditions.checkArgument(node != null, "Cannot parse view representation from null object"); | ||
| Preconditions.checkArgument( | ||
| node.isObject(), "Cannot parse view representation from non-object: %s", node); | ||
| String type = JsonUtil.getString(TYPE, node).toLowerCase(Locale.ENGLISH); | ||
| switch (type) { | ||
| case ViewRepresentation.Type.SQL: | ||
| return SQLViewRepresentationParser.fromJson(node); | ||
|
|
||
| default: | ||
| return ImmutableUnknownViewRepresentation.builder().type(type).build(); | ||
amogh-jahagirdar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
javax.annotation.NullableThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ViewRepresentations currently has a single required "type" field so it wasn't marked as Nullable to begin with. Let me know if I'm missing something!