/** * Copyright 2014 Yahoo! Inc. Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * See accompanying LICENSE file. */ package com.yahoo.sql4d; import com.yahoo.sql4d.query.BaseAggQueryMeta; import com.yahoo.sql4d.query.PlainDimQueryMeta; import com.yahoo.sql4d.query.QueryMeta; import com.yahoo.sql4d.query.nodes.AggItem; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * One or more query meta which are joinable on primary key. * @author srikalyan */ public class QueryProgram extends Program<QueryMeta>{ public final List<String> primaryJoinableHooks = new ArrayList<>();// Has 'N-1' items public final List<String> joinTypes = new ArrayList<>();// Has 'N-1' items public QueryProgram() { this.type = Type.QUERY; } public void addJoinHook(String hook) { primaryJoinableHooks.add(hook); } public void addJoinType(String type) { joinTypes.add(type); } @Override public String toString() { StringBuilder buffer = new StringBuilder(); int i = 0; for (QueryMeta qMeta: getAllStmnts()) { buffer.append(qMeta.toString()); buffer.append("\n"); if (i == numStmnts() - 1) { break; } if (numStmnts() > 1) { buffer.append(" joined with "); buffer.append(primaryJoinableHooks.get(i++)); buffer.append("\n"); } } return buffer.toString(); } /** * TODO: This method should be a full blown functional but right now address * only partial semantics. * Do all semantic checks here. * @throws java.lang.Exception */ @Override public void isValid() throws Exception { if (numStmnts() >= 2) { if (primaryJoinableHooks.size() > 0) { for (String joinField:primaryJoinableHooks) { if (joinField.equals("timestamp")) {// timestamp is implicitly present in the result. continue; } for (QueryMeta query: getAllStmnts()) { boolean isPresent = false; if (query instanceof BaseAggQueryMeta) {// Since BaseAggQueryMeta is also a PlainDimQueryMeta we go with former first. for (AggItem item:((BaseAggQueryMeta)query).aggregations) { if (joinField.equals(item.fieldName) || (item.asName != null && joinField.equals(item.asName))) { isPresent = true; } } } if (query instanceof PlainDimQueryMeta) { Map<String, String> dims = ((PlainDimQueryMeta)query).fetchDimensions; for (Map.Entry<String, String> entry :dims.entrySet()) { if (joinField.equals(entry.getKey()) || (entry.getValue() != null && joinField.equals(entry.getValue()))) { isPresent = true; } } } if (!isPresent) { String error = joinField + " mentioned in the composite key should appear in all the data sources being queried and joined."; throw new Exception(error); } } } } else { String error = "Need atleast one field to join on"; throw new Exception(error); } } } }