class TimestreamMetadataHandler extends GlueMetadataHandler {

    @Override
    public GetTableResponse doGetTable(BlockAllocator blockAllocator, GetTableRequest request)
            throws Exception
    {
        logger.info("doGetTable: enter", request.getTableName());

        Schema schema = null;
        try {
            if (glue != null) {
                schema = super.doGetTable(blockAllocator, request, TABLE_FILTER).getSchema();
                logger.info("doGetTable: Retrieved schema for table[{}] from AWS Glue.", request.getTableName());
            }
        }
        catch (RuntimeException ex) {
            logger.warn("doGetTable: Unable to retrieve table[{}:{}] from AWS Glue.",
                    request.getTableName().getSchemaName(),
                    request.getTableName().getTableName(),
                    ex);
        }

        if (schema == null) {
            TableName tableName = request.getTableName();
            String describeQuery = queryFactory.createDescribeTableQueryBuilder()
                    .withTablename(tableName.getTableName())
                    .withDatabaseName(tableName.getSchemaName())
                    .build();

            logger.info("doGetTable: Retrieving schema for table[{}] from TimeStream using describeQuery[{}].",
                    request.getTableName(), describeQuery);

            QueryRequest queryRequest = new QueryRequest().withQueryString(describeQuery);
            SchemaBuilder schemaBuilder = SchemaBuilder.newBuilder();
            do {
                QueryResult queryResult = tsQuery.query(queryRequest);
                for (Row next : queryResult.getRows()) {
                    List<Datum> datum = next.getData();

                    if (datum.size() != 3) {
                        throw new RuntimeException("Unexpected datum size " + datum.size() +
                                " while getting schema from datum[" + datum.toString() + "]");
                    }

                    Field nextField = TimestreamSchemaUtils.makeField(datum.get(0).getScalarValue(), datum.get(1).getScalarValue());
                    schemaBuilder.addField(nextField);
                }
                queryRequest = new QueryRequest().withNextToken(queryResult.getNextToken());
            }
            while (queryRequest.getNextToken() != null);

            schema = schemaBuilder.build();
        }

        return new GetTableResponse(request.getCatalogName(), request.getTableName(), schema);
    }

    public  TimestreamMetadataHandler();
    @VisibleForTesting protected  TimestreamMetadataHandler(AmazonTimestreamQuery tsQuery,
            AmazonTimestreamWrite tsMeta,
            AWSGlue glue,
            EncryptionKeyFactory keyFactory,
            AWSSecretsManager secretsManager,
            AmazonAthena athena,
            String spillBucket,
            String spillPrefix);

}