package com.thinkbiganalytics.util; /*- * #%L * thinkbig-nifi-core-processors * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import com.google.common.io.LineReader; import com.thinkbiganalytics.hive.util.HiveUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import java.io.IOException; import java.io.StringReader; import java.util.List; import java.util.Vector; import java.util.stream.Collectors; import java.util.stream.Stream; public class ColumnSpec { private String name; private String comment; private String dataType; private boolean pk; private boolean createDt; private boolean modifiedDt; public ColumnSpec(String name, String dataType, String comment) { this(name, dataType, comment, false, false, false); } public ColumnSpec(String name, String dataType, String comment, boolean pk, boolean createDt, boolean modifiedDt) { super(); Validate.notEmpty(name); this.name = name.toLowerCase().trim(); this.dataType = (StringUtils.isEmpty(dataType) ? "string" : dataType); this.comment = comment; this.pk = pk; this.createDt = createDt; this.modifiedDt = modifiedDt; validate(); } public static String toPrimaryKeyJoinSQL(ColumnSpec[] specs, String leftTableAlias, String rightTableAlias) { final String safeLeftTable = HiveUtils.quoteIdentifier(leftTableAlias); final String safeRightTable = HiveUtils.quoteIdentifier(rightTableAlias); final List<String> keys = Stream.of(specs) .filter(ColumnSpec::isPk) .map(ColumnSpec::getName) .map(HiveUtils::quoteIdentifier) .map(column -> safeLeftTable + "." + column + " = " + safeRightTable + "." + column) .collect(Collectors.toList()); return StringUtils.join(keys, " AND "); } public static String[] toPrimaryKeys(ColumnSpec[] specs) { return Stream.of(specs) .filter(ColumnSpec::isPk) .map(ColumnSpec::getName) .map(HiveUtils::quoteIdentifier) .toArray(String[]::new); } /** * Method for defining a column specification as a pipe-delimited format: column|data type|comment (optional)|pk|created|modified. Each row separated by a newline */ public static ColumnSpec[] createFromString(String specString) { if (StringUtils.isEmpty(specString)) { return null; } List<ColumnSpec> specs = new Vector<>(); try { LineReader lineReader = new LineReader( new StringReader(specString)); String line; while ((line = lineReader.readLine()) != null) { String[] parts = line.split("\\|"); int len = parts.length; if (len > 0) { String columnName = ""; String comment = ""; String dataType = "string"; boolean pk = false; boolean modifiedDt = false; boolean createDt = false; switch (len) { default: case 6: modifiedDt = "1".equals(parts[5].trim()); case 5: createDt = "1".equals(parts[4].trim()); case 4: pk = "1".equals(parts[3].trim()); case 3: comment = parts[2]; case 2: dataType = parts[1]; case 1: columnName = parts[0]; } specs.add(new ColumnSpec(columnName, dataType, comment, pk, createDt, modifiedDt)); } } return specs.toArray(new ColumnSpec[0]); } catch (IOException e) { throw new RuntimeException("Failed to parse column specs[" + specString + "]", e); } } public void validate() { Validate.notEmpty(name); Validate.notEmpty(dataType); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public boolean isPk() { return pk; } public void setPk(boolean pk) { this.pk = pk; } public boolean isCreateDt() { return createDt; } public void setCreateDt(boolean createDt) { this.createDt = createDt; } public boolean isModifiedDt() { return modifiedDt; } public void setModifiedDt(boolean modifiedDt) { this.modifiedDt = modifiedDt; } public String toCreateSQL() { return toCreateSQL(false); } public String toCreateSQL(boolean strings) { StringBuffer sb = new StringBuffer(); sb.append(HiveUtils.quoteIdentifier(name)).append(' '); sb.append((strings ? "string" : dataType)); if (!StringUtils.isEmpty(comment)) { sb.append(" COMMENT ").append(HiveUtils.quoteString(comment)); } return sb.toString(); } public String toPartitionSQL() { return HiveUtils.quoteIdentifier(name) + " " + dataType; } }