我想用jooq来查询Hive。HiveSQL方言与mysql方言相当接近。现在我遇到了这些问题:配置单元支持限制n,不支持限制n偏移k。虚拟解决方案-覆盖选择限制(limit);在jooq中解决这些问题的最佳实践是什么?
7lrncoxx1#
不幸的是,扩展jooq以完全支持新的sql方言并不是很简单。随着时间的推移,jooq的api得到了广泛的发展,它支持一系列标准的和特定于供应商的sql语法变体。虽然apachehive方言可能看起来与mysql类似,但jooq的内部可能需要实现许多细微的差异。限制的不同实施。。抵消条款只是一个问题。也就是说,用jooq加上“未知”或“不支持”的方言通常不是一个好主意。
在短期内,您可能需要修补jooq的呈现sql。最好的方法是使用executelistener,如下所述:http://www.jooq.org/doc/latest/manual/sql-execution/execute-listeners/http://www.jooq.org/javadoc/latest/org/jooq/executelistener.html在接收到“rendernd()”事件后,您将能够访问呈现的sql并使用正则表达式或任何您喜欢的技术对其进行修改。
从长远来看,如果实施#2337,可能会有更好的解决方案(但我们可能不会实施)
mzillmmw2#
下面是最肮脏的解决方案:)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; } }
2条答案
按热度按时间7lrncoxx1#
不幸的是,扩展jooq以完全支持新的sql方言并不是很简单。随着时间的推移,jooq的api得到了广泛的发展,它支持一系列标准的和特定于供应商的sql语法变体。虽然apachehive方言可能看起来与mysql类似,但jooq的内部可能需要实现许多细微的差异。限制的不同实施。。抵消条款只是一个问题。也就是说,用jooq加上“未知”或“不支持”的方言通常不是一个好主意。
解决方案:短期内
在短期内,您可能需要修补jooq的呈现sql。最好的方法是使用executelistener,如下所述:
http://www.jooq.org/doc/latest/manual/sql-execution/execute-listeners/
http://www.jooq.org/javadoc/latest/org/jooq/executelistener.html
在接收到“rendernd()”事件后,您将能够访问呈现的sql并使用正则表达式或任何您喜欢的技术对其进行修改。
解决办法:从长远来看
从长远来看,如果实施#2337,可能会有更好的解决方案(但我们可能不会实施)
mzillmmw2#
下面是最肮脏的解决方案:)jooq用户组没有回答不幸的是:(