/* * Microsoft JDBC Driver for SQL Server * * Copyright(c) Microsoft Corporation All rights reserved. * * This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information. */ package com.microsoft.sqlserver.testframework.sqlType; import java.sql.JDBCType; import java.util.BitSet; import java.util.concurrent.ThreadLocalRandom; import com.microsoft.sqlserver.testframework.DBCoercion; import com.microsoft.sqlserver.testframework.DBCoercions; import com.microsoft.sqlserver.testframework.DBConnection; import com.microsoft.sqlserver.testframework.DBItems; public abstract class SqlType extends DBItems { // TODO: add seed to generate random data -> will help to reproduce the // exact data for debugging protected String name = null; // type name for creating SQL query protected JDBCType jdbctype = JDBCType.NULL; protected int precision = 0; protected int scale = 0; protected Object minvalue = null; protected Object maxvalue = null; protected Object nullvalue = null; // Primitives have non-null defaults protected VariableLengthType variableLengthType; protected Class type = null; protected BitSet flags = new BitSet(); protected DBCoercions coercions = new DBCoercions(); public static final int DEFAULT = 0; public static final int NULLABLE = 1; public static final int UPDATABLE = 2; public static final int NUMERIC = 3; public static final int FLOATINGPOINT = 4; public static final int FIXED = 5; public static final int CREATEPARAMS = 6; public static final int CHARACTER = 7; public static final int UNICODE = 8; public static final int LONG = 9; public static final int SEARCHABLE = 10; public static final int XML = 11; public static final int UDT = 12; public static final int BINARY = 13; public static final int TEMPORAL = 14; public static final int BOOLEAN = 15; public static final int PRIMITIVE = 16; public static final int COLLATE = 17; public static final int GUID = 18; /** * * @param name * @param jdbctype * @param precision * @param scale * @param min * minimum allowed value for the SQL type * @param max * maximum allowed value for the SQL type * @param nullvalue * default null value for the SQL type * @param variableLengthType * {@link VariableLengthType} */ SqlType(String name, JDBCType jdbctype, int precision, int scale, Object min, Object max, Object nullvalue, VariableLengthType variableLengthType, Class type) { this.name = name; this.jdbctype = jdbctype; this.precision = precision; this.scale = scale; this.minvalue = min; this.maxvalue = max; this.nullvalue = nullvalue; this.variableLengthType = variableLengthType; this.type = type; } /** * * @return valid random value for the SQL type */ public Object createdata() { try { return null; } catch (Exception e) { // Make this easier to debug throw new Error("createdata failed: ", e); } } /** * create valid random value for the SQL type * @param type * @param data * @return */ public Object createdata(Class type, byte[] data) { if (type == String.class) return new String(data); return data; } /** * * @return JDBCType of SqlType object */ public JDBCType getJdbctype() { return jdbctype; } /** * * @return */ public Class getType() { return type; } /** * * @param jdbctype * set JDBCType of SqlType object */ public void setJdbctype(JDBCType jdbctype) { this.jdbctype = jdbctype; } /** * * @return precision set for the SqlType */ public int getPrecision() { return precision; } /** * * @param precision * set precision for SqlType */ public void setPrecision(int precision) { this.precision = precision; } /** * * @return scale set for the SqlType */ public int getScale() { return scale; } /** * * @param scale * set precision for SqlType */ public void setScale(int scale) { this.scale = scale; } /** * * @return string value of SqlType */ public String getName() { return name; } /** * * @return null value for the SqlType */ public Object getNullvalue() { return nullvalue; } /** * * @return minimum allowed value for the SQL type */ public Object getMinvalue() { return minvalue; } /** * * @return maximum allowed value for the SQL type */ public Object getMaxvalue() { return maxvalue; } /** * * @return variableLengthType {@link VariableLengthType} */ public Object getVariableLengthType() { return variableLengthType; } /** * generates random precision for SQL types with precision */ void generatePrecision() { int minPrecision = 1; int maxPrecision = this.precision; this.precision = ThreadLocalRandom.current().nextInt(minPrecision, maxPrecision + 1); } /** * generates random precision for SQL types with scale */ void generateScale() { int minScale = 1; int maxScale = this.scale; this.scale = ThreadLocalRandom.current().nextInt(minScale, maxScale + 1); } /** * @return */ public boolean isString() { return flags.get(CHARACTER); } /** * * @param target * @param flag * @param conn * @return * @throws Exception */ public boolean canConvert(Class target, int flag, DBConnection conn) throws Exception { double serverversion = conn.getServerVersion(); if (flag == DBCoercion.SET || flag == DBCoercion.SETOBJECT || flag == DBCoercion.UPDATE || flag == DBCoercion.UPDATEOBJECT || flag == DBCoercion.REG) { // SQL 8 does not allow conversion from string to money if (flag != DBCoercion.SETOBJECT && serverversion < 9.0 && this instanceof SqlMoney && target == String.class) return false; if (flag == DBCoercion.SET || flag == DBCoercion.SETOBJECT) { // setTemporal() on textual columns returns unverifiable format if (this.isString() && (target == java.sql.Date.class || target == java.sql.Time.class || target == java.sql.Timestamp.class)) return false; } } DBCoercion coercion = coercions.find(target); if (coercion != null) return coercion.flags().get(flag); return false; } }