public MetadataSchemaQueryResult execute()

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);
    }