2

Hiveを征服するためにJOOQを使用しようとしています。Hive SQL方言は、MySQL方言にかなり似ています。今、私はこれらの問題に遭遇しました:

  • HiveはLIMITNをサポートしますが、LIMIT N OFFSET Kはサポートしません。ダミーソリューション-select.limit(limit);をオーバーライドします。

JOOQでこのような問題を解決するためのベストプラクティスは何ですか?

4

2 に答える 2

3

残念ながら、jOOQを拡張して新しいSQLダイアレクトを完全にサポートすることは、それほど簡単ではありません。jOOQのAPIは時間の経過とともに大幅に成長し、標準およびベンダー固有のSQL構文バリアントの優れたセットをサポートしています。Apache Hive方言はMySQLに似ているように見えるかもしれませんが、jOOQの内部に実装する必要がある微妙な違いがおそらくたくさんあります。LIMIT..OFFSET句の異なる実装は1つの問題にすぎません。とはいえ、一般的に、「不明」または「サポートされていない」方言でjOOQを使用することはお勧めできません。

解決策:短期的には

短期的には、おそらくjOOQのレンダリングされたSQLにパッチを適用する必要があります。このための最良の手法は、ここに記載されているようにExecuteListenerを使用することです。

「renderEnd()」イベントを受信すると、レンダリングされたSQLにアクセスし、正規表現または任意の手法を使用して変更できます。

解決策:長期的には

長期的には、#2337が実装されている場合/が実装されている場合はより良い解決策があるかもしれません(しかし、おそらくそれは実装されません)

于 2013-03-15T19:08:41.790 に答える
1

これが最も汚い解決策です:)JOOQユーザーグループは残念ながら答えませんでした:(

public class CountRatingQueryBuilder {

    private static final String SCORING_TABLE_NAME = "web_resource_rating";

    private final Connection connection;
    private final ScoringMetadata scoringMetadata;

    private final SelectSelectStep select;
    private final Factory create;

    public CountRatingQueryBuilder(Connection connection, ScoringMetadata scoringMetadata){
        this.connection = connection;
        this.scoringMetadata = scoringMetadata;

        create = new Factory(this.connection, SQLDialect.MYSQL);
        select = create.select();

        withSelectFieldsClause();
    }

    public CountRatingQueryBuilder withLimit(int limit){
        select.limit(limit);
        return this;
    }

    public CountRatingQueryBuilder withRegionId(Integer regionId){
        select.where(REGION_ID.field().equal(regionId));
        return this;
    }

    public CountRatingQueryBuilder withResourceTypeId(int resourceTypeId){
        select.where(RESOURCE_TYPE_ID.field().equal(resourceTypeId));
        return this;
    }

    public CountRatingQueryBuilder withRequestTimeBetween(long beginTimestamp, long endTimestamp){
        select.where(REQUEST_TIME.field().between(beginTimestamp, endTimestamp));
        return this;
    }

    public CountRatingQueryBuilder withResourceId(int resourceId){
        select.where(RESOURCE_ID.field().equal(resourceId));
        return this;
    }



    protected void withGroupByClause(){
        select.groupBy(REGION_ID.field());
        select.groupBy(RESOURCE_TYPE_ID.field());
        select.groupBy(RESOURCE_ID.field());
        select.groupBy(CONTENT_ID.field());
    }

    protected void withSelectFieldsClause(){
        select.select(REGION_ID.field());
        select.select(RESOURCE_TYPE_ID.field());
        select.select(CONTENT_ID.field());
        select.select(RESOURCE_ID.field());
        select.select(Factory.count(HIT_COUNT.field()).as(SUM_HIT_COUNT.fieldName()));
    }

    protected void withFromClause(){
        select.from(SCORING_TABLE_NAME);
    }

    protected void withOrderByClause(){
        select.orderBy(SUM_HIT_COUNT.field().desc());
    }

    public String build(){
        withGroupByClause();
        withOrderByClause();
        withFromClause();
        return select.getSQL().replace("offset ?","");//dirty hack for MySQL dialect. TODO: we can try to implement our own SQL dialect for Hive :)

    }

    public List<ResultRow> buildAndFetch(){
        String sqlWithPlaceholders = build();

        List<ResultRow> scoringResults = new ArrayList<ResultRow>(100);
        List<Record> recordResults = create.fetch(sqlWithPlaceholders, ArrayUtils.subarray(select.getBindValues().toArray(new Object[select.getBindValues().size()]),0, select.getBindValues().size()-1));//select.fetch();
        for(Record record : recordResults){
            ResultRowBuilder resultRowBuilder = ResultRowBuilder.create();

            resultRowBuilder.withContentType(scoringMetadata.getResourceType(record.getValue(RESOURCE_TYPE_ID.fieldName(), Integer.class)));
            resultRowBuilder.withHitCount(record.getValue(SUM_HIT_COUNT.fieldName(), Long.class));
            resultRowBuilder.withUrl(record.getValue(CONTENT_ID.fieldName(), String.class));
            scoringResults.add(resultRowBuilder.build());
        }
        return scoringResults;
    }

}
于 2013-03-14T09:44:48.143 に答える