summaryrefslogtreecommitdiff
path: root/src/library/scala/dbc/datatype/Factory.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/scala/dbc/datatype/Factory.scala')
-rw-r--r--src/library/scala/dbc/datatype/Factory.scala246
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.")
+ }
+ }
+}