adutra commented on code in PR #1802:
URL: https://github.com/apache/polaris/pull/1802#discussion_r2125835690


##########
persistence/relational-jdbc/build.gradle.kts:
##########
@@ -34,6 +34,7 @@ dependencies {
   compileOnly(libs.jakarta.inject.api)
 
   implementation(libs.smallrye.common.annotation) // @Identifier
+  implementation(libs.postgresql)

Review Comment:
   This is creating a hard dependency from this project to the Postgres JDBC 
driver, FYI.



##########
persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/QueryGenerator.java:
##########
@@ -34,38 +37,67 @@
 import org.apache.polaris.persistence.relational.jdbc.models.ModelGrantRecord;
 import 
org.apache.polaris.persistence.relational.jdbc.models.ModelPolicyMappingRecord;
 import 
org.apache.polaris.persistence.relational.jdbc.models.ModelPrincipalAuthenticationData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class QueryGenerator {
+  private static final Logger log = 
LoggerFactory.getLogger(QueryGenerator.class);
+  private final DatabaseType databaseType;
 
-  public static <T> String generateSelectQuery(
+  public QueryGenerator(DatabaseType databaseType) {
+    this.databaseType = databaseType;
+  }
+
+  public DatabaseType getDatabaseType() {
+    return databaseType;
+  }
+
+  public static class PreparedQuery {
+    private final String sql;
+    private final List<Object> parameters;
+
+    public PreparedQuery(String sql, List<Object> parameters) {
+      this.sql = sql;
+      this.parameters = parameters;
+    }
+
+    public String getSql() {
+      return sql;
+    }
+
+    public List<Object> getParameters() {
+      return parameters;
+    }
+  }
+
+  public <T> PreparedQuery generateSelectQuery(
       @Nonnull Converter<T> entity, @Nonnull Map<String, Object> whereClause) {
-    return generateSelectQuery(entity, generateWhereClause(whereClause));
+
+    String tableName = getTableName(entity.getClass());
+    Map<String, Object> objectMap = entity.toMap(databaseType);

Review Comment:
   This is very inefficient; we don't need to collect the object's current 
values, we only need the keys (column names).



##########
persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/QueryGenerator.java:
##########
@@ -205,9 +227,14 @@ public static String getTableName(@Nonnull Class<?> 
entityClass) {
       throw new IllegalArgumentException("Unsupported entity class: " + 
entityClass.getName());
     }
 
-    // TODO: check if we want to make schema name configurable.
-    tableName = "POLARIS_SCHEMA." + tableName;
+    return "POLARIS_SCHEMA." + tableName;
+  }
 
-    return tableName;
+  private void checkInvalidColumns(Map<String, Object> entity, Map<String, 
Object> whereClause) {
+    List<String> allColumns = new ArrayList<>(entity.keySet());
+    allColumns.add("realm_id");
+    if (!allColumns.containsAll(whereClause.keySet())) {
+      throw new IllegalArgumentException("Invalid query " + 
whereClause.keySet());
+    }
   }

Review Comment:
   ```suggestion
     private void checkInvalidColumns(Map<String, Object> entity, Map<String, 
Object> whereClause) {
       if (!whereClause.isEmpty()) {
         for (String key : whereClause.keySet()) {
           if (!entity.containsKey(key) && !key.equals("realm_id")) {
             throw new IllegalArgumentException("Invalid query column: " + key);
           }
         }
       }
   ```



##########
persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java:
##########
@@ -269,8 +291,7 @@ public PolarisBaseEntity lookupEntity(
       @Nonnull PolarisCallContext callCtx, long catalogId, long entityId, int 
typeCode) {
     Map<String, Object> params =
         Map.of("catalog_id", catalogId, "id", entityId, "type_code", typeCode, 
"realm_id", realmId);
-    String query = generateSelectQuery(new ModelEntity(), params);
-    return getPolarisBaseEntity(query);
+    return getPolarisBaseEntity(queryGenerator.generateSelectQuery(new 
ModelEntity(), params));

Review Comment:
   Not related to this change, but why do we need so many WHERE conditions? The 
PK is `(realmId, id)`, so that should be sufficient.



##########
persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/QueryGenerator.java:
##########
@@ -37,35 +40,51 @@
 
 public class QueryGenerator {
 
-  public static <T> String generateSelectQuery(
+  public static class PreparedQuery {
+    private final String sql;
+    private final List<Object> parameters;
+
+    public PreparedQuery(String sql, List<Object> parameters) {
+      this.sql = sql;
+      this.parameters = parameters;
+    }
+
+    public String getSql() {
+      return sql;
+    }
+
+    public List<Object> getParameters() {
+      return parameters;
+    }
+  }
+
+  public static <T> PreparedQuery generateSelectQuery(
       @Nonnull Converter<T> entity, @Nonnull Map<String, Object> whereClause) {

Review Comment:
   I tend to agree with @dimas-b, SQL should be statically defined at compile 
time for maximum security and efficiency.
   
   It should be possible to achieve that by declaring a few constants in each 
model class. e.g. for `ModelEntity`:
   
   ```java
   public class ModelEntity implements Converter<PolarisBaseEntity> {
   
     public static final String TABLE_NAME = "ENTITIES";
   
     public static final List<String> PK_COLUMNS = List.of("realm_id", "id");
   
     public static final List<String> ALL_COLUMNS =
         List.of(
             "realm_id",
             "id",
             "catalog_id",
             "parent_id",
             "type_code",
             "name",
             "entity_version",
             "sub_type_code",
             "create_timestamp",
             "drop_timestamp",
             "purge_timestamp",
             "to_purge_timestamp",
             "last_update_timestamp",
             "properties",
             "internal_properties",
             "grant_records_version");
   
     public static final String LOOKUP_QUERY =
         "SELECT "
             + String.join(", ", ALL_COLUMNS)
             + " FROM "
             + TABLE_NAME
             + " WHERE "
             + String.join(" = ? AND ", PK_COLUMNS)
             + " = ?";
   
     public static final String LIST_QUERY =
         "SELECT "
             + String.join(", ", ALL_COLUMNS)
             + " FROM "
             + TABLE_NAME
             + " WHERE realm_id = ? AND catalog_id = ? AND parent_id = ? AND 
type_code = ?";
   
     public static void bindLookupQuery(PreparedStatement stmt, ModelEntity 
entity, String realmId) throws SQLException {
       stmt.setObject(1, realmId);
       stmt.setObject(2, entity.getId());
     }
     
     public static void bindListQuery(PreparedStatement stmt, ModelEntity 
entity, String realmId) throws SQLException {
       stmt.setObject(1, realmId);
       stmt.setObject(2, entity.getCatalogId());
       stmt.setObject(3, entity.getParentId());
       stmt.setObject(4, entity.getTypeCode());
     }
   ...
   ```



-- 
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: issues-unsubscr...@polaris.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to