diff options
Diffstat (limited to 'src/library/scala/dbc/datatype/Factory.scala')
-rw-r--r-- | src/library/scala/dbc/datatype/Factory.scala | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/library/scala/dbc/datatype/Factory.scala b/src/library/scala/dbc/datatype/Factory.scala new file mode 100644 index 0000000000..13d9cd35e2 --- /dev/null +++ b/src/library/scala/dbc/datatype/Factory.scala @@ -0,0 +1,246 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.dbc.datatype; + +import java.sql.Types._; +import java.math.BigInteger; +import java.math.BigDecimal; + +object Factory { + + final val java_lang_Integer_SIZE = 32; + final val java_lang_Long_SIZE = 64; + + /** Returns a mullable property formated as a boolean option */ + def isNullable (metadata:java.sql.ResultSetMetaData, index:Int): Option[scala.Boolean] = + metadata.isNullable(index) match { + case java.sql.ResultSetMetaData.columnNoNulls => Some(false); + case java.sql.ResultSetMetaData.columnNullable => Some(true); + case java.sql.ResultSetMetaData.columnNoNulls => None; + } + + /** Returns the binary precision for an integer field. This should only be + * used to find precision for integer numbers. It assumes that + * bytes cannot be used partially (result % 8 = 0). */ + def bytePrecision (precision:Int, signed:scala.Boolean, safe:scala.Boolean): Int = { + val decimalPrecision = precision + (if (safe) 1 else 0); + Pair(signed,decimalPrecision) match { + case Pair(_,0) => java.lang.Integer.MAX_VALUE // That's a bit of a hack. + case Pair(_,dp) if (dp <= 3) => 8 + case Pair(_,dp) if (dp <= 5) => 16 + case Pair(true,dp) if (dp <= 7) => 24 + case Pair(false,dp) if (dp <= 8) => 24 + case Pair(_,dp) if (dp <= 10) => 32 + case Pair(true,dp) if (dp <= 12) => 40 + case Pair(false,dp) if (dp <= 13) => 40 + case Pair(_,dp) if (dp <= 15) => 48 + case Pair(_,dp) if (dp <= 17) => 56 + case Pair(true,dp) if (dp <= 19) => 64 + case Pair(false,dp) if (dp <= 20) => 64 + case Pair(_,dp) if (dp <= 22) => 72 + case Pair(true,dp) if (dp <= 24) => 80 + case Pair(false,dp) if (dp <= 25) => 80 + case Pair(_,dp) if (dp <= 27) => 88 + case Pair(_,dp) if (dp <= 29) => 96 + case Pair(_,dp) if (dp <= 32) => 104 + case Pair(_,dp) if (dp <= 34) => 112 + case Pair(true,dp) if (dp <= 36) => 120 + case Pair(false,dp) if (dp <= 37) => 120 + case Pair(_,dp) if (dp <= 39) => 128 + case _ => java.lang.Integer.MAX_VALUE + } + } + + def create (metadata:java.sql.ResultSetMetaData, index:Int): DataType = { + metadata.getColumnType(index) match { + /* Boolean data types. */ + case BOOLEAN => new datatype.Boolean { + override val nullable = isNullable(metadata,index); + } + case BIT => new datatype.Boolean { + override val nullable = isNullable(metadata,index); + } + /* Fixed precision numeric data types. */ + case DECIMAL => { + Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match { + case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) => + new datatype.ExactNumeric[Int](DataType.INT) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(bp,true) if (bp <= java_lang_Long_SIZE) => + new datatype.ExactNumeric[Long](DataType.LONG) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(_,true) => + new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(_,false) => + new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + } + } + case NUMERIC => { + Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match { + case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) => + new datatype.ExactNumeric[Int](DataType.INT) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(bp,true) if (bp <= java_lang_Long_SIZE) => + new datatype.ExactNumeric[Long](DataType.LONG) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(_,true) => + new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + case Pair(_,false) => + new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 10; + val precision = metadata.getPrecision(index); + val signed = metadata.isSigned(index); + val scale = metadata.getScale(index); + } + } + } + /* Fixed precision integer data types. */ + case BIGINT => + new datatype.ExactNumeric[Long](DataType.LONG) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 64; + val signed = metadata.isSigned(index); + val scale = 0; + } + case INTEGER => + new datatype.ExactNumeric[Int](DataType.INT) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 32; + val signed = metadata.isSigned(index); + val scale = 0; + } + case SMALLINT => + new datatype.ExactNumeric[Short](DataType.SHORT) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 16; + val signed = metadata.isSigned(index); + val scale = 0; + } + case TINYINT => + new datatype.ExactNumeric[Byte](DataType.BYTE) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 8; + val signed = metadata.isSigned(index); + val scale = 0; + } + /* Floating point numeric data types. */ + case REAL => + new datatype.ApproximateNumeric[Float](DataType.FLOAT) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 64; + val signed = metadata.isSigned(index); + } + case DOUBLE => + new datatype.ApproximateNumeric[Double](DataType.DOUBLE) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 128; + val signed = metadata.isSigned(index); + } + case FLOAT => + new datatype.ApproximateNumeric[Double](DataType.DOUBLE) { + override val nullable = isNullable(metadata,index); + val precisionRadix = 2; + val precision = 128; + val signed = metadata.isSigned(index); + } + /* Character string data types. */ + case CHAR => new datatype.Character { + override val nullable = isNullable(metadata,index); + val length = metadata.getColumnDisplaySize(index); + } + case CLOB => new datatype.CharacterLargeObject { + override val nullable = isNullable(metadata,index); + } + case LONGVARCHAR => { + if (metadata.getColumnDisplaySize(index) >= 0) + new datatype.CharacterVarying { + override val nullable = isNullable(metadata,index); + def length = metadata.getColumnDisplaySize(index); + } + else // A PostgreSQL Hack + new datatype.CharacterLargeObject { + override val nullable = isNullable(metadata,index); + } + } + case VARCHAR => { + if (metadata.getColumnDisplaySize(index) >= 0) + new datatype.CharacterVarying { + override val nullable = isNullable(metadata,index); + def length = metadata.getColumnDisplaySize(index); + } + else // A PostgreSQL Hack + new datatype.CharacterLargeObject { + override val nullable = isNullable(metadata,index); + } + } + /* Undefined cases. */ + case OTHER => new datatype.Unknown { + override val nullable = isNullable(metadata, index); + } + /* Unsupported data types. */ + case REF | ARRAY | STRUCT => + error ("I don't support composite data types yet."); + case DATALINK | DISTINCT | JAVA_OBJECT | NULL => + error ("I won't support strange data types."); + /* Unsupported binary string data types. */ + case BINARY | BLOB | LONGVARBINARY | VARBINARY => + error ("I don't support binary string data types yet."); + /* Unsupported date and time data types. */ + case DATE | TIME | TIMESTAMP => + error ("I don't support date and time data types yet."); + /* Default case */ + case x => error ("I don't know about this ("+metadata.getColumnTypeName(index)+") JDBC type.") + } + } +} |