org.apache.hive.hplsql.Var Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.hive.hplsql;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Date;
import java.sql.Timestamp;
/**
* Variable or the result of expression
*/
public class Var {
// Data types
public enum Type {BOOL, CURSOR, DATE, DECIMAL, DERIVED_TYPE, DERIVED_ROWTYPE, DOUBLE, FILE, IDENT, BIGINT, INTERVAL, ROW,
RS_LOCATOR, STRING, STRINGLIST, TIMESTAMP, NULL};
public static final String DERIVED_TYPE = "DERIVED%TYPE";
public static final String DERIVED_ROWTYPE = "DERIVED%ROWTYPE";
public static Var Empty = new Var();
public static Var Null = new Var(Type.NULL);
public String name;
public Type type;
public Object value;
int len;
int scale;
boolean constant = false;
public Var() {
type = Type.NULL;
}
public Var(Var var) {
name = var.name;
type = var.type;
value = var.value;
len = var.len;
scale = var.scale;
}
public Var(Long value) {
this.type = Type.BIGINT;
this.value = value;
}
public Var(BigDecimal value) {
this.type = Type.DECIMAL;
this.value = value;
}
public Var(String name, Long value) {
this.type = Type.BIGINT;
this.name = name;
this.value = value;
}
public Var(String value) {
this.type = Type.STRING;
this.value = value;
}
public Var(Double value) {
this.type = Type.DOUBLE;
this.value = value;
}
public Var(Date value) {
this.type = Type.DATE;
this.value = value;
}
public Var(Timestamp value, int scale) {
this.type = Type.TIMESTAMP;
this.value = value;
this.scale = scale;
}
public Var(Interval value) {
this.type = Type.INTERVAL;
this.value = value;
}
public Var(ArrayList value) {
this.type = Type.STRINGLIST;
this.value = value;
}
public Var(Boolean b) {
type = Type.BOOL;
value = b;
}
public Var(String name, Row row) {
this.name = name;
this.type = Type.ROW;
this.value = new Row(row);
}
public Var(Type type, String name) {
this.type = type;
this.name = name;
}
public Var(Type type, Object value) {
this.type = type;
this.value = value;
}
public Var(String name, Type type, Object value) {
this.name = name;
this.type = type;
this.value = value;
}
public Var(Type type) {
this.type = type;
}
public Var(String name, String type, String len, String scale, Var def) {
this.name = name;
setType(type);
if (len != null) {
this.len = Integer.parseInt(len);
}
if (scale != null) {
this.scale = Integer.parseInt(scale);
}
if (def != null) {
cast(def);
}
}
/**
* Cast a new value to the variable
*/
public Var cast(Var val) {
if (constant) {
return this;
}
else if (val == null || val.value == null) {
value = null;
}
else if (type == Type.DERIVED_TYPE) {
type = val.type;
value = val.value;
}
else if (type == val.type && type == Type.STRING) {
cast((String)val.value);
}
else if (type == val.type) {
value = val.value;
}
else if (type == Type.STRING) {
cast(val.toString());
}
else if (type == Type.BIGINT) {
if (val.type == Type.STRING) {
value = Long.parseLong((String)val.value);
}
}
else if (type == Type.DECIMAL) {
if (val.type == Type.STRING) {
value = new BigDecimal((String)val.value);
}
else if (val.type == Type.BIGINT) {
value = BigDecimal.valueOf(val.longValue());
}
else if (val.type == Type.DOUBLE) {
value = BigDecimal.valueOf(val.doubleValue());
}
}
else if (type == Type.DOUBLE) {
if (val.type == Type.STRING) {
value = new Double((String)val.value);
}
else if (val.type == Type.BIGINT || val.type == Type.DECIMAL) {
value = Double.valueOf(val.doubleValue());
}
}
else if (type == Type.DATE) {
value = Utils.toDate(val.toString());
}
else if (type == Type.TIMESTAMP) {
value = Utils.toTimestamp(val.toString());
}
return this;
}
/**
* Cast a new string value to the variable
*/
public Var cast(String val) {
if (!constant && type == Type.STRING) {
if (len != 0 ) {
int l = val.length();
if (l > len) {
value = val.substring(0, len);
return this;
}
}
value = val;
}
return this;
}
/**
* Set the new value
*/
public void setValue(String str) {
if(!constant && type == Type.STRING) {
value = str;
}
}
public Var setValue(Long val) {
if (!constant && type == Type.BIGINT) {
value = val;
}
return this;
}
public Var setValue(Boolean val) {
if (!constant && type == Type.BOOL) {
value = val;
}
return this;
}
public void setValue(Object value) {
if (!constant) {
this.value = value;
}
}
/**
* Set the new value from the result set
*/
public Var setValue(ResultSet rs, ResultSetMetaData rsm, int idx) throws SQLException {
int type = rsm.getColumnType(idx);
if (type == java.sql.Types.CHAR || type == java.sql.Types.VARCHAR) {
cast(new Var(rs.getString(idx)));
}
else if (type == java.sql.Types.INTEGER || type == java.sql.Types.BIGINT ||
type == java.sql.Types.SMALLINT || type == java.sql.Types.TINYINT) {
cast(new Var(new Long(rs.getLong(idx))));
}
else if (type == java.sql.Types.DECIMAL || type == java.sql.Types.NUMERIC) {
cast(new Var(rs.getBigDecimal(idx)));
}
else if (type == java.sql.Types.FLOAT || type == java.sql.Types.DOUBLE) {
cast(new Var(new Double(rs.getDouble(idx))));
}
return this;
}
/**
* Set ROW values from the result set
*/
public Var setValues(ResultSet rs, ResultSetMetaData rsm) throws SQLException {
Row row = (Row)this.value;
int idx = 1;
for (Column column : row.getColumns()) {
Var var = new Var(column.getName(), column.getType(), null, null, null);
var.setValue(rs, rsm, idx);
column.setValue(var);
idx++;
}
return this;
}
/**
* Set the data type from string representation
*/
void setType(String type) {
this.type = defineType(type);
}
/**
* Set the data type from JDBC type code
*/
void setType(int type) {
this.type = defineType(type);
}
/**
* Set the variable as constant
*/
void setConstant(boolean constant) {
this.constant = constant;
}
/**
* Define the data type from string representation
*/
public static Type defineType(String type) {
if (type == null) {
return Type.NULL;
}
else if (type.equalsIgnoreCase("INT") || type.equalsIgnoreCase("INTEGER") || type.equalsIgnoreCase("BIGINT") ||
type.equalsIgnoreCase("SMALLINT") || type.equalsIgnoreCase("TINYINT") ||
type.equalsIgnoreCase("BINARY_INTEGER") || type.equalsIgnoreCase("PLS_INTEGER") ||
type.equalsIgnoreCase("SIMPLE_INTEGER") || type.equalsIgnoreCase("INT2") ||
type.equalsIgnoreCase("INT4") || type.equalsIgnoreCase("INT8")) {
return Type.BIGINT;
}
else if (type.equalsIgnoreCase("CHAR") || type.equalsIgnoreCase("VARCHAR") || type.equalsIgnoreCase("VARCHAR2") ||
type.equalsIgnoreCase("STRING") || type.equalsIgnoreCase("XML")) {
return Type.STRING;
}
else if (type.equalsIgnoreCase("DEC") || type.equalsIgnoreCase("DECIMAL") || type.equalsIgnoreCase("NUMERIC") ||
type.equalsIgnoreCase("NUMBER")) {
return Type.DECIMAL;
}
else if (type.equalsIgnoreCase("REAL") || type.equalsIgnoreCase("FLOAT") || type.toUpperCase().startsWith("DOUBLE") ||
type.equalsIgnoreCase("BINARY_FLOAT") || type.toUpperCase().startsWith("BINARY_DOUBLE") ||
type.equalsIgnoreCase("SIMPLE_FLOAT") || type.toUpperCase().startsWith("SIMPLE_DOUBLE")) {
return Type.DOUBLE;
}
else if (type.equalsIgnoreCase("DATE")) {
return Type.DATE;
}
else if (type.equalsIgnoreCase("TIMESTAMP")) {
return Type.TIMESTAMP;
}
else if (type.equalsIgnoreCase("BOOL") || type.equalsIgnoreCase("BOOLEAN")) {
return Type.BOOL;
}
else if (type.equalsIgnoreCase("SYS_REFCURSOR")) {
return Type.CURSOR;
}
else if (type.equalsIgnoreCase("UTL_FILE.FILE_TYPE")) {
return Type.FILE;
}
else if (type.toUpperCase().startsWith("RESULT_SET_LOCATOR")) {
return Type.RS_LOCATOR;
}
else if (type.equalsIgnoreCase(Var.DERIVED_TYPE)) {
return Type.DERIVED_TYPE;
}
return Type.NULL;
}
/**
* Define the data type from JDBC type code
*/
public static Type defineType(int type) {
if (type == java.sql.Types.CHAR || type == java.sql.Types.VARCHAR) {
return Type.STRING;
}
else if (type == java.sql.Types.INTEGER || type == java.sql.Types.BIGINT) {
return Type.BIGINT;
}
return Type.NULL;
}
/**
* Remove value
*/
public void removeValue() {
type = Type.NULL;
name = null;
value = null;
len = 0;
scale = 0;
}
/**
* Compare values
*/
@Override
public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
Var var = (Var)obj;
if (this == var) {
return true;
}
else if (var == null || var.value == null || this.value == null) {
return false;
}
if (type == Type.BIGINT) {
if (var.type == Type.BIGINT && ((Long)value).longValue() == ((Long)var.value).longValue()) {
return true;
}
else if (var.type == Type.DECIMAL) {
return equals((BigDecimal)var.value, (Long)value);
}
}
else if (type == Type.STRING && var.type == Type.STRING &&
((String)value).equals((String)var.value)) {
return true;
}
else if (type == Type.DECIMAL && var.type == Type.DECIMAL &&
((BigDecimal)value).compareTo((BigDecimal)var.value) == 0) {
return true;
}
else if (type == Type.DOUBLE) {
if (var.type == Type.DOUBLE && ((Double)value).compareTo((Double)var.value) == 0) {
return true;
}
else if (var.type == Type.DECIMAL && ((Double)value).compareTo(((BigDecimal)var.value).doubleValue()) == 0) {
return true;
}
}
return false;
}
/**
* Check if variables of different data types are equal
*/
public boolean equals(BigDecimal d, Long i) {
if (d.compareTo(new BigDecimal(i)) == 0) {
return true;
}
return false;
}
/**
* Compare values
*/
public int compareTo(Var v) {
if (this == v) {
return 0;
}
else if (v == null) {
return -1;
}
else if (type == Type.BIGINT && v.type == Type.BIGINT) {
return ((Long)value).compareTo((Long)v.value);
}
else if (type == Type.STRING && v.type == Type.STRING) {
return ((String)value).compareTo((String)v.value);
}
return -1;
}
/**
* Calculate difference between values in percent
*/
public BigDecimal percentDiff(Var var) {
BigDecimal d1 = new Var(Var.Type.DECIMAL).cast(this).decimalValue();
BigDecimal d2 = new Var(Var.Type.DECIMAL).cast(var).decimalValue();
if (d1 != null && d2 != null) {
if (d1.compareTo(BigDecimal.ZERO) != 0) {
return d1.subtract(d2).abs().multiply(new BigDecimal(100)).divide(d1, 2, RoundingMode.HALF_UP);
}
}
return null;
}
/**
* Increment an integer value
*/
public Var increment(Long i) {
if (type == Type.BIGINT) {
value = new Long(((Long)value).longValue() + i);
}
return this;
}
/**
* Decrement an integer value
*/
public Var decrement(Long i) {
if (type == Type.BIGINT) {
value = new Long(((Long)value).longValue() - i);
}
return this;
}
/**
* Return an integer value
*/
public int intValue() {
if (type == Type.BIGINT) {
return ((Long)value).intValue();
}
else if (type == Type.STRING) {
return Integer.parseInt((String)value);
}
throw new NumberFormatException();
}
/**
* Return a long integer value
*/
public long longValue() {
if (type == Type.BIGINT) {
return ((Long)value).longValue();
}
throw new NumberFormatException();
}
/**
* Return a decimal value
*/
public BigDecimal decimalValue() {
if (type == Type.DECIMAL) {
return (BigDecimal)value;
}
throw new NumberFormatException();
}
/**
* Return a double value
*/
public double doubleValue() {
if (type == Type.DOUBLE) {
return ((Double)value).doubleValue();
}
else if (type == Type.BIGINT) {
return ((Long)value).doubleValue();
}
else if (type == Type.DECIMAL) {
return ((BigDecimal)value).doubleValue();
}
throw new NumberFormatException();
}
/**
* Return true/false for BOOL type
*/
public boolean isTrue() {
if(type == Type.BOOL && value != null) {
return ((Boolean)value).booleanValue();
}
return false;
}
/**
* Negate the boolean value
*/
public void negate() {
if(type == Type.BOOL && value != null) {
boolean v = ((Boolean)value).booleanValue();
value = Boolean.valueOf(!v);
}
}
/**
* Check if the variable contains NULL
*/
public boolean isNull() {
if (type == Type.NULL || value == null) {
return true;
}
return false;
}
/**
* Convert value to String
*/
@Override
public String toString() {
if (type == Type.IDENT) {
return name;
}
else if (value == null) {
return null;
}
else if (type == Type.BIGINT) {
return ((Long)value).toString();
}
else if (type == Type.STRING) {
return (String)value;
}
else if (type == Type.DATE) {
return ((Date)value).toString();
}
else if (type == Type.TIMESTAMP) {
int len = 19;
String t = ((Timestamp)value).toString(); // .0 returned if the fractional part not set
if (scale > 0) {
len += scale + 1;
}
if (t.length() > len) {
t = t.substring(0, len);
}
return t;
}
return value.toString();
}
/**
* Convert value to SQL string - string literals are quoted and escaped, ab'c -> 'ab''c'
*/
public String toSqlString() {
if (value == null) {
return "NULL";
}
else if (type == Type.STRING) {
return Utils.quoteString((String)value);
}
return toString();
}
/**
* Set variable name
*/
public void setName(String name) {
this.name = name;
}
/**
* Get variable name
*/
public String getName() {
return name;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy