in data-catalog-api/server/service/src/main/java/org/apache/airavata/datacatalog/api/query/impl/MetadataSchemaQueryExecutorImpl.java [72:192]
public MetadataSchemaQueryResult execute(UserEntity userEntity, String sql, int page, int pageSize)
throws MetadataSchemaSqlParseException, MetadataSchemaSqlValidateException {
// Create a schema that contains the data_product table and all of the metadata
// schemas
SchemaPlus schema = Frameworks.createRootSchema(true);
schema.add("data_product", new AbstractTable() {
@Override
public RelDataType getRowType(RelDataTypeFactory typeFactory) {
Builder builder = (Builder) typeFactory.builder();
return builder
.add("data_product_id", SqlTypeName.INTEGER)
.add("parent_data_product_id", SqlTypeName.INTEGER)
.add("external_id", SqlTypeName.VARCHAR)
.add("metadata", SqlTypeName.OTHER)
.build();
}
});
// TODO: limit by tenant id
List<MetadataSchemaEntity> metadataSchemas = metadataSchemaRepository.findAll();
for (MetadataSchemaEntity metadataSchema : metadataSchemas) {
schema.add(metadataSchema.getSchemaName(), new AbstractTable() {
@Override
public RelDataType getRowType(RelDataTypeFactory typeFactory) {
Builder builder = (Builder) typeFactory.builder();
// Add all of the common fields
builder.add("data_product_id", SqlTypeName.INTEGER)
.add("parent_data_product_id", SqlTypeName.INTEGER)
.add("external_id", SqlTypeName.VARCHAR)
.add("metadata", SqlTypeName.OTHER);
// Add all of the schema specific metadata fields
for (MetadataSchemaFieldEntity metadataSchemaField : metadataSchema.getMetadataSchemaFields()) {
builder.add(metadataSchemaField.getFieldName(),
getSqlTypeName(metadataSchemaField.getFieldValueType()));
}
return builder.build();
}
});
}
FrameworkConfig config = Frameworks.newConfigBuilder()
.defaultSchema(schema)
.parserConfig(SqlParser.Config.DEFAULT.withUnquotedCasing(Casing.TO_LOWER))
.build();
Planner planner = Frameworks.getPlanner(config);
SqlNode sqlNode = parse(planner, sql);
SqlValidator validator = getValidator(schema, config, planner);
// Validate the query
SqlNode validatedSqlNode = validate(validator, sqlNode);
// create a mapping of table aliases to actual tables (metadata schemas)
// For example, if query is of the form "select * from smilesdb as sm", then
// create a mapping from sm -> smilesdb
// TODO: may not be a SqlSelect, might be an OrderBy for example
Map<String, String> tableAliases = new HashMap<>();
validatedSqlNode.accept(new SqlShuttle() {
@Override
public SqlNode visit(SqlCall call) {
if (call.getKind() == SqlKind.UNION) {
// If there are multiple UNIONS
for (SqlNode operand : call.getOperandList()) {
operand.accept(this);
}
} else if (call instanceof SqlSelect) {
// if it's a plain select statement, visit it directly
visitSelect((SqlSelect) call);
}
return super.visit(call);
}
private void visitSelect(SqlSelect selectNode) {
selectNode.getFrom().accept(new SqlShuttle() {
@Override
public SqlNode visit(SqlCall call) {
if (call.isA(Collections.singleton(SqlKind.AS))) {
SqlIdentifier first = call.operand(0);
SqlIdentifier second = call.operand(1);
tableAliases.put(second.getSimple(), first.getSimple());
}
return super.visit(call);
}
});
}
});
String finalSql = metadataSchemaQueryWriter.rewriteQuery(userEntity, validatedSqlNode, metadataSchemas,
tableAliases);
logger.debug("Metadata schema query final sql: {}", finalSql);
// total count
String countSql = "SELECT COUNT(*) FROM (" + finalSql + ") as count_alias";
Number countResult = (Number) entityManager.createNativeQuery(countSql).getSingleResult();
int totalCount = countResult.intValue();
if (page > 0 && pageSize >0) {
// offset
int offset = (page - 1) * pageSize;
finalSql = finalSql + " LIMIT " + pageSize + " OFFSET " + offset;
}
List<DataProductEntity> dataProductEntities = entityManager.createNativeQuery(finalSql, DataProductEntity.class)
.getResultList();
List<DataProduct> dataProducts = new ArrayList<>();
for (DataProductEntity dataProductEntity : dataProductEntities) {
org.apache.airavata.datacatalog.api.DataProduct.Builder dpBuilder = DataProduct.newBuilder();
dataProductMapper.mapEntityToModel(dataProductEntity, dpBuilder);
dataProducts.add(dpBuilder.build());
}
return new MetadataSchemaQueryResult(dataProducts, totalCount);
}