From 0a5eb2c599eead1eeba7559ed0dcc5706079bf4d Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Mon, 20 Mar 2006 15:58:47 +0000 Subject: 1. 2. ScalaTool Ant task updated to be more flexible. 3. Build now generates a separate archive for DBC (also changed in source layout). --- src/compiler/scala/tools/ant/ScalaTool.scala | 125 +++++----- .../scala/tools/ant/templates/generic-unix.tmpl | 85 ++++--- .../scala/tools/ant/templates/int-unix.tmpl | 99 -------- .../scala/tools/ant/templates/tool-unix.tmpl | 74 +++--- src/dbc/scala/dbc/DataType.scala | 70 ++++++ src/dbc/scala/dbc/Database.scala | 189 ++++++++++++++ src/dbc/scala/dbc/Syntax.scala | 48 ++++ src/dbc/scala/dbc/Utilities.scala | 29 +++ src/dbc/scala/dbc/Value.scala | 28 +++ src/dbc/scala/dbc/Vendor.scala | 42 ++++ .../scala/dbc/datatype/ApproximateNumeric.scala | 57 +++++ src/dbc/scala/dbc/datatype/Boolean.scala | 31 +++ src/dbc/scala/dbc/datatype/Character.scala | 40 +++ .../scala/dbc/datatype/CharacterLargeObject.scala | 31 +++ src/dbc/scala/dbc/datatype/CharacterString.scala | 24 ++ src/dbc/scala/dbc/datatype/CharacterVarying.scala | 41 +++ src/dbc/scala/dbc/datatype/ExactNumeric.scala | 65 +++++ src/dbc/scala/dbc/datatype/Factory.scala | 250 +++++++++++++++++++ src/dbc/scala/dbc/datatype/Numeric.scala | 32 +++ src/dbc/scala/dbc/datatype/String.scala | 24 ++ src/dbc/scala/dbc/datatype/Unknown.scala | 34 +++ .../scala/dbc/exception/IncompatibleSchema.scala | 19 ++ .../scala/dbc/exception/UnsupportedFeature.scala | 16 ++ src/dbc/scala/dbc/result/Field.scala | 63 +++++ src/dbc/scala/dbc/result/FieldMetadata.scala | 36 +++ src/dbc/scala/dbc/result/Relation.scala | 72 ++++++ src/dbc/scala/dbc/result/Status.scala | 28 +++ src/dbc/scala/dbc/result/Tuple.scala | 42 ++++ src/dbc/scala/dbc/statement/AccessMode.scala | 26 ++ src/dbc/scala/dbc/statement/DerivedColumn.scala | 36 +++ src/dbc/scala/dbc/statement/Expression.scala | 29 +++ src/dbc/scala/dbc/statement/Insert.scala | 36 +++ src/dbc/scala/dbc/statement/InsertionData.scala | 41 +++ src/dbc/scala/dbc/statement/IsolationLevel.scala | 32 +++ src/dbc/scala/dbc/statement/JoinType.scala | 49 ++++ src/dbc/scala/dbc/statement/Jointure.scala | 47 ++++ src/dbc/scala/dbc/statement/Relation.scala | 55 +++++ src/dbc/scala/dbc/statement/Select.scala | 95 +++++++ src/dbc/scala/dbc/statement/SetClause.scala | 22 ++ src/dbc/scala/dbc/statement/SetQuantifier.scala | 34 +++ src/dbc/scala/dbc/statement/Statement.scala | 18 ++ src/dbc/scala/dbc/statement/Status.scala | 30 +++ src/dbc/scala/dbc/statement/Table.scala | 40 +++ src/dbc/scala/dbc/statement/Transaction.scala | 55 +++++ src/dbc/scala/dbc/statement/Update.scala | 47 ++++ .../scala/dbc/statement/expression/Aggregate.scala | 34 +++ .../dbc/statement/expression/BinaryOperator.scala | 32 +++ .../scala/dbc/statement/expression/Constant.scala | 22 ++ .../scala/dbc/statement/expression/Default.scala | 21 ++ src/dbc/scala/dbc/statement/expression/Field.scala | 39 +++ .../dbc/statement/expression/FunctionCall.scala | 32 +++ .../scala/dbc/statement/expression/Select.scala | 27 ++ .../dbc/statement/expression/SetFunction.scala | 39 +++ .../scala/dbc/statement/expression/TypeCast.scala | 31 +++ .../dbc/statement/expression/UnaryOperator.scala | 32 +++ src/dbc/scala/dbc/syntax/DataTypeUtil.scala | 98 ++++++++ src/dbc/scala/dbc/syntax/Database.scala | 33 +++ src/dbc/scala/dbc/syntax/Statement.scala | 274 +++++++++++++++++++++ src/dbc/scala/dbc/syntax/StatementExpression.scala | 221 +++++++++++++++++ src/dbc/scala/dbc/value/ApproximateNumeric.scala | 28 +++ src/dbc/scala/dbc/value/Boolean.scala | 27 ++ src/dbc/scala/dbc/value/Character.scala | 35 +++ src/dbc/scala/dbc/value/CharacterLargeObject.scala | 35 +++ src/dbc/scala/dbc/value/CharacterVarying.scala | 35 +++ src/dbc/scala/dbc/value/Conversion.scala | 157 ++++++++++++ src/dbc/scala/dbc/value/ExactNumeric.scala | 35 +++ src/dbc/scala/dbc/value/Factory.scala | 95 +++++++ src/dbc/scala/dbc/value/Unknown.scala | 27 ++ src/dbc/scala/dbc/vendor/PostgreSQL.scala | 27 ++ src/library/scala/dbc/DataType.scala | 70 ------ src/library/scala/dbc/Database.scala | 190 -------------- src/library/scala/dbc/Syntax.scala | 48 ---- src/library/scala/dbc/Utilities.scala | 29 --- src/library/scala/dbc/Value.scala | 28 --- src/library/scala/dbc/Vendor.scala | 42 ---- .../scala/dbc/datatype/ApproximateNumeric.scala | 57 ----- src/library/scala/dbc/datatype/Boolean.scala | 31 --- src/library/scala/dbc/datatype/Character.scala | 40 --- .../scala/dbc/datatype/CharacterLargeObject.scala | 31 --- .../scala/dbc/datatype/CharacterString.scala | 24 -- .../scala/dbc/datatype/CharacterVarying.scala | 41 --- src/library/scala/dbc/datatype/ExactNumeric.scala | 65 ----- src/library/scala/dbc/datatype/Factory.scala | 250 ------------------- src/library/scala/dbc/datatype/Numeric.scala | 32 --- src/library/scala/dbc/datatype/String.scala | 24 -- src/library/scala/dbc/datatype/Unknown.scala | 34 --- .../scala/dbc/exception/IncompatibleSchema.scala | 19 -- .../scala/dbc/exception/UnsupportedFeature.scala | 16 -- src/library/scala/dbc/result/Field.scala | 63 ----- src/library/scala/dbc/result/FieldMetadata.scala | 36 --- src/library/scala/dbc/result/Relation.scala | 72 ------ src/library/scala/dbc/result/Status.scala | 28 --- src/library/scala/dbc/result/Tuple.scala | 42 ---- src/library/scala/dbc/statement/AccessMode.scala | 26 -- .../scala/dbc/statement/DerivedColumn.scala | 36 --- src/library/scala/dbc/statement/Expression.scala | 29 --- src/library/scala/dbc/statement/Insert.scala | 36 --- .../scala/dbc/statement/InsertionData.scala | 41 --- .../scala/dbc/statement/IsolationLevel.scala | 32 --- src/library/scala/dbc/statement/JoinType.scala | 49 ---- src/library/scala/dbc/statement/Jointure.scala | 47 ---- src/library/scala/dbc/statement/Relation.scala | 55 ----- src/library/scala/dbc/statement/Select.scala | 95 ------- src/library/scala/dbc/statement/SetClause.scala | 22 -- .../scala/dbc/statement/SetQuantifier.scala | 34 --- src/library/scala/dbc/statement/Statement.scala | 18 -- src/library/scala/dbc/statement/Status.scala | 30 --- src/library/scala/dbc/statement/Table.scala | 40 --- src/library/scala/dbc/statement/Transaction.scala | 55 ----- src/library/scala/dbc/statement/Update.scala | 47 ---- .../scala/dbc/statement/expression/Aggregate.scala | 34 --- .../dbc/statement/expression/BinaryOperator.scala | 32 --- .../scala/dbc/statement/expression/Constant.scala | 22 -- .../scala/dbc/statement/expression/Default.scala | 21 -- .../scala/dbc/statement/expression/Field.scala | 39 --- .../dbc/statement/expression/FunctionCall.scala | 32 --- .../scala/dbc/statement/expression/Select.scala | 27 -- .../dbc/statement/expression/SetFunction.scala | 39 --- .../scala/dbc/statement/expression/TypeCast.scala | 31 --- .../dbc/statement/expression/UnaryOperator.scala | 32 --- src/library/scala/dbc/syntax/DataTypeUtil.scala | 98 -------- src/library/scala/dbc/syntax/Database.scala | 33 --- src/library/scala/dbc/syntax/Statement.scala | 274 --------------------- .../scala/dbc/syntax/StatementExpression.scala | 221 ----------------- .../scala/dbc/value/ApproximateNumeric.scala | 28 --- src/library/scala/dbc/value/Boolean.scala | 27 -- src/library/scala/dbc/value/Character.scala | 35 --- .../scala/dbc/value/CharacterLargeObject.scala | 35 --- src/library/scala/dbc/value/CharacterVarying.scala | 35 --- src/library/scala/dbc/value/Conversion.scala | 157 ------------ src/library/scala/dbc/value/ExactNumeric.scala | 35 --- src/library/scala/dbc/value/Factory.scala | 95 ------- src/library/scala/dbc/value/Unknown.scala | 27 -- src/library/scala/dbc/vendor/PostgreSQL.scala | 27 -- 134 files changed, 3576 insertions(+), 3686 deletions(-) delete mode 100644 src/compiler/scala/tools/ant/templates/int-unix.tmpl create mode 100644 src/dbc/scala/dbc/DataType.scala create mode 100644 src/dbc/scala/dbc/Database.scala create mode 100644 src/dbc/scala/dbc/Syntax.scala create mode 100644 src/dbc/scala/dbc/Utilities.scala create mode 100644 src/dbc/scala/dbc/Value.scala create mode 100644 src/dbc/scala/dbc/Vendor.scala create mode 100644 src/dbc/scala/dbc/datatype/ApproximateNumeric.scala create mode 100644 src/dbc/scala/dbc/datatype/Boolean.scala create mode 100644 src/dbc/scala/dbc/datatype/Character.scala create mode 100644 src/dbc/scala/dbc/datatype/CharacterLargeObject.scala create mode 100644 src/dbc/scala/dbc/datatype/CharacterString.scala create mode 100644 src/dbc/scala/dbc/datatype/CharacterVarying.scala create mode 100644 src/dbc/scala/dbc/datatype/ExactNumeric.scala create mode 100644 src/dbc/scala/dbc/datatype/Factory.scala create mode 100644 src/dbc/scala/dbc/datatype/Numeric.scala create mode 100644 src/dbc/scala/dbc/datatype/String.scala create mode 100644 src/dbc/scala/dbc/datatype/Unknown.scala create mode 100644 src/dbc/scala/dbc/exception/IncompatibleSchema.scala create mode 100644 src/dbc/scala/dbc/exception/UnsupportedFeature.scala create mode 100644 src/dbc/scala/dbc/result/Field.scala create mode 100644 src/dbc/scala/dbc/result/FieldMetadata.scala create mode 100644 src/dbc/scala/dbc/result/Relation.scala create mode 100644 src/dbc/scala/dbc/result/Status.scala create mode 100644 src/dbc/scala/dbc/result/Tuple.scala create mode 100644 src/dbc/scala/dbc/statement/AccessMode.scala create mode 100644 src/dbc/scala/dbc/statement/DerivedColumn.scala create mode 100644 src/dbc/scala/dbc/statement/Expression.scala create mode 100644 src/dbc/scala/dbc/statement/Insert.scala create mode 100644 src/dbc/scala/dbc/statement/InsertionData.scala create mode 100644 src/dbc/scala/dbc/statement/IsolationLevel.scala create mode 100644 src/dbc/scala/dbc/statement/JoinType.scala create mode 100644 src/dbc/scala/dbc/statement/Jointure.scala create mode 100644 src/dbc/scala/dbc/statement/Relation.scala create mode 100644 src/dbc/scala/dbc/statement/Select.scala create mode 100644 src/dbc/scala/dbc/statement/SetClause.scala create mode 100644 src/dbc/scala/dbc/statement/SetQuantifier.scala create mode 100644 src/dbc/scala/dbc/statement/Statement.scala create mode 100644 src/dbc/scala/dbc/statement/Status.scala create mode 100644 src/dbc/scala/dbc/statement/Table.scala create mode 100644 src/dbc/scala/dbc/statement/Transaction.scala create mode 100644 src/dbc/scala/dbc/statement/Update.scala create mode 100644 src/dbc/scala/dbc/statement/expression/Aggregate.scala create mode 100644 src/dbc/scala/dbc/statement/expression/BinaryOperator.scala create mode 100644 src/dbc/scala/dbc/statement/expression/Constant.scala create mode 100644 src/dbc/scala/dbc/statement/expression/Default.scala create mode 100644 src/dbc/scala/dbc/statement/expression/Field.scala create mode 100644 src/dbc/scala/dbc/statement/expression/FunctionCall.scala create mode 100644 src/dbc/scala/dbc/statement/expression/Select.scala create mode 100644 src/dbc/scala/dbc/statement/expression/SetFunction.scala create mode 100644 src/dbc/scala/dbc/statement/expression/TypeCast.scala create mode 100644 src/dbc/scala/dbc/statement/expression/UnaryOperator.scala create mode 100644 src/dbc/scala/dbc/syntax/DataTypeUtil.scala create mode 100644 src/dbc/scala/dbc/syntax/Database.scala create mode 100644 src/dbc/scala/dbc/syntax/Statement.scala create mode 100644 src/dbc/scala/dbc/syntax/StatementExpression.scala create mode 100644 src/dbc/scala/dbc/value/ApproximateNumeric.scala create mode 100644 src/dbc/scala/dbc/value/Boolean.scala create mode 100644 src/dbc/scala/dbc/value/Character.scala create mode 100644 src/dbc/scala/dbc/value/CharacterLargeObject.scala create mode 100644 src/dbc/scala/dbc/value/CharacterVarying.scala create mode 100644 src/dbc/scala/dbc/value/Conversion.scala create mode 100644 src/dbc/scala/dbc/value/ExactNumeric.scala create mode 100644 src/dbc/scala/dbc/value/Factory.scala create mode 100644 src/dbc/scala/dbc/value/Unknown.scala create mode 100644 src/dbc/scala/dbc/vendor/PostgreSQL.scala delete mode 100644 src/library/scala/dbc/DataType.scala delete mode 100644 src/library/scala/dbc/Database.scala delete mode 100644 src/library/scala/dbc/Syntax.scala delete mode 100644 src/library/scala/dbc/Utilities.scala delete mode 100644 src/library/scala/dbc/Value.scala delete mode 100644 src/library/scala/dbc/Vendor.scala delete mode 100644 src/library/scala/dbc/datatype/ApproximateNumeric.scala delete mode 100644 src/library/scala/dbc/datatype/Boolean.scala delete mode 100644 src/library/scala/dbc/datatype/Character.scala delete mode 100644 src/library/scala/dbc/datatype/CharacterLargeObject.scala delete mode 100644 src/library/scala/dbc/datatype/CharacterString.scala delete mode 100644 src/library/scala/dbc/datatype/CharacterVarying.scala delete mode 100644 src/library/scala/dbc/datatype/ExactNumeric.scala delete mode 100644 src/library/scala/dbc/datatype/Factory.scala delete mode 100644 src/library/scala/dbc/datatype/Numeric.scala delete mode 100644 src/library/scala/dbc/datatype/String.scala delete mode 100644 src/library/scala/dbc/datatype/Unknown.scala delete mode 100644 src/library/scala/dbc/exception/IncompatibleSchema.scala delete mode 100644 src/library/scala/dbc/exception/UnsupportedFeature.scala delete mode 100644 src/library/scala/dbc/result/Field.scala delete mode 100644 src/library/scala/dbc/result/FieldMetadata.scala delete mode 100644 src/library/scala/dbc/result/Relation.scala delete mode 100644 src/library/scala/dbc/result/Status.scala delete mode 100644 src/library/scala/dbc/result/Tuple.scala delete mode 100644 src/library/scala/dbc/statement/AccessMode.scala delete mode 100644 src/library/scala/dbc/statement/DerivedColumn.scala delete mode 100644 src/library/scala/dbc/statement/Expression.scala delete mode 100644 src/library/scala/dbc/statement/Insert.scala delete mode 100644 src/library/scala/dbc/statement/InsertionData.scala delete mode 100644 src/library/scala/dbc/statement/IsolationLevel.scala delete mode 100644 src/library/scala/dbc/statement/JoinType.scala delete mode 100644 src/library/scala/dbc/statement/Jointure.scala delete mode 100644 src/library/scala/dbc/statement/Relation.scala delete mode 100644 src/library/scala/dbc/statement/Select.scala delete mode 100644 src/library/scala/dbc/statement/SetClause.scala delete mode 100644 src/library/scala/dbc/statement/SetQuantifier.scala delete mode 100644 src/library/scala/dbc/statement/Statement.scala delete mode 100644 src/library/scala/dbc/statement/Status.scala delete mode 100644 src/library/scala/dbc/statement/Table.scala delete mode 100644 src/library/scala/dbc/statement/Transaction.scala delete mode 100644 src/library/scala/dbc/statement/Update.scala delete mode 100644 src/library/scala/dbc/statement/expression/Aggregate.scala delete mode 100644 src/library/scala/dbc/statement/expression/BinaryOperator.scala delete mode 100644 src/library/scala/dbc/statement/expression/Constant.scala delete mode 100644 src/library/scala/dbc/statement/expression/Default.scala delete mode 100644 src/library/scala/dbc/statement/expression/Field.scala delete mode 100644 src/library/scala/dbc/statement/expression/FunctionCall.scala delete mode 100644 src/library/scala/dbc/statement/expression/Select.scala delete mode 100644 src/library/scala/dbc/statement/expression/SetFunction.scala delete mode 100644 src/library/scala/dbc/statement/expression/TypeCast.scala delete mode 100644 src/library/scala/dbc/statement/expression/UnaryOperator.scala delete mode 100644 src/library/scala/dbc/syntax/DataTypeUtil.scala delete mode 100644 src/library/scala/dbc/syntax/Database.scala delete mode 100644 src/library/scala/dbc/syntax/Statement.scala delete mode 100644 src/library/scala/dbc/syntax/StatementExpression.scala delete mode 100644 src/library/scala/dbc/value/ApproximateNumeric.scala delete mode 100644 src/library/scala/dbc/value/Boolean.scala delete mode 100644 src/library/scala/dbc/value/Character.scala delete mode 100644 src/library/scala/dbc/value/CharacterLargeObject.scala delete mode 100644 src/library/scala/dbc/value/CharacterVarying.scala delete mode 100644 src/library/scala/dbc/value/Conversion.scala delete mode 100644 src/library/scala/dbc/value/ExactNumeric.scala delete mode 100644 src/library/scala/dbc/value/Factory.scala delete mode 100644 src/library/scala/dbc/value/Unknown.scala delete mode 100644 src/library/scala/dbc/vendor/PostgreSQL.scala (limited to 'src') diff --git a/src/compiler/scala/tools/ant/ScalaTool.scala b/src/compiler/scala/tools/ant/ScalaTool.scala index de130777ec..94ab2d9918 100644 --- a/src/compiler/scala/tools/ant/ScalaTool.scala +++ b/src/compiler/scala/tools/ant/ScalaTool.scala @@ -60,34 +60,34 @@ package scala.tools.ant { /** The path to the exec script file. ".bat" will be appended for the * Windows BAT file, if generated. */ private var file: Option[File] = None - /** The name of this tool. By default this is equal to the file name. */ - private var name: Option[String] = None - /** The main class to run. */ + /** The main class to run. If this is not set, a generic script will be generated */ private var mainClass: Option[String] = None + /** The name of this tool. Can only be set when a main class is defined, + * default this is equal to the file name. */ + private var name: Option[String] = None /** Supported platforms for the script. Either "unix" or "windows". Defaults * to both. */ private var platforms: List[String] = Nil /** The optional version number. If set, when "-version" is passed to the - * script, this value will be printed. */ + * script, this value will be printed. */ private var version: String = "" /** The optional copyright notice, that will be printed in the script. */ private var copyright: String = "This file is copyrighted by its owner" /** An (optional) path to all JARs that this script depend on. Paths must be * relative to the scala home directory. If not set, all JAR archives in * "lib/" are automatically added. */ - private var classpath: List[String] = Nil + private var extclasspath: List[String] = Nil /** Comma-separated Java system properties to pass to the JRE. Properties - * are formated as name=value. Properties scala.home and scala.tool.name - * are always set. */ + * are formated as name=value. Properties scala.home, scala.class.path, + * scala.boot.class.path and scala.ext.class.path are always set; + * scala.tool.name and scala.tool.version are set when this script is + * non-generic. */ private var properties: List[Pair[String,String]] = Nil /** Additional flags passed to the JRE ("java [javaFlags] class"). */ private var javaFlags: String = "" - /** Additional flags passed to the tool ("java class [toolFlags]"). */ + /** Additional flags passed to the tool ("java class [toolFlags]"). Can only + * be set when a main class is defined */ private var toolFlags: String = "" - /** The path to the generic runtime script file. ".bat" will be appended for - * the Windows BAT file, if generated. If not set, no generic runtime - * script will be generated. */ - private var genericFile: Option[File] = None /******************************************************************************\ ** Properties setters ** @@ -132,10 +132,10 @@ package scala.tools.ant { def setCopyright(input: String) = copyright = input - /** Sets the classpath attribute. Used by Ant. + /** Sets the extension classpath attribute. Used by Ant. * @param input The value of classpath. */ - def setClasspath(input: String) = - classpath = classpath ::: List.fromArray(input.split(":")) + def setExtclasspath(input: String) = + extclasspath = extclasspath ::: List.fromArray(input.split(":")) /** Sets the properties attribute. Used by Ant. * @param input The value for properties. */ @@ -158,11 +158,6 @@ package scala.tools.ant { def setToolflags(input: String) = toolFlags = input - /** Sets the version attribute. Used by Ant. - * @param input The value of version. */ - def setGenericfile(input: File) = - genericFile = Some(input) - /******************************************************************************\ ** Properties getters ** \******************************************************************************/ @@ -175,13 +170,13 @@ package scala.tools.ant { /** Gets the value of the classpath attribute in a Scala-friendly form. * @returns The class path as a list of files. */ - private def getUnixClasspath: String = - classpath.mkString("", ":", "") + private def getUnixExtClasspath: String = + extclasspath.mkString("", ":", "") /** Gets the value of the classpath attribute in a Scala-friendly form. * @returns The class path as a list of files. */ - private def getWinClasspath: String = - classpath.map(.replace('/', '\\')). + private def getWinExtClasspath: String = + extclasspath.map(.replace('/', '\\')). mkString("", ";", "") /** Gets the value of the classpath attribute in a Scala-friendly form. @@ -191,12 +186,6 @@ package scala.tools.ant { case Pair(name,value) => "-D" + name + "=\"" + value + "\"" }).mkString("", " ", "") - /** Gets the value of the file attribute in a Scala-friendly form. - * @returns The file as a file. */ - private def getGenericFile: File = - if (genericFile.isEmpty) error("Member 'file' is empty.") - else getProject().resolveFile(genericFile.get.toString()) - /******************************************************************************\ ** Compilation and support methods ** \******************************************************************************/ @@ -263,6 +252,24 @@ package scala.tools.ant { replaceAll("#([^#]*)#", "%_$1%") ) + private def pipeTemplate(template: String, patches: Map[String,String]) = { + val resourceRoot = "scala/tools/ant/templates/" + if (platforms.contains("unix")) { + val unixPatches = expandUnixVar(patches. + update("extclasspath", getUnixExtClasspath)) + val unixTemplateResource = resourceRoot + template + "-unix.tmpl" + val unixTemplate = readResource(unixTemplateResource, unixPatches) + writeFile(getFile, unixTemplate) + } + if (platforms.contains("windows")) { + val winPatches = expandWinVar(patches. + update("extclasspath", getWinExtClasspath)) + val winTemplateResource = resourceRoot + template + "-windows.tmpl" + val winTemplate = readResource(winTemplateResource, winPatches) + writeFile(new File(getFile.getAbsolutePath() + ".bat"), winTemplate) + } + } + /******************************************************************************\ ** The big execute method ** @@ -272,43 +279,29 @@ package scala.tools.ant { override def execute() = { // Tests if all mandatory attributes are set and valid. if (file.isEmpty) error("Attribute 'file' is not set.") - if (name.isEmpty) name = Some(file.get.getName()) - if (mainClass.isEmpty) error("Attribute 'mainclass' is not set.") if (platforms.isEmpty) platforms = Platforms.values - // Gets the input streams for the script templates. - val resourceRoot = "scala/tools/ant/templates/" - val patches = ListMap.Empty. - update("name", name.get). - update("class", mainClass.get). - update("version", version). - update("copyright", copyright). - update("properties", getProperties). - update("javaflags", javaFlags). - update("toolflags", toolFlags) - if (platforms.contains("unix")) { - val unixPatches = expandUnixVar( - patches.update("classpath", getUnixClasspath)) - val unixTemplateResource = resourceRoot + "tool-unix.tmpl" - val unixTemplate = readResource(unixTemplateResource, unixPatches) - writeFile(getFile, unixTemplate) - if (!genericFile.isEmpty) { - val unixTemplateResource = resourceRoot + "generic-unix.tmpl" - val unixTemplate = readResource(unixTemplateResource, unixPatches) - writeFile(getGenericFile, unixTemplate) - } - } - if (platforms.contains("windows")) { - val winPatches = expandWinVar( - patches.update("classpath", getWinClasspath)) - val winTemplateResource = resourceRoot + "tool-windows.tmpl" - val winTemplate = readResource(winTemplateResource, winPatches) - writeFile(new File(getFile.getAbsolutePath() + ".bat"), winTemplate) - if (!genericFile.isEmpty) { - val winTemplateResource = resourceRoot + "generic-windows.tmpl" - val winTemplate = readResource(winTemplateResource, winPatches) - writeFile(new File(getGenericFile.getAbsolutePath() + ".bat"), - winTemplate) - } + if (mainClass.isEmpty) { + if (toolFlags != "") + error("Attribute 'toolflags' cannot be set in a generic file.") + if (!name.isEmpty) + error("Attribute 'name' cannot be set in a generic file.") + val patches = ListMap.Empty. + update("version", version). + update("copyright", copyright). + update("properties", getProperties). + update("javaflags", javaFlags) + pipeTemplate("generic", patches) + } else { + val patches = ListMap.Empty. + update("name", name.get). + update("class", mainClass.get). + update("version", version). + update("copyright", copyright). + update("properties", getProperties). + update("javaflags", javaFlags). + update("toolflags", toolFlags) + if (name.isEmpty) name = Some(file.get.getName()) + pipeTemplate("tool", patches) } } diff --git a/src/compiler/scala/tools/ant/templates/generic-unix.tmpl b/src/compiler/scala/tools/ant/templates/generic-unix.tmpl index c06273c36e..e2c899682e 100644 --- a/src/compiler/scala/tools/ant/templates/generic-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/generic-unix.tmpl @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh ############################################################################## # Scala runtime @version@ @@ -31,50 +31,58 @@ done; SCALA_HOME=`dirname "$SOURCE"`/..; SCALA_HOME=`cd "$SCALA_HOME"; pwd`; -## buraq: previous version of this script computed the MYCLASSPATH and -## then appended it to the bootclasspath. Unfortunately, this -## won't work for library code that uses reflection to obtain -## a class living on the classpath. For this reason, we have -## to merge everything in the -cp classpath. This requires -## intercepting the user's -cp, if any, or the user's $CLASSPATH, -## if set, appending our libs to it and passing the whole thing by -cp +EXTENSION_CLASSPATH="@extclasspath@" +USER_CLASSPATH="." +USER_ARGS="" -MYCLASSPATH=@classpath@ -if [ "$MYCLASSPATH" == "" ] ; then +if [ "$EXTENSION_CLASSPATH" == "" ] ; then for jar in `ls $SCALA_HOME/lib/*.jar` ; do - MYCLASSPATH="$MYCLASSPATH:$jar" + EXTENSION_CLASSPATH="$EXTENSION_CLASSPATH:$jar" done - MYCLASSPATH=${MYCLASSPATH:1} + EXTENSION_CLASSPATH=${EXTENSION_CLASSPATH:1} fi -QQ_USERCLASSPATH="." -QQ_USERARGS="" -QQ_NEXT=0 +if [ "$CLASSPATH" != "" ] ; then + USER_CLASSPATH="$CLASSPATH" +fi + +QQ_CP_ARGUMENT=0 for i in $@@ ; do - if [ $QQ_NEXT -eq 1 ] ; then - QQ_USERCLASSPATH=$i - QQ_NEXT=0 + if [ "$QQ_CP_ARGUMENT" -eq 1 ] ; then + USER_CLASSPATH=$i + QQ_CP_ARGUMENT=0 else if [[ $i = "-cp" || $i = "-classpath" ]] ; then - QQ_NEXT=1 + QQ_CP_ARGUMENT=1 else - QQ_USERARGS="$QQ_USERARGS $i" - QQ_NEXT=0 + USER_ARGS="$USER_ARGS $i" + QQ_CP_ARGUMENT=0 fi fi done -## Lex suggested the user classpath comes before -## the Scala libraries, since it gets preferred. - -if [ "$QQ_USERCLASSPATH" != "." ] ; then - MYCLASSPATH="$QQ_USERCLASSPATH:$MYCLASSPATH" +MYCLASSPATH="" +if [ "$EXTENSION_CLASSPATH" == "" ] ; then + MYCLASSPATH="$USER_CLASSPATH" else - if [ "$CLASSPATH" != "" ] ; then - MYCLASSPATH="$CLASSPATH:$MYCLASSPATH" + if [ "$USER_CLASSPATH" == "" ] ; then + MYCLASSPATH="$EXTENSION_CLASSPATH" else - MYCLASSPATH=".:$MYCLASSPATH" + MYCLASSPATH="$USER_CLASSPATH:$EXTENSION_CLASSPATH" + fi +fi + +for flag in "$@@" ; do + if [ "$flag" == '-version' ] ; then + echo "Scala runtime version @version@ -- @copyright@" + ${JAVACMD:=java} -version + exit 0 fi +done + +BOOT_CLASSPATH="" +if [ -f "$SCALA_HOME/lib/scala-library.jar" ] ; then + BOOT_CLASSPATH="$SCALA_HOME/lib/scala-library.jar" fi if $cygwin; then @@ -83,17 +91,16 @@ if $cygwin; then else format=windows fi + SCALA_HOME=`cygpath --$format "$SCALA_HOME"` + USER_CLASSPATH=`cygpath --path --$format "$USER_CLASSPATH"` + BOOT_CLASSPATH=`cygpath --path --$format "$BOOT_CLASSPATH"` + EXTENSION_CLASSPATH=`cygpath --path --$format "$EXTENSION_CLASSPATH"` MYCLASSPATH=`cygpath --path --$format "$MYCLASSPATH"` fi -QQ_USERARGS="-cp $MYCLASSPATH $QQ_USERARGS" - -for flag in "$@@" ; do - if [ "$flag" == '-version' ] ; then - echo "Scala runtime version @version@ -- @copyright@" - ${JAVACMD:=java} -version - exit 0 - fi -done +QQ_BOOT_ARG="" +if [ "$BOOT_CLASSPATH" != "" ] ; then + QQ_BOOT_ARG="-Xbootclasspath/a:$BOOT_CLASSPATH" +fi -${JAVACMD:=java} @javaflags@ $QQ_USERARGS +${JAVACMD:=java} $QQ_BOOT_ARG @javaflags@ -cp "$MYCLASSPATH" -Dscala.home="$SCALA_HOME" -Dscala.class.path="$USER_CLASSPATH" -Dscala.boot.class.path="$BOOT_CLASSPATH" -Dscala.ext.path="$EXTENSION_CLASSPATH" @properties@ $USER_ARGS diff --git a/src/compiler/scala/tools/ant/templates/int-unix.tmpl b/src/compiler/scala/tools/ant/templates/int-unix.tmpl deleted file mode 100644 index 7a78d65258..0000000000 --- a/src/compiler/scala/tools/ant/templates/int-unix.tmpl +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - -############################################################################## -# @name@ @version@ -############################################################################## -# @copyright@ -# This is free software; see the distribution for copying conditions. -# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. -############################################################################## - -cygwin=false; -darwin=false; -case "`uname`" in - CYGWIN*) cygwin=true ;; - Darwin*) darwin=true ;; -esac - -SOURCE=$0; -SCRIPT=`basename "$SOURCE"`; -while [ -h "$SOURCE" ]; do - SCRIPT=`basename "$SOURCE"`; - LOOKUP=`ls -ld "$SOURCE"`; - TARGET=`expr "$LOOKUP" : '.*-> \(.*\)$'`; - if expr "${TARGET:-.}/" : '/.*/$' > /dev/null; then - SOURCE=${TARGET:-.}; - else - SOURCE=`dirname "$SOURCE"`/${TARGET:-.}; - fi; -done; -SCALA_HOME=`dirname "$SOURCE"`/..; -SCALA_HOME=`cd "$SCALA_HOME"; pwd`; - -## buraq: previous version of this script computed the MYCLASSPATH and -## then appended it to the bootclasspath. Unfortunately, this -## won't work for library code that uses reflection to obtain -## a class living on the classpath. For this reason, we have -## to merge everything in the -cp classpath. This requires -## intercepting the user's -cp, if any, or the user's $CLASSPATH, -## if set, appending our libs to it and passing the whole thing by -cp - -MYCLASSPATH=@classpath@ -if [ "$MYCLASSPATH" == "" ] ; then - for jar in `ls $SCALA_HOME/lib/*.jar` ; do - MYCLASSPATH="$MYCLASSPATH:$jar" - done - MYCLASSPATH=${MYCLASSPATH:1} -fi - -QQ_USERCLASSPATH="." -QQ_USERARGS="" -QQ_OTHER="" -QQ_NEXT=0 -for i in $@@ ; do - if [ $QQ_NEXT -eq 1 ] ; then - QQ_USERCLASSPATH=$i - QQ_NEXT=0 - else - if [[ $i = "-cp" || $i = "-classpath" ]] ; then - QQ_NEXT=1 - else - QQ_OTHER="$QQ_OTHER $i" - QQ_NEXT=0 - fi - fi -done - -## Lex suggested the user classpath comes before -## the Scala libraries, since it gets preferred. - -if [ "$QQ_USERCLASSPATH" != "." ] ; then - MYCLASSPATH="$QQ_USERCLASSPATH:$MYCLASSPATH" -else - if [ "$CLASSPATH" != "" ] ; then - MYCLASSPATH="$CLASSPATH:$MYCLASSPATH" - else - MYCLASSPATH=".:$MYCLASSPATH" - fi -fi - -if $cygwin; then - if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then - format=mixed - else - format=windows - fi - MYCLASSPATH=`cygpath --path --$format "$MYCLASSPATH"` -fi - -QQ_USERARGS="-cp $MYCLASSPATH $QQ_USERARGS" - -for flag in "$@@" ; do - if [ "$flag" == '-version' ] ; then - echo "@name@ version @version@ -- @copyright@" - exit 0 - fi -done - -${JAVACMD:=java} @javaflags@ -Dscala.home="$SCALA_HOME" -Dscala.tool.name="@name@" -Dscala.tool.version="@version@" @properties@ $QQ_USERARGS @class@ @toolflags@ $QQ_OTHER diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl index d192198bad..3777c9bf89 100644 --- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh ############################################################################## # @name@ @version@ @@ -31,51 +31,18 @@ done; SCALA_HOME=`dirname "$SOURCE"`/..; SCALA_HOME=`cd "$SCALA_HOME"; pwd`; -## buraq: previous version of this script computed the MYCLASSPATH and -## then appended it to the bootclasspath. Unfortunately, this -## won't work for library code that uses reflection to obtain -## a class living on the classpath. For this reason, we have -## to merge everything in the -cp classpath. This requires -## intercepting the user's -cp, if any, or the user's $CLASSPATH, -## if set, appending our libs to it and passing the whole thing by -cp +EXTENSION_CLASSPATH="@extclasspath@" +BOOT_CLASSPATH="@bootclasspath@" +USER_ARGS="" -MYCLASSPATH=@classpath@ -if [ "$MYCLASSPATH" == "" ] ; then +if [ "$EXTENSION_CLASSPATH" == "" ] ; then for jar in `ls $SCALA_HOME/lib/*.jar` ; do - MYCLASSPATH="$MYCLASSPATH:$jar" + EXTENSION_CLASSPATH="$EXTENSION_CLASSPATH:$jar" done - MYCLASSPATH=${MYCLASSPATH:1} + EXTENSION_CLASSPATH=${EXTENSION_CLASSPATH:1} fi -QQ_USERCLASSPATH="." -QQ_USERARGS="" -QQ_NEXT=0 -for i in $@@ ; do - if [ $QQ_NEXT -eq 1 ] ; then - QQ_USERCLASSPATH=$i - QQ_NEXT=0 - else - if [[ $i = "-cp" || $i = "-classpath" ]] ; then - QQ_NEXT=1 - else - QQ_USERARGS="$QQ_USERARGS $i" - QQ_NEXT=0 - fi - fi -done - -## Lex suggested the user classpath comes before -## the Scala libraries, since it gets preferred. - -if [ "$QQ_USERCLASSPATH" != "." ] ; then - MYCLASSPATH="$QQ_USERCLASSPATH:$MYCLASSPATH" -else - if [ "$CLASSPATH" != "" ] ; then - MYCLASSPATH="$CLASSPATH:$MYCLASSPATH" - else - MYCLASSPATH=".:$MYCLASSPATH" - fi -fi +MYCLASSPATH="$EXTENSION_CLASSPATH" if $cygwin; then if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then @@ -94,4 +61,27 @@ for flag in "$@@" ; do fi done -${JAVACMD:=java} @javaflags@ -Dscala.home="$SCALA_HOME" -Dscala.tool.name="@name@" -Dscala.tool.version="@version@" @properties@ -cp $MYCLASSPATH @class@ @toolflags@ $QQ_USERARGS +BOOT_CLASSPATH="" +if [ -f "$SCALA_HOME/lib/scala-library.jar" ] ; then + BOOT_CLASSPATH="$SCALA_HOME/lib/scala-library.jar" +fi + +if $cygwin; then + if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then + format=mixed + else + format=windows + fi + SCALA_HOME=`cygpath --$format "$SCALA_HOME"` + USER_CLASSPATH=`cygpath --path --$format "$USER_CLASSPATH"` + BOOT_CLASSPATH=`cygpath --path --$format "$BOOT_CLASSPATH"` + EXTENSION_CLASSPATH=`cygpath --path --$format "$EXTENSION_CLASSPATH"` + MYCLASSPATH=`cygpath --path --$format "$MYCLASSPATH"` +fi + +QQ_BOOT_ARG="" +if [ "$BOOT_CLASSPATH" != "" ] ; then + QQ_BOOT_ARG="-Xbootclasspath/a:$BOOT_CLASSPATH" +fi + +${JAVACMD:=java} $QQ_BOOT_ARG @javaflags@ -cp "$MYCLASSPATH" -Dscala.home="$SCALA_HOME" -Dscala.class.path="$USER_CLASSPATH" -Dscala.boot.class.path="$BOOT_CLASSPATH" -Dscala.ext.path="$EXTENSION_CLASSPATH" -Dscala.tool.name="@name@" -Dscala.tool.version="@version@" @properties@ @class@ @toolflags@ $@@ diff --git a/src/dbc/scala/dbc/DataType.scala b/src/dbc/scala/dbc/DataType.scala new file mode 100644 index 0000000000..f9b12bc431 --- /dev/null +++ b/src/dbc/scala/dbc/DataType.scala @@ -0,0 +1,70 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +/** An ISO-9075:2003 (SQL) data type. Mappings between SQL types and + * database specific types should be provided by the database driver. + */ +abstract class DataType { + + /** Tests whether this datatype is equivalent to another. Usually, two + * types are defined as equivalent if they are equal. Two types can be + * equivalent without being equal if values of those types will be + * encoded in the same native Scala type. + */ + def isEquivalent(datatype: DataType): Boolean; + + /** Tests whether this datatype is equivalent or a subtype of another + * datatype. Type A is said to be subtype of type + * B if any value of type A can be + * represented as a value of type B. + */ + def isSubtypeOf(datatype: DataType): Boolean; + + /** The native Scala type in which values of this SQL type will be + * encoded. + */ + type NativeType <: Any; + + /** The native Scala type in which values of this SQL type will be + * encoded. This must point to the same type as NativeType. + */ + def nativeTypeId: DataType.Id; + + /** Whether the value can take the null value, None when this property is + * unknown. + */ + def nullable: Option[Boolean] = None; + + /** The SQL name of the type */ + def sqlString: String = "UNDEFINED DATA TYPE" + +} + +object DataType { + + type Id = Int; + + val OBJECT : Id = 10; + val BOOLEAN : Id = 20; + val BYTE : Id = 30; + val SHORT : Id = 31; + val INT : Id = 32; + val LONG : Id = 33; + val BIG_INTEGER: Id = 34; + val BIG_DECIMAL: Id = 35; + val FLOAT : Id = 40; + val DOUBLE : Id = 41; + val STRING : Id = 50; + +} diff --git a/src/dbc/scala/dbc/Database.scala b/src/dbc/scala/dbc/Database.scala new file mode 100644 index 0000000000..3dd27c8481 --- /dev/null +++ b/src/dbc/scala/dbc/Database.scala @@ -0,0 +1,189 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +import java.sql._; + +/** A link to a database. The Database abstract class must + * be specialised for every different DBMS. + * @author Gilles Dubochet + **/ +case class Database(dbms: Vendor) { + + class Closed extends Exception {} + + /** A lock used for operations that need to be atomic for this database + * instance. */ + private val lock: scala.concurrent.Lock = new scala.concurrent.Lock(); + + /** The vendor of the DBMS that contains this database. */ + private val vendor: Vendor = dbms; + + /** The Database connections available to use. */ + private var availableConnections: List[Connection] = Nil; + + /** The connections that are currently in use. */ + private var usedConnections: List[Connection] = Nil; + + /** Whether the database no longer accepts new connections. */ + private var closing: Boolean = false; + + /** Retrieves a connection from the available connection pool or creates + * a new one. + * + * @returns A connection that can be used to access the database. + */ + private def getConnection: Connection = { + if (closing) { + throw new Closed; + } else { + availableConnections match { + case Nil => { + lock.acquire; + val connection = vendor.getConnection; + usedConnections = connection :: usedConnections; + lock.release; + connection + } + case connection :: cs => { + lock.acquire; + availableConnections = cs; + usedConnections = connection :: usedConnections; + lock.release; + connection; + } + } + } + } + + /** Closes a connection to this database. A closed connection might + * also return to the available connection pool if the latter is depleted. + * + * @param connection The connection that should be closed. + */ + private def closeConnection(connection: Connection): Unit = { + if (closing) { + connection.close(); + } else { + lock.acquire; + usedConnections = usedConnections.remove(e => (e.equals(connection))); + if (availableConnections.length < vendor.retainedConnections) + availableConnections = connection :: availableConnections + else + connection.close(); + lock.release; + } + } + + /** .. + */ + def close: Unit = { + closing = true; + for (val conn <- availableConnections) conn.close(); + } + + /** Executes a statement that returns a relation on this database. + * + * @param relationStatement The statement to execute. + * @return The relation returned by the database for this statement. + */ + def executeStatement(relationStatement: statement.Relation): result.Relation = + executeStatement(relationStatement, false); + + /** Executes a statement that returns a relation on this database. + * + * @param relationStatement The statement to execute. + * @param debug Whether debugging information should be printed on the console. + * @return The relation returned by the database for this statement. + */ + def executeStatement(relationStatement: statement.Relation, + debug: Boolean): result.Relation = + new scala.dbc.result.Relation { + val statement = relationStatement; + if (debug) Console.println("## " + statement.sqlString); + private val connection = getConnection; + val sqlResult = connection.createStatement().executeQuery(statement.sqlString); + closeConnection(connection); + statement.typeCheck(this); + } + + /** Executes a statement that updates the state of the database. + * + * @param statusStatement The statement to execute. + * @return The status of the database after the statement has been executed. + */ + def executeStatement(statusStatement: statement.Status): result.Status[Unit] = + executeStatement(statusStatement, false); + + /** Executes a statement that updates the state of the database. + * + * @param statusStatement The statement to execute. + * @param debug Whether debugging information should be printed on the console. + * @return The status of the database after the statement has been executed. + */ + def executeStatement(statusStatement: statement.Status, + debug: Boolean): result.Status[Unit] = + new scala.dbc.result.Status[Unit] { + val statement = statusStatement; + if (debug) Console.println("## " + statement.sqlString); + def result = (); + private val connection = getConnection; + val jdbcStatement: java.sql.Statement = connection.createStatement(); + jdbcStatement.execute(statement.sqlString); + val touchedCount = Some(jdbcStatement.getUpdateCount()); + closeConnection(connection); + } + + /** Executes a list of statements or other operations inside a transaction. + * Only statements are protected in a transaction, other Scala code is not. + * + * @param transactionStatement The transaction to execute as a closure. + * @return The status of the database after the transaction has been executed. + */ + def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType]): result.Status[ResultType] = + executeStatement(transactionStatement, false); + + /** Executes a list of statements or other operations inside a transaction. + * Only statements are protected in a transaction, other Scala code is not. + * + * @param transactionStatement The transaction to execute as a closure. + * @param debug Whether debugging information should be printed on the console. + * @return The status of the database after the transaction has been executed. + */ + def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType], debug: Boolean): result.Status[ResultType] = { + new scala.dbc.result.Status[ResultType] { + val touchedCount = None; + val statement = transactionStatement; + private val connection = getConnection; + connection.setAutoCommit(false); + val jdbcStatement: java.sql.Statement = connection.createStatement(); + if (debug) Console.println("## " + transactionStatement.sqlStartString); + jdbcStatement.execute(transactionStatement.sqlStartString); + val result: ResultType = try { + val buffer = transactionStatement.transactionBody(Database.this); + if (debug) Console.println("## " + transactionStatement.sqlCommitString); + jdbcStatement.execute(transactionStatement.sqlCommitString); + buffer + } catch { + case e: Throwable => { + if (debug) Console.println("## " + transactionStatement.sqlAbortString); + jdbcStatement.execute(transactionStatement.sqlAbortString); + throw e; + } + } + connection.setAutoCommit(true); + closeConnection(connection); + } + } + +} diff --git a/src/dbc/scala/dbc/Syntax.scala b/src/dbc/scala/dbc/Syntax.scala new file mode 100644 index 0000000000..d8ed87740a --- /dev/null +++ b/src/dbc/scala/dbc/Syntax.scala @@ -0,0 +1,48 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +import java.math.{BigDecimal, BigInteger}; + + +/** This class .. + * + */ +object Syntax { + + import syntax.DataTypeUtil; + + /* Data types */ + def boolean = DataTypeUtil.boolean; + def tinyint = DataTypeUtil.tinyint; + def smallint = DataTypeUtil.smallint; + def integer = DataTypeUtil.integer; + def bigint = DataTypeUtil.bigint; + def real = DataTypeUtil.real; + + def numeric(precision: Int) = DataTypeUtil.numeric(precision); + def numeric(precision: Int, scale: Int) = DataTypeUtil.numeric(precision, scale); + + def doublePrecision = DataTypeUtil.doublePrecision; + def character(length: Int) = DataTypeUtil.character(length); + def characterVarying(length: Int) = DataTypeUtil.characterVarying(length); + def characterLargeObject = DataTypeUtil.characterLargeObject; + + /* Statements */ + //def select + + /* Other stuff */ + def database (server: String, username: String, password: String): dbc.Database = + syntax.Database.database(server, username, password); + +} diff --git a/src/dbc/scala/dbc/Utilities.scala b/src/dbc/scala/dbc/Utilities.scala new file mode 100644 index 0000000000..c2691143f3 --- /dev/null +++ b/src/dbc/scala/dbc/Utilities.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +/** An object offering transformation methods (views) on various values. + * This object's members must be visible in an expression to use value + * auto-conversion. + */ +object Utilities { + + implicit def constantToValue (obj: statement.expression.Constant): Value = + obj.constantValue; + + implicit def valueToConstant (obj: Value): statement.expression.Constant = + new statement.expression.Constant { + val constantValue = obj; + } + +} diff --git a/src/dbc/scala/dbc/Value.scala b/src/dbc/scala/dbc/Value.scala new file mode 100644 index 0000000000..13a7678928 --- /dev/null +++ b/src/dbc/scala/dbc/Value.scala @@ -0,0 +1,28 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +/** A SQL-99 value of any type. */ +abstract class Value { + + /** The SQL-99 type of the value. */ + val dataType: DataType; + + type NativeType = dataType.type#NativeType; + + val nativeValue: NativeType; + + /** A SQL-99 compliant string representation of the value. */ + def sqlString: String; + +} diff --git a/src/dbc/scala/dbc/Vendor.scala b/src/dbc/scala/dbc/Vendor.scala new file mode 100644 index 0000000000..b9b3595d95 --- /dev/null +++ b/src/dbc/scala/dbc/Vendor.scala @@ -0,0 +1,42 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc; + + +import java.sql.{Connection, Driver}; + + +/** This class .. + */ +abstract class Vendor { + + def nativeDriverClass: Class; + def uri: java.net.URI; + def user: String; + def pass: String; + def nativeProperties: java.util.Properties = { + val properties = new java.util.Properties(); + properties.setProperty("user", user); + properties.setProperty("password", pass); + properties + } + + def retainedConnections: Int; + + def getConnection: Connection = { + val driver = nativeDriverClass.newInstance().asInstanceOf[Driver]; + driver.connect(uri.toString(),nativeProperties) + } + + def urlProtocolString: String; + +} diff --git a/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala b/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala new file mode 100644 index 0000000000..8943f46364 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala @@ -0,0 +1,57 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A type category for all SQL types that store varying-precision + * numbers. + */ +abstract class ApproximateNumeric[Type] ( + override val nativeTypeId: DataType.Id +) extends datatype.Numeric[Type](nativeTypeId) { + + def isEquivalent(datatype: DataType) = datatype match { + case dt: ApproximateNumeric[Type] => + (nativeTypeId == dt.nativeTypeId && + precisionRadix == dt.precisionRadix && + precision == dt.precision && + signed == dt.signed) + case _ => + false + } + + def isSubtypeOf (datatype:DataType) = datatype match { + case dt:ApproximateNumeric[Type] => + (nativeTypeId == dt.nativeTypeId && + precisionRadix == dt.precisionRadix && + precision <= dt.precision && + signed == dt.signed) + case _ => + false + } + + /** A SQL-99 compliant string representation of the type. + *

Compatibility notice

This method assumes that a real + * uses 32 bits and a double 64. This is not defined in the + * standard but is usually the case. + */ + override def sqlString: java.lang.String = Tuple2(precisionRadix,precision) match { + case Tuple2(2,64) => "REAL" + case Tuple2(2,128) => "DOUBLE PRECISION" + case Tuple2(2,p) => + throw exception.UnsupportedFeature("SQL-99 does not support an approximate numeric type with a binary defined precision other than 16, 32 and 64 bits"); + case Tuple2(10,p) => "FLOAT (" + p.toString() + ")" + case Tuple2(pr,_) => + throw exception.UnsupportedFeature("SQL-99 does not support the precision of an approximate numeric type to be defined in a radix other than 2 or 10"); + } + +} diff --git a/src/dbc/scala/dbc/datatype/Boolean.scala b/src/dbc/scala/dbc/datatype/Boolean.scala new file mode 100644 index 0000000000..c4a880885e --- /dev/null +++ b/src/dbc/scala/dbc/datatype/Boolean.scala @@ -0,0 +1,31 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** The SQL type for a truth value. */ +class Boolean extends DataType { + + def isEquivalent (datatype:DataType) = datatype match { + case dt:Boolean => true + case _ => false + } + + def isSubtypeOf (datatype:DataType) = isEquivalent(datatype); + + type NativeType = scala.Boolean; + val nativeTypeId = DataType.BOOLEAN; + + /** A SQL-99 compliant string representation of the type. */ + override def sqlString: java.lang.String = "BOOLEAN"; + +} diff --git a/src/dbc/scala/dbc/datatype/Character.scala b/src/dbc/scala/dbc/datatype/Character.scala new file mode 100644 index 0000000000..02b4b182e0 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/Character.scala @@ -0,0 +1,40 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A SQL type for a string of characters of arbitrary length with + * arbitrary character set. + */ +abstract class Character extends CharacterString { + + def isEquivalent(datatype: DataType) = datatype match { + case dt: Character => + length == dt.length && encoding == dt.encoding + case _ => + false + } + + def isSubtypeOf(datatype: DataType) = datatype match { + case dt: Character => + length >= dt.length && encoding == dt.encoding + case _ => + false + } + + /** The length of the string defined in characters. */ + def length: Int; + + /** A SQL-99 compliant string representation of the type. */ + override def sqlString: java.lang.String = "CHARACTER (" + length.toString() + ")"; + +} diff --git a/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala b/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala new file mode 100644 index 0000000000..c84bb4bae9 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala @@ -0,0 +1,31 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A SQL type for an unbounded length string of characters with arbitrary + * character set. */ +class CharacterLargeObject extends CharacterString { + + def isEquivalent (datatype:DataType) = datatype match { + case dt:CharacterLargeObject => { + encoding == dt.encoding + } + case _ => false + } + + def isSubtypeOf (datatype:DataType) = isEquivalent(datatype); + + /** A SQL-99 compliant string representation of the type. */ + override def sqlString: java.lang.String = "CHARACTER LARGE OBJECT"; + +} diff --git a/src/dbc/scala/dbc/datatype/CharacterString.scala b/src/dbc/scala/dbc/datatype/CharacterString.scala new file mode 100644 index 0000000000..1f250475b3 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/CharacterString.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A type category for all SQL types that store strings of characters. */ +abstract class CharacterString extends String { + + type NativeType = java.lang.String; + val nativeTypeId = DataType.STRING; + + /** The name of the character set in which the string is encoded. */ + def encoding: Option[java.lang.String] = None; + +} diff --git a/src/dbc/scala/dbc/datatype/CharacterVarying.scala b/src/dbc/scala/dbc/datatype/CharacterVarying.scala new file mode 100644 index 0000000000..e0cdbc819b --- /dev/null +++ b/src/dbc/scala/dbc/datatype/CharacterVarying.scala @@ -0,0 +1,41 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A SQL type for a varying length string of characters with arbitrary + * maximal length and arbitrary character set. + */ +abstract class CharacterVarying extends CharacterString { + + def isEquivalent(datatype: DataType) = datatype match { + case dt: CharacterVarying => + length == dt.length && encoding == dt.encoding + case _ => + false + } + + def isSubtypeOf(datatype: DataType) = datatype match { + case dt: CharacterVarying => + length >= dt.length && encoding == dt.encoding + case _ => + false + } + + /** The maximal length of the string defined in characters. */ + def length: Int; + + /** A SQL-99 compliant string representation of the type. */ + override def sqlString: java.lang.String = + "CHARACTER VARYING (" + length.toString() + ")"; + +} diff --git a/src/dbc/scala/dbc/datatype/ExactNumeric.scala b/src/dbc/scala/dbc/datatype/ExactNumeric.scala new file mode 100644 index 0000000000..331cf866e1 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/ExactNumeric.scala @@ -0,0 +1,65 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A type category for all SQL types that store constant-precision + * numbers. + */ +abstract class ExactNumeric[Type]( + override val nativeTypeId: DataType.Id +) extends datatype.Numeric[Type](nativeTypeId) { + + def isEquivalent(datatype: DataType) = datatype match { + case dt: ExactNumeric[Type] => + (nativeTypeId == dt.nativeTypeId && + precisionRadix == dt.precisionRadix && + precision == dt.precision && + scale == dt.scale && + signed == dt.signed) + case _ => + false + } + + def isSubtypeOf(datatype: DataType) = datatype match { + case dt: ExactNumeric[Type] => + (nativeTypeId == dt.nativeTypeId && + precisionRadix == dt.precisionRadix && + precision <= dt.precision && + scale <= dt.scale && + signed == dt.signed) + case _ => + false + } + + /** The number of digits used after the decimal point. */ + def scale: Int; + + /** A SQL-99 compliant string representation of the type. + *

Compatibility notice

This method assumes that an integer + * uses 32 bits, a small 16 and a big 64. This is not defined in the + * standard but is usually the case. + */ + override def sqlString: java.lang.String = Tuple3(precisionRadix,precision,scale) match { + case Tuple3(2,16,0) => "SMALLINT" + case Tuple3(2,32,0) => "INTEGER" + case Tuple3(2,64,0) => "BIGINT" + case Tuple3(2,java.lang.Integer.MAX_VALUE,0) => "BIGINT" + case Tuple3(2,p,s) => + throw exception.UnsupportedFeature("SQL-99 does not support an exact numeric type with a binary defined precision other than 16, 32 and 64 bits"); + case Tuple3(10,p,0) => "NUMERIC (" + p.toString() + ")" + case Tuple3(10,p,s) => "NUMERIC (" + p.toString() + ", " + s.toString() + ")" + case Tuple3(pr,_,_) => + throw exception.UnsupportedFeature("SQL-99 does not support the precision of an exact numeric type to be defined in a radix other than 2 or 10"); + } + +} diff --git a/src/dbc/scala/dbc/datatype/Factory.scala b/src/dbc/scala/dbc/datatype/Factory.scala new file mode 100644 index 0000000000..a4a9672184 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/Factory.scala @@ -0,0 +1,250 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +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.") + } + } +} diff --git a/src/dbc/scala/dbc/datatype/Numeric.scala b/src/dbc/scala/dbc/datatype/Numeric.scala new file mode 100644 index 0000000000..d086ecdfff --- /dev/null +++ b/src/dbc/scala/dbc/datatype/Numeric.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A type category for all SQL types that store numbers. */ +abstract class Numeric[Type](_nativeTypeId: DataType.Id) extends DataType { + + type NativeType = Type; + val nativeTypeId = _nativeTypeId; + + /** The radix in which the precision (and scale when appliable) is defined. + * ISO-9075 only allows 2 and 10 for this value. + */ + def precisionRadix: Int; + + /** The number of significant digits for that number. */ + def precision: Int; + + /** Whether the number is signed or not. */ + def signed: scala.Boolean; + +} diff --git a/src/dbc/scala/dbc/datatype/String.scala b/src/dbc/scala/dbc/datatype/String.scala new file mode 100644 index 0000000000..878bea7061 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/String.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** A type category for all SQL types that store strings of elements. + */ +abstract class String extends DataType { + + /** The maximal possible length of the string defined in characters. + * This is an implementation-specific value. + */ + def maxLength: Option[Int] = None; + +} diff --git a/src/dbc/scala/dbc/datatype/Unknown.scala b/src/dbc/scala/dbc/datatype/Unknown.scala new file mode 100644 index 0000000000..4ab1db59f8 --- /dev/null +++ b/src/dbc/scala/dbc/datatype/Unknown.scala @@ -0,0 +1,34 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.datatype; + + +/** The SQL type for a truth value. */ +class Unknown extends DataType { + + def isEquivalent(datatype: DataType) = datatype match { + case dt: Unknown => + nativeTypeId == dt.nativeTypeId + case _ => + false + } + + def isSubtypeOf(datatype: DataType) = true; + + type NativeType = Object; + val nativeTypeId = DataType.OBJECT; + + /** A SQL-99 compliant string representation of the type. */ + override def sqlString: java.lang.String = + error("The 'UNKNOWN' data type cannot be represented."); + +} diff --git a/src/dbc/scala/dbc/exception/IncompatibleSchema.scala b/src/dbc/scala/dbc/exception/IncompatibleSchema.scala new file mode 100644 index 0000000000..bb566ff6f2 --- /dev/null +++ b/src/dbc/scala/dbc/exception/IncompatibleSchema.scala @@ -0,0 +1,19 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.exception; + + +/** A type category for all SQL types that store constant-precision numbers. */ +case class IncompatibleSchema ( + expectedSchema: List[DataType], + foundSchema: List[DataType] +) extends Exception; diff --git a/src/dbc/scala/dbc/exception/UnsupportedFeature.scala b/src/dbc/scala/dbc/exception/UnsupportedFeature.scala new file mode 100644 index 0000000000..073bd8ab32 --- /dev/null +++ b/src/dbc/scala/dbc/exception/UnsupportedFeature.scala @@ -0,0 +1,16 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.exception; + + +/** A type category for all SQL types that store constant-precision numbers. */ +case class UnsupportedFeature (msg: String) extends Exception; diff --git a/src/dbc/scala/dbc/result/Field.scala b/src/dbc/scala/dbc/result/Field.scala new file mode 100644 index 0000000000..75c9898076 --- /dev/null +++ b/src/dbc/scala/dbc/result/Field.scala @@ -0,0 +1,63 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.result; + + +import scala.dbc.datatype._; +import scala.dbc.value._; + +/** An ISO-9075:2003 (SQL) table field. */ +abstract class Field { + + /** The content (value) of the field. The type of this value is undefined, + * transformation into a useful type will be done by an automatic view + * function defined in the field object. */ + def content: Value; + + final def value[Type <: Value]: Type = + content.asInstanceOf[Type]; + + final def exactNumericValue[NativeType] = + content.asInstanceOf[dbc.value.ExactNumeric[NativeType]]; + + final def approximateNumericValue[NativeType] = + content.asInstanceOf[dbc.value.ApproximateNumeric[NativeType]]; + + final def booleanValue = + content.asInstanceOf[dbc.value.Boolean]; + + final def characterValue = + content.asInstanceOf[dbc.value.Character]; + + final def characterLargeObjectValue = + content.asInstanceOf[dbc.value.CharacterLargeObject]; + + final def characterVaryingValue = + content.asInstanceOf[dbc.value.CharacterVarying]; + + final def unknownValue = + content.asInstanceOf[dbc.value.Unknown]; + + /** The tuple that contains this field. */ + def originatingTuple: Tuple; + + /** The field metadata attached to this field. */ + def metadata: FieldMetadata; + +} + +object Field { + + implicit def fieldToValue (field:Field): Value = field.content; + + +} diff --git a/src/dbc/scala/dbc/result/FieldMetadata.scala b/src/dbc/scala/dbc/result/FieldMetadata.scala new file mode 100644 index 0000000000..a3117a262c --- /dev/null +++ b/src/dbc/scala/dbc/result/FieldMetadata.scala @@ -0,0 +1,36 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.result; + + +/** Informations attached to a field about its content and its relationship to the originating database. */ +abstract class FieldMetadata { + + /** The name of the field. */ + def name: String; + + /** The index of the field in the tuple. */ + def index: Int; + + /** The expected type of the field. This information is used for automatic transformation of the field value into a usable type. */ + def datatype: DataType; + + /** The name of the catalog in the database from which the field originates */ + def catalog: String; + + /** The name of the schema in the database from which the field originates */ + def schema: String; + + /** The name of the table in the database from which the field originates */ + def table: String; + +} diff --git a/src/dbc/scala/dbc/result/Relation.scala b/src/dbc/scala/dbc/result/Relation.scala new file mode 100644 index 0000000000..218f8ff825 --- /dev/null +++ b/src/dbc/scala/dbc/result/Relation.scala @@ -0,0 +1,72 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.result; + + +/** An ISO-9075:2003 (SQL) table. This is equivalent to a relation in the + * relational model. */ +abstract class Relation extends Object with Iterable[Tuple] { + + /** The statement that generated this relation. */ + def statement: scala.dbc.statement.Relation; + + /** A JDBC result containing this relation. */ + protected def sqlResult: java.sql.ResultSet; + + /** A JDBC metadata object attached to the relation. */ + protected def sqlMetadata: java.sql.ResultSetMetaData = sqlResult.getMetaData(); + + /** Metadata about all fields in a tuple of the relation. */ + def metadata: List[FieldMetadata] = + for (val count <- List.range(1, sqlMetadata.getColumnCount()+1)) yield + new FieldMetadata { + val name: String = sqlMetadata.getColumnName(count); + val index: Int = count; + val datatype: DataType = dbc.datatype.Factory.create(sqlMetadata,count); + val catalog: String = sqlMetadata.getCatalogName(count); + val schema: String = sqlMetadata.getSchemaName(count); + val table: String = sqlMetadata.getTableName(count); + } + + /** Metadata about the field at the given index. If there is no such + * field None is returned instead. */ + def metadataFor (index:Int): Option[FieldMetadata] = + try {Some(metadata(index))} catch {case e => None} + + /** Metadata about the field with the given column name. If there is no + * such field, None is returned instead. */ + def metadataFor (name:String): Option[FieldMetadata] = + metadata.find(f=>(f.name==name)); + + /** An iterator on the tuples of the relation. + *

Caution

A Relation only has one single iterator, due to limitations + * in DBMS. This means that if this method is called multiple times, all returned + * iterators will share the same state. */ + def elements: Iterator[Tuple] = new Iterator[Tuple] { + protected val result: java.sql.ResultSet = Relation.this.sqlResult; + def hasNext: Boolean = !(result.isLast()); + def next: Tuple = { + if (result.next()) { + new Tuple { + val me = this; + val originatingRelation = Relation.this; + val fields: List[Field] = for (val fieldMetadata <- metadata) yield + new Field { + val metadata = fieldMetadata; + val content = dbc.value.Factory.create(result,metadata.index,metadata.datatype); + val originatingTuple = me; + } + } + } else error("next on empty iterator") + } + } +} diff --git a/src/dbc/scala/dbc/result/Status.scala b/src/dbc/scala/dbc/result/Status.scala new file mode 100644 index 0000000000..c8a2370819 --- /dev/null +++ b/src/dbc/scala/dbc/result/Status.scala @@ -0,0 +1,28 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.result; + + +import scala.dbc.datatype._; + +/** An object containing the status of a query */ +abstract class Status[ResultType] { + + /** The statement that generated this status result. */ + def statement: scala.dbc.statement.Statement; + + /** The number of elements modified or added by this statement. */ + def touchedCount: Option[Int]; + + def result: ResultType; + +} diff --git a/src/dbc/scala/dbc/result/Tuple.scala b/src/dbc/scala/dbc/result/Tuple.scala new file mode 100644 index 0000000000..6ed8955951 --- /dev/null +++ b/src/dbc/scala/dbc/result/Tuple.scala @@ -0,0 +1,42 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.result; + + +/** An ISO-9075:2003 (SQL) table row. This is equivalent to a tuple in the relational model. */ +abstract class Tuple { + + /** All the fields contained in the tuple. */ + def fields: List[Field]; + + /** The relation that contains the tuple. */ + def originatingRelation: Relation; + + /** The field at the given index. If there is no such field (that is the index is out of bounds), None is returned instead. */ + def apply (index:Int): Field = + try { + fields(index) + } catch { + case e => + throw new java.lang.IndexOutOfBoundsException("Field at index "+index+" does not exist in relation"); + } + + /** The field with the given column name. If there is no such field, None is returned instead. */ + def apply (name:String): Field = { + def findField (fields: List[Field], name:String): Field = fields match { + case Nil => throw new java.lang.IndexOutOfBoundsException("Field '"+name+"' does not exist in relation") + case field :: _ if (field.metadata.name == name) => field + case field :: fields => findField (fields, name) + } + findField (fields, name); + } +} diff --git a/src/dbc/scala/dbc/statement/AccessMode.scala b/src/dbc/scala/dbc/statement/AccessMode.scala new file mode 100644 index 0000000000..16f778b35e --- /dev/null +++ b/src/dbc/scala/dbc/statement/AccessMode.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +abstract class AccessMode { + def sqlString: String; +} + +object AccessMode { + case object ReadOnly extends AccessMode { + def sqlString = "READ ONLY"; + } + case object ReadWrite extends AccessMode { + def sqlString = "READ WRITE" + } +} diff --git a/src/dbc/scala/dbc/statement/DerivedColumn.scala b/src/dbc/scala/dbc/statement/DerivedColumn.scala new file mode 100644 index 0000000000..653ce75698 --- /dev/null +++ b/src/dbc/scala/dbc/statement/DerivedColumn.scala @@ -0,0 +1,36 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +abstract class DerivedColumn { + + /** The value for the column. This value can be of any type but must be + * calculated from fields that appear in a relation that takes part + * in the query. */ + def valueExpression: Expression; + + /** A new name for this field. This name must be unique for the query in + * which the column takes part. */ + def asClause: Option[String]; + + /** A SQL-99 compliant string representation of the derived column + * sub-statement. This only has a meaning inside a select statement. */ + def sqlString: String = ( + valueExpression.sqlInnerString + + (asClause match { + case None => "" + case Some(ac) => " AS " + ac + }) + ); + +} diff --git a/src/dbc/scala/dbc/statement/Expression.scala b/src/dbc/scala/dbc/statement/Expression.scala new file mode 100644 index 0000000000..6243564311 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Expression.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** An expression that calculates some value from fields. */ +abstract class Expression extends Relation { + + def fieldTypes: List[DataType] = Nil; + + /** A SQL-99 compliant string representation of the expression. */ + def sqlString: String = { + "SELECT " + sqlInnerString + } + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String; + +} diff --git a/src/dbc/scala/dbc/statement/Insert.scala b/src/dbc/scala/dbc/statement/Insert.scala new file mode 100644 index 0000000000..19d236d2fb --- /dev/null +++ b/src/dbc/scala/dbc/statement/Insert.scala @@ -0,0 +1,36 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +import scala.dbc.statement.expression._; + +/** An insertion of values into a table. */ +case class Insert ( + insertionTarget: String, + insertionData: InsertionData +) extends Status { + + /** A SQL-99 compliant string representation of the select statement. */ + def sqlString: String = ( + "INSERT INTO " + + insertionTarget + + " " + insertionData.sqlString + ); + + /** The name of the table where the data should be added. */ + //def insertionTarget: String; + + /** The data that will be added tot he table. */ + //def insertionData: InsertionData; + +} diff --git a/src/dbc/scala/dbc/statement/InsertionData.scala b/src/dbc/scala/dbc/statement/InsertionData.scala new file mode 100644 index 0000000000..c36dde0fb7 --- /dev/null +++ b/src/dbc/scala/dbc/statement/InsertionData.scala @@ -0,0 +1,41 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +import scala.dbc.statement.expression._; + +/** Data to be inserted into a table in an Insert. */ +abstract class InsertionData { + def sqlString: String; +} + +object InsertionData { + /** Insertion of data resulting from a query on the database. */ + case class Subquery (query:Relation) extends InsertionData { + def sqlString = query.sqlString; + } + /** Insertion of data as explicitly defined values. */ + case class Constructor ( + columnNames:Option[List[String]], + columnValues:List[Expression] + ) extends InsertionData { + def sqlString = ( + (columnNames match { + case None => "" + case Some(cn) => cn.mkString(" (",", ",")") + }) + + " VALUES" + + columnValues.map(e=>e.sqlInnerString).mkString(" (",", ",")") + ) + } +} diff --git a/src/dbc/scala/dbc/statement/IsolationLevel.scala b/src/dbc/scala/dbc/statement/IsolationLevel.scala new file mode 100644 index 0000000000..4d1d2ef2de --- /dev/null +++ b/src/dbc/scala/dbc/statement/IsolationLevel.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +abstract class IsolationLevel { + def sqlString: String; +} + +object IsolationLevel { + case object ReadUncommitted extends IsolationLevel { + def sqlString = "ISOLATION LEVEL READ UNCOMMITTED" + } + case object ReadCommitted extends IsolationLevel { + def sqlString = "ISOLATION LEVEL READ COMMITTED" + } + case object RepeatableRead extends IsolationLevel { + def sqlString = "ISOLATION LEVEL REPEATABLE READ" + } + case object Serializable extends IsolationLevel { + def sqlString = "ISOLATION LEVEL SERIALIZABLE" + } +} diff --git a/src/dbc/scala/dbc/statement/JoinType.scala b/src/dbc/scala/dbc/statement/JoinType.scala new file mode 100644 index 0000000000..77befa5607 --- /dev/null +++ b/src/dbc/scala/dbc/statement/JoinType.scala @@ -0,0 +1,49 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A join behaviour in a Jointure. */ +abstract class JoinType { + /** A SQL-99 string representation of the join behaviour. */ + def sqlString: String; +} + +object JoinType { + /** A join behaviour where a joined tuple is created only when a + * corresponding tuple exists in both original relations. */ + case object Inner extends JoinType { + val sqlString = "INNER JOIN" + } + /** A join behaviour family where a joined tuple is created even when a + * tuple has no corresponding tuple in the other relation. The fields + * populated by values of the other tuple will receive the NULL value. + */ + abstract class Outer extends JoinType; + object Outer { + /** An outer join behaviour where there will be at least on tuple for + * every tuple in the left relation. */ + case object Left extends Outer { + val sqlString = "LEFT OUTER JOIN" + } + /** An outer join behaviour where there will be at least on tuple for + * every tuple in the right relation. */ + case object Right extends Outer { + val sqlString = "RIGHT OUTER JOIN" + } + /** An outer join behaviour where there will be at least on tuple for + * every tuple in both right and left relations. */ + case object Full extends Outer { + val sqlString = "FULL OUTER JOIN" + } + } +} diff --git a/src/dbc/scala/dbc/statement/Jointure.scala b/src/dbc/scala/dbc/statement/Jointure.scala new file mode 100644 index 0000000000..471626ab05 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Jointure.scala @@ -0,0 +1,47 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A jointure between two relations. */ +abstract class Jointure extends Relation { + + /** The relation on the left part of the join. */ + def leftRelation: Relation; + + /** The relation on the right part of the join. */ + def rightRelation: Relation; + + /** The type of the jointure. */ + def joinType: JoinType; + + /** The condition on which the jointure needs be done. */ + def joinCondition: Option[Expression]; + + /** A SQL-99 compliant string representation of the relation statement. */ + def sqlString: String = { + "SELECT * FROM " + sqlInnerString + } + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside a query. */ + def sqlInnerString: String = ( + leftRelation.sqlInnerString + " " + + joinType.sqlString + " " + + rightRelation.sqlInnerString + + (joinCondition match { + case Some(jc) => jc.sqlString + case None => "" + }) + ) + +} diff --git a/src/dbc/scala/dbc/statement/Relation.scala b/src/dbc/scala/dbc/statement/Relation.scala new file mode 100644 index 0000000000..d6e86b39a5 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Relation.scala @@ -0,0 +1,55 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A statement that returns a relation. */ +abstract class Relation extends Statement { + + def isCompatibleType: (DataType,DataType)=>Boolean = + ((dt,wdt)=>dt.isSubtypeOf(wdt)); + + def typeCheck (relation: result.Relation): Unit = { + val sameType: Boolean = ( + relation.metadata.length == fieldTypes.length && + (relation.metadata.zip(fieldTypes).forall({case Pair(field,expectedType) => + isCompatibleType(field.datatype, expectedType)})) + ); + if (!sameType) + throw new exception.IncompatibleSchema(fieldTypes,relation.metadata.map(field=>field.datatype)); + } + + def fieldTypes: List[DataType]; + + def sqlTypeString: String = + if (fieldTypes.isEmpty) + "UNTYPED" + else + fieldTypes.map(dt=>dt.sqlString).mkString("RELATION (",", ",")"); + + /** A SQL-99 compliant string representation of the statement. */ + def sqlString: String; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String; + + /** Executes the statement on the given database. */ + def execute (database: scala.dbc.Database): scala.dbc.result.Relation = { + database.executeStatement(this); + } + + def execute (database:scala.dbc.Database, debug:Boolean): scala.dbc.result.Relation = { + database.executeStatement(this,debug); + } + +} diff --git a/src/dbc/scala/dbc/statement/Select.scala b/src/dbc/scala/dbc/statement/Select.scala new file mode 100644 index 0000000000..4da6b9e571 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Select.scala @@ -0,0 +1,95 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A statement that when executed on a database will return a relation. + * The returned relation will be a subset of a table in the database or + * a jointure between such subsets. */ +abstract class Select extends Relation { + + /** Defines if duplicated tuples should be removed from the returned + * relation.

Compatibility notice

Some DBMS (PostgreSQL) allow + * uniqueness constrains on an arbitrary field instead of the entire + * tuple. */ + def setQuantifier: Option[SetQuantifier]; + + /** Defines the output fields that a tuple in the returned relation will + * contain, and their content with respect to the tables in the + * database. If the fields are not specified (that is the list is + * empty), all possible input fields will be returned.

Compatibility + * notice

SQL's qualified asterisk select sublist is not + * available. */ + def selectList: List[DerivedColumn]; + + /** Defines the relations from which the query will obtain its data.*/ + def fromClause: List[Relation]; + + /** Defines condition that must be true in the returned relation's tuples. + * This value expression must return a boolean or boolean-compatible + * value. This condition is applied before any GROUP BY clause. */ + def whereClause: Option[Expression]; + + /** Defines the grouping of the returned relation's tuples. One tuple is + * returned for every group. The value of selectList must + * use aggregate functions for calculation. */ + def groupByClause: Option[List[Expression]]; + + /** Defines conditions that must be true in the returned relation's tuples. + * The value expression must return a boolean can only refer to fields + * that are grouped or to any field from inside an aggregate function. */ + def havingClause: Option[Expression]; + + /* def windowClause: Option[_]; */ + + /** A SQL-99 compliant string representation of the select statement. */ + def sqlString: String = ( + "SELECT" + + (setQuantifier match { + case None => "" + case Some(sq) => " " + sq.sqlString + }) + + (selectList match { + case Nil => " *" + case _ => (" " + selectList.tail.foldLeft(selectList.head.sqlString) + ((name:String, dc:DerivedColumn) => name + ", " + dc.sqlString)) + }) + + (fromClause match { + case Nil => error("Empty from clause is not allowed") + case _ => (" FROM " + fromClause.tail.foldLeft(fromClause.head.sqlInnerString) + ((name:String, rel:Relation) => name + ", " + rel.sqlInnerString)) + }) + + (whereClause match { + case None => "" + case Some(expr) => " WHERE " + expr.sqlInnerString + }) + + (groupByClause match { + case None => "" + case Some(gbl) => gbl match { + case Nil => error("Empty group by clause is not allowed") + case _ => + (" GROUP BY " + + gbl.tail.foldLeft(gbl.head.sqlInnerString) + ((name:String, gb) => name + ", " + gb.sqlInnerString)) + } + }) + + (havingClause match { + case None => "" + case Some(expr) => " HAVING " + expr.sqlString + }) + ); + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside a query. */ + def sqlInnerString: String = "("+sqlString+")"; + +} diff --git a/src/dbc/scala/dbc/statement/SetClause.scala b/src/dbc/scala/dbc/statement/SetClause.scala new file mode 100644 index 0000000000..e6a55ae846 --- /dev/null +++ b/src/dbc/scala/dbc/statement/SetClause.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +import scala.dbc.statement.expression._; + +/** Data to be inserted into a table in an Insert. */ +case class SetClause (name:String, expr:Expression) { + val value: Pair[String,Expression] = Pair(name,expr); + def sqlString: String = + value._1 + " = " + value._2.sqlInnerString; +} diff --git a/src/dbc/scala/dbc/statement/SetQuantifier.scala b/src/dbc/scala/dbc/statement/SetQuantifier.scala new file mode 100644 index 0000000000..ad7c2238c8 --- /dev/null +++ b/src/dbc/scala/dbc/statement/SetQuantifier.scala @@ -0,0 +1,34 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A set quantifier that defines the collection type of a relation. */ +abstract class SetQuantifier { + /** A SQL-99 compliant string representation of the set quantifier. */ + def sqlString: String; +} + +object SetQuantifier { + /** A set quantifier that defines a relation as being a bag. That means + * that duplicates are allowed. */ + case object AllTuples extends SetQuantifier { + /** A SQL-99 compliant string representation of the set quantifier. */ + def sqlString: String = "ALL"; + } + /** A set quantifier that defines a relation as being a set. That means + * that duplicates are not allowed and will be pruned. */ + case object DistinctTuples extends SetQuantifier { + /** A SQL-99 compliant string representation of the set quantifier. */ + def sqlString: String = "DISTINCT"; + } +} diff --git a/src/dbc/scala/dbc/statement/Statement.scala b/src/dbc/scala/dbc/statement/Statement.scala new file mode 100644 index 0000000000..5c78b075b7 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Statement.scala @@ -0,0 +1,18 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** An ISO-9075:2003 (SQL) statement. */ +abstract class Statement { + +} diff --git a/src/dbc/scala/dbc/statement/Status.scala b/src/dbc/scala/dbc/statement/Status.scala new file mode 100644 index 0000000000..3065ec5f7a --- /dev/null +++ b/src/dbc/scala/dbc/statement/Status.scala @@ -0,0 +1,30 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A statement that changes the status of the database. */ +abstract class Status extends Statement { + + /** A SQL-99 compliant string representation of the statement. */ + def sqlString: String; + + /** Executes the statement on the given database. */ + def execute (database: scala.dbc.Database): scala.dbc.result.Status[Unit] = { + database.executeStatement(this); + } + + def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[Unit] = { + database.executeStatement(this,debug); + } + +} diff --git a/src/dbc/scala/dbc/statement/Table.scala b/src/dbc/scala/dbc/statement/Table.scala new file mode 100644 index 0000000000..17015a6c73 --- /dev/null +++ b/src/dbc/scala/dbc/statement/Table.scala @@ -0,0 +1,40 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A reference to a table in the database. + * @author Gilles Dubochet + * @version 1.0 */ +abstract class Table extends Relation { + + /** The name of the table in the database. */ + def tableName: String; + + /** The name that the table will be called in the enclosing statement. */ + def tableRename: Option[String]; + + /** A SQL-99 compliant string representation of the relation statement. */ + def sqlString: String = { + "SELECT * FROM " + tableName + } + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside a query. */ + def sqlInnerString: String = ( + tableName + + (tableRename match { + case None => "" + case Some(rename) => " AS " + rename + }) + ) +} diff --git a/src/dbc/scala/dbc/statement/Transaction.scala b/src/dbc/scala/dbc/statement/Transaction.scala new file mode 100644 index 0000000000..a802aa82fa --- /dev/null +++ b/src/dbc/scala/dbc/statement/Transaction.scala @@ -0,0 +1,55 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +/** A statement that changes the status of the database. */ +case class Transaction [ResultType] ( + transactionBody: (scala.dbc.Database=>ResultType), + accessMode: Option[AccessMode], + isolationLevel: Option[IsolationLevel] +) extends Statement { + + /** A SQL-99 compliant string representation of the statement. */ + def sqlStartString: String = ( + "START TRANSACTION" + + (Pair(accessMode,isolationLevel) match { + case Pair(None,None) => "" + case Pair(Some(am),None) => " " + am.sqlString + case Pair(None,Some(il)) => " " + il.sqlString + case Pair(Some(am),Some(il)) => " " + am.sqlString + ", " + il.sqlString + }) + ); + + def sqlCommitString: String = { + "COMMIT" + } + + def sqlAbortString: String = { + "ROLLBACK" + } + + //def transactionBody: (()=>Unit); + + //def accessMode: Option[AccessMode]; + + //def isolationLevel: Option[IsolationLevel]; + + def execute (database: scala.dbc.Database): scala.dbc.result.Status[ResultType] = { + database.executeStatement(this); + } + + def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[ResultType] = { + database.executeStatement(this,debug); + } + +} diff --git a/src/dbc/scala/dbc/statement/Update.scala b/src/dbc/scala/dbc/statement/Update.scala new file mode 100644 index 0000000000..cf8a3c9b6f --- /dev/null +++ b/src/dbc/scala/dbc/statement/Update.scala @@ -0,0 +1,47 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement; + + +import scala.dbc.statement.expression._; + +/** An update of the state of a table. */ +case class Update ( + updateTarget: String, + setClauses: List[SetClause], + whereClause: Option[Expression] +) extends Status { + + + /** A SQL-99 compliant string representation of the select statement. */ + def sqlString: String = ( + "UPDATE " + + updateTarget + + " SET " + setClauses.map(sc=>sc.sqlString).mkString("",", ","") + + (whereClause match { + case None => "" + case Some(expr) => " WHERE " + expr.sqlString + }) + ); + + /** The name of the table that should be updated. */ + //def updateTarget: String; + + /** The data that will be added tot he table. */ + //def setClauses: List[SetClause]; + + /** Defines condition that must be true in the tuples that will be updated. + * This value expression must return a boolean or boolean-compatible + * value. */ + //def whereClause: Option[scala.dbc.statement.expression.Expression]; + +} diff --git a/src/dbc/scala/dbc/statement/expression/Aggregate.scala b/src/dbc/scala/dbc/statement/expression/Aggregate.scala new file mode 100644 index 0000000000..3a93864475 --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/Aggregate.scala @@ -0,0 +1,34 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class Aggregate extends Expression { + + def aggregateName: String; + + def setFunction: SetFunction; + + def filterClause: Option[Expression]; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = ( + aggregateName + + "(" + setFunction.sqlString + ")" + + (filterClause match { + case None => "" + case Some(fc) => " FILTER (WHERE " + fc.sqlString + ")" + }) + ) + +} diff --git a/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala b/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala new file mode 100644 index 0000000000..3b3ac6f0fe --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class BinaryOperator extends Expression { + + /** The name of the operator. */ + def operator: String; + + /** The expression applied on the left of the operator. */ + def leftOperand: Expression; + + /** The expression applied on the right of the operator. */ + def rightOperand: Expression; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = { + leftOperand.sqlInnerString + " " + operator + " " + rightOperand.sqlInnerString + } + +} diff --git a/src/dbc/scala/dbc/statement/expression/Constant.scala b/src/dbc/scala/dbc/statement/expression/Constant.scala new file mode 100644 index 0000000000..6ee665c97d --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/Constant.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class Constant extends Expression { + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = constantValue.sqlString; + + /** The value of the constant. */ + def constantValue: Value; +} diff --git a/src/dbc/scala/dbc/statement/expression/Default.scala b/src/dbc/scala/dbc/statement/expression/Default.scala new file mode 100644 index 0000000000..7d03872ab5 --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/Default.scala @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +case object Default extends Expression { + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = "DEFAULT"; + +} diff --git a/src/dbc/scala/dbc/statement/expression/Field.scala b/src/dbc/scala/dbc/statement/expression/Field.scala new file mode 100644 index 0000000000..b005f024bd --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/Field.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class Field extends Expression { + + /** The name of the schema in the database where the field is located. */ + def schemaName: Option[String] = None; + + /** The name of the table in the database where the field is located. */ + def tableName: Option[String]; + + /** The name of the field in the database. */ + def fieldName: String; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = ( + (schemaName match { + case None => "" + case Some(sn) => sn + "." + }) + + (tableName match { + case None => "" + case Some(tn) => tn + "." + }) + fieldName + ) + +} diff --git a/src/dbc/scala/dbc/statement/expression/FunctionCall.scala b/src/dbc/scala/dbc/statement/expression/FunctionCall.scala new file mode 100644 index 0000000000..bfee8701dd --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/FunctionCall.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +case class FunctionCall ( + functionName: String, + arguments: List[Expression] +) extends Expression { + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = { + functionName + "(" + arguments.mkString("",", ","") + ")" + } + + /** The name of the function to call. */ + //def functionName: String; + + /** A list of all argument expressions to pass to the function, in order. */ + //def arguments: List[Expression]; + +} diff --git a/src/dbc/scala/dbc/statement/expression/Select.scala b/src/dbc/scala/dbc/statement/expression/Select.scala new file mode 100644 index 0000000000..44c14e8474 --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/Select.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class Select extends Expression { + + /** The actual select statement */ + def selectStatement: statement.Select; + + /** A SQL-99 compliant string representation of the expression. */ + override def sqlString: String = selectStatement.sqlString; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = "("+selectStatement.sqlString+")"; + +} diff --git a/src/dbc/scala/dbc/statement/expression/SetFunction.scala b/src/dbc/scala/dbc/statement/expression/SetFunction.scala new file mode 100644 index 0000000000..b58850df12 --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/SetFunction.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class SetFunction { + /** A SQL-99 compliant string representation of the set quantifier. */ + def sqlString: String; +} + +object SetFunction { + abstract class Asterisk extends SetFunction { + def sqlString = "(*)"; + } + abstract class General extends SetFunction { + def setQuantifier: Option[SetQuantifier]; + def valueExpression: Expression; + def sqlString = ( + "(" + + (setQuantifier match { + case None => "" + case Some(sq) => sq.sqlString + " " + }) + + valueExpression.sqlString + ")" + ); + } + abstract class Binary extends SetFunction { + def sqlString = error("Binary set function is not supported yet."); + } +} diff --git a/src/dbc/scala/dbc/statement/expression/TypeCast.scala b/src/dbc/scala/dbc/statement/expression/TypeCast.scala new file mode 100644 index 0000000000..5c9cbddebe --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/TypeCast.scala @@ -0,0 +1,31 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +case class TypeCast ( + expression: Expression, + castType: DataType +) extends Expression { + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = { + "CAST (" + expression.sqlInnerString + " AS " + castType.sqlString + ")"; + } + + /** The expression that will be casted. */ + //def expression: Expression; + + /** The type to which to cast. */ + //def castType: scala.dbc.datatype.DataType; +} diff --git a/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala b/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala new file mode 100644 index 0000000000..9068595f77 --- /dev/null +++ b/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.statement.expression; + + +abstract class UnaryOperator extends Expression { + + /** The name of the operator */ + def operator: String; + + /** Whether the operator comes before the operand or not. */ + def operatorIsLeft: Boolean; + + /** The operand applied to the operator. */ + def operand: Expression; + + /** A SQL-99 compliant string representation of the relation sub- + * statement. This only has a meaning inside another statement. */ + def sqlInnerString: String = operatorIsLeft match { + case true => operator + " " + operand.sqlInnerString; + case false => operand.sqlInnerString + " " + operator; + } +} diff --git a/src/dbc/scala/dbc/syntax/DataTypeUtil.scala b/src/dbc/scala/dbc/syntax/DataTypeUtil.scala new file mode 100644 index 0000000000..c42efb082f --- /dev/null +++ b/src/dbc/scala/dbc/syntax/DataTypeUtil.scala @@ -0,0 +1,98 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.syntax; + + +import java.math.BigDecimal; +import java.math.BigInteger; + +object DataTypeUtil { + + final val java_lang_Integer_SIZE = 32; + final val java_lang_Long_SIZE = 64; + + def boolean = new datatype.Boolean; + def tinyint = new datatype.ExactNumeric[Byte](dbc.DataType.BYTE) { + val precisionRadix = 2; + val precision = 8; + val signed = true; + val scale = 0; + } + def smallint = new datatype.ExactNumeric[Short](dbc.DataType.SHORT) { + val precisionRadix = 2; + val precision = 16; + val signed = true; + val scale = 0; + } + def integer = new datatype.ExactNumeric[Int](dbc.DataType.INT) { + val precisionRadix = 2; + val precision = 32; + val signed = true; + val scale = 0; + } + def bigint = new datatype.ExactNumeric[Long](dbc.DataType.LONG) { + val precisionRadix = 2; + val precision = 64; + val signed = true; + val scale = 0; + } + def numeric (_precision:Int): DataType = numeric(_precision,0); + def numeric (_precision:Int, _scale:Int): DataType = + Pair(datatype.Factory.bytePrecision(_precision,true,true),_scale == 0) match { + case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) => + new datatype.ExactNumeric[Int](DataType.INT) { + val precisionRadix = 10; + val precision = _precision; + val signed = true; + val scale = 0; + } + case Pair(bp,true) if (bp <= java_lang_Long_SIZE) => + new datatype.ExactNumeric[Long](DataType.LONG) { + val precisionRadix = 10; + val precision = _precision; + val signed = true; + val scale = 0; + } + case Pair(_,true) => + new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) { + val precisionRadix = 10; + val precision = _precision; + val signed = true; + val scale = 0; + } + case Pair(_,false) => + new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) { + val precisionRadix = 10; + val precision = _precision; + val signed = true; + val scale = _scale; + } + } + def real = new datatype.ApproximateNumeric[Float](DataType.FLOAT) { + val precisionRadix = 2; + val precision = 64; + val signed = true; + } + def doublePrecision = new datatype.ApproximateNumeric[Double](DataType.DOUBLE) { + val precisionRadix = 2; + val precision = 128; + val signed = true; + } + def character (_length: Int) = new datatype.Character { + val length = _length; + } + def characterVarying (_length: Int) = new datatype.CharacterVarying { + def length = _length; + } + def characterLargeObject = new datatype.CharacterLargeObject; + +} diff --git a/src/dbc/scala/dbc/syntax/Database.scala b/src/dbc/scala/dbc/syntax/Database.scala new file mode 100644 index 0000000000..31a04b1129 --- /dev/null +++ b/src/dbc/scala/dbc/syntax/Database.scala @@ -0,0 +1,33 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.syntax; + + +import java.net.URI; + +object Database { + + def database (server:String, username:String, password:String): dbc.Database = { + val uri = new URI(server); + // Java 1.5 if (uri.toString().contains("postgres")) { + if (uri.toString().indexOf("postgres") != -1) { + new dbc.Database(new vendor.PostgreSQL { + val uri = new URI(server); + val user = username; + val pass = password; + }) + } else { + throw new Exception("No DBMS vendor support could be found for the given URI"); + } + } + +} diff --git a/src/dbc/scala/dbc/syntax/Statement.scala b/src/dbc/scala/dbc/syntax/Statement.scala new file mode 100644 index 0000000000..027a05b8fc --- /dev/null +++ b/src/dbc/scala/dbc/syntax/Statement.scala @@ -0,0 +1,274 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.syntax; + + +import java.math.BigDecimal; +import java.math.BigInteger; + +import StatementExpression._; + +/* + +ASSUMPTIONS: + +IMPROVABLE: +For type safety, all types must be defined. If one is missing, none is taken into account. +It is possible to redefine many types or renamings for a field, in that case, + only the last one is taken into account ("a" as "b" as "c" of boolean as "e" of integer + is equivalent to "a" as "e" of integer). + +FIXED: + +*/ + +object Statement { + + // SELECT ZYGOTE ... + + def select: SelectZygote = new SelectZygote { + val setQuantifier = None; + } + def selectBag: SelectZygote = new SelectZygote { + val setQuantifier = Some(statement.SetQuantifier.AllTuples); + } + def selectSet: SelectZygote = new SelectZygote { + val setQuantifier = Some(statement.SetQuantifier.DistinctTuples); + } + + abstract class SelectZygote { + def setQuantifier: Option[statement.SetQuantifier]; + def fields (sdc:SelectDerivedColumns): SelectOf = new SelectOf { + val setQuantifier = SelectZygote.this.setQuantifier; + val selectList = sdc.selectList; + val selectTypes = sdc.selectTypes; + } + } + + abstract class SelectDerivedField { + def fieldValue: StatementField; + def fieldRename: Option[String] = {val x = None; x} + def fieldType: Option[dbc.DataType] = {val x = None; x} + def as (rename:String): SelectDerivedField = new SelectDerivedField { + val fieldValue = SelectDerivedField.this.fieldValue; + override val fieldRename = Some(rename); + override val fieldType = SelectDerivedField.this.fieldType; + } + def of (datatype:dbc.DataType): SelectDerivedField = new SelectDerivedField { + val fieldValue = SelectDerivedField.this.fieldValue; + override val fieldRename = SelectDerivedField.this.fieldRename; + override val fieldType = Some(datatype); + } + } + + implicit def statementFieldToSelectDerivedField (fv:StatementField): SelectDerivedField = new SelectDerivedField { + val fieldValue = fv; + } + + implicit def stringToSelectDerivedField (fv:String): SelectDerivedField = new SelectDerivedField { + val fieldValue: StatementField = StatementExpression.stringToStatementField(fv); + } + + abstract class SelectDerivedColumns { + def selectList: List[statement.DerivedColumn]; + def selectTypes: List[DataType]; + def and (sdc:SelectDerivedColumns): SelectDerivedColumns = new SelectDerivedColumns { + val selectList = SelectDerivedColumns.this.selectList ::: sdc.selectList; + val selectTypes = + if (SelectDerivedColumns.this.selectTypes.isEmpty | sdc.selectTypes.isEmpty) + Nil + else + SelectDerivedColumns.this.selectTypes ::: sdc.selectTypes; + } + } + + implicit def selectDerivedFieldToSelectDerivedColumns (sdf:SelectDerivedField): SelectDerivedColumns = new SelectDerivedColumns { + val selectList = List(new statement.DerivedColumn { + val valueExpression = sdf.fieldValue.toStatement; + val asClause = sdf.fieldRename; + }); + val selectTypes = if (sdf.fieldType.isEmpty) Nil else List(sdf.fieldType.get); + } + + implicit def stringToSelectDerivedColumns (sdfs:String): SelectDerivedColumns = { + val sdf: SelectDerivedField = sdfs; + selectDerivedFieldToSelectDerivedColumns(sdf); + } + + // SELECT OF ... + + abstract class SelectOf { + def setQuantifier: Option[statement.SetQuantifier]; + def selectList: List[statement.DerivedColumn]; + def selectTypes: List[DataType]; + def from (sst:SelectSourceTables): SelectBeyond = new SelectBeyond { + val setQuantifier = SelectOf.this.setQuantifier; + val selectList = SelectOf.this.selectList; + val selectTypes = SelectOf.this.selectTypes; + val fromClause = sst.fromClause; + val whereClause = None; + val groupByClause = None; + val havingClause = None; + } + } + + abstract class SelectSourceTable { + def fromRelation: statement.Relation; + def innerJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { + val fromRelation = new statement.Jointure { + val leftRelation = SelectSourceTable.this.fromRelation; + val rightRelation = sst.fromRelation; + val joinType = statement.JoinType.Inner; + val joinCondition = None; + val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; + } + } + def leftOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { + val fromRelation = new statement.Jointure { + val leftRelation = SelectSourceTable.this.fromRelation; + val rightRelation = sst.fromRelation; + val joinType = statement.JoinType.Outer.Left; + val joinCondition = None; + val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; + } + } + def rightOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { + val fromRelation = new statement.Jointure { + val leftRelation = SelectSourceTable.this.fromRelation; + val rightRelation = sst.fromRelation; + val joinType = statement.JoinType.Outer.Right; + val joinCondition = None; + val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; + } + } + def fullOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { + val fromRelation = new statement.Jointure { + val leftRelation = SelectSourceTable.this.fromRelation; + val rightRelation = sst.fromRelation; + val joinType = statement.JoinType.Outer.Full; + val joinCondition = None; + val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; + } + } + } + + implicit def stringToSelectSourceTable (sct:String): SelectSourceTable = new SelectSourceTable { + val fromRelation = new statement.Table { + val tableName = sct; + val tableRename = None; + val fieldTypes = Nil; + } + } + + implicit def selectToSelectSourceTable (sct:statement.Select): SelectSourceTable = new SelectSourceTable { + val fromRelation = sct; + } + + abstract class SelectSourceTables { + def fromClause: List[statement.Relation]; + def join (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables { + val fromClause = SelectSourceTables.this.fromClause ::: List(sct.fromRelation); + } + } + + implicit def stringToSelectSourceTables (sct:String): SelectSourceTables = new SelectSourceTables { + val fromClause = List(new statement.Table { + val tableName = sct; + val tableRename = None; + val fieldTypes = Nil; + }); + } + + implicit def selectToSelectSourceTables (sct:statement.Select): SelectSourceTables = new SelectSourceTables { + val fromClause = List(sct); + } + + implicit def selectSourceTableToSelectSourceTables (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables { + val fromClause = List(sct.fromRelation); + } + + // SELECT BEYOND ... + + abstract class SelectBeyond { + def setQuantifier: Option[statement.SetQuantifier]; + def selectList: List[statement.DerivedColumn]; + def selectTypes: List[DataType]; + def fromClause: List[statement.Relation]; + def whereClause: Option[statement.Expression]; + def groupByClause: Option[List[statement.Expression]]; + def havingClause: Option[statement.Expression]; + def where (se:StatementExpression): SelectBeyond = new SelectBeyond { + val setQuantifier = SelectBeyond.this.setQuantifier; + val selectList = SelectBeyond.this.selectList; + val selectTypes = SelectBeyond.this.selectTypes; + val fromClause = SelectBeyond.this.fromClause; + val whereClause = Some(se.toStatement); + val groupByClause = SelectBeyond.this.groupByClause; + val havingClause = SelectBeyond.this.havingClause; + } + def groupBy (sgb:SelectGroupBy): SelectBeyond = new SelectBeyond { + val setQuantifier = SelectBeyond.this.setQuantifier; + val selectList = SelectBeyond.this.selectList; + val selectTypes = SelectBeyond.this.selectTypes; + val fromClause = SelectBeyond.this.fromClause; + val whereClause = SelectBeyond.this.whereClause; + val groupByClause = Some(sgb.groupByClause); + val havingClause = SelectBeyond.this.havingClause; + } + def having (se:StatementExpression): SelectBeyond = new SelectBeyond { + val setQuantifier = SelectBeyond.this.setQuantifier; + val selectList = SelectBeyond.this.selectList; + val selectTypes = SelectBeyond.this.selectTypes; + val fromClause = SelectBeyond.this.fromClause; + val whereClause = SelectBeyond.this.whereClause; + val groupByClause = SelectBeyond.this.groupByClause; + val havingClause = Some(se.toStatement); + } + } + + implicit def selectBeyondToStatementSelect (sb:SelectBeyond): statement.Select = new statement.Select { + val setQuantifier = sb.setQuantifier; + val selectList = sb.selectList; + val fromClause = sb.fromClause; + val whereClause = sb.whereClause; + val groupByClause = sb.groupByClause; + val havingClause = sb.havingClause; + val fieldTypes = sb.selectTypes; + } + + abstract class SelectGroupBy { + def groupByClause: List[statement.Expression]; + def then (se:StatementExpression): SelectGroupBy = new SelectGroupBy { + val groupByClause = + SelectGroupBy.this.groupByClause ::: List(se.toStatement); + } + def then (se:String): SelectGroupBy = new SelectGroupBy { + val groupByClause = + SelectGroupBy.this.groupByClause ::: List(new statement.expression.Field { + val tableName = None; + val fieldName = se; + }); + } + } + + implicit def statementExpressionToSelectGroupBy (se:StatementExpression): SelectGroupBy = new SelectGroupBy { + val groupByClause = List(se.toStatement); + } + + implicit def stringToSelectGroupBy (se:String): SelectGroupBy = new SelectGroupBy { + val groupByClause = List(new statement.expression.Field { + val tableName = None; + val fieldName = se; + }); + } + +} diff --git a/src/dbc/scala/dbc/syntax/StatementExpression.scala b/src/dbc/scala/dbc/syntax/StatementExpression.scala new file mode 100644 index 0000000000..78c75ae174 --- /dev/null +++ b/src/dbc/scala/dbc/syntax/StatementExpression.scala @@ -0,0 +1,221 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.syntax; + + +import java.math.BigDecimal; +import java.math.BigInteger; + +abstract class StatementExpression { + + def toStatement: statement.Expression; + + def and (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "AND"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def or (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "OR"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def == (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "="; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def < (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "<"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def > (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = ">"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def <= (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "<="; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def >= (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = ">="; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def <> (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "<>"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def isNull: StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "IS NULL"; + val operatorIsLeft = false; + val operand = StatementExpression.this.toStatement; + } + } + def isNotNull: StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "IS NOT NULL"; + val operatorIsLeft = false; + val operand = StatementExpression.this.toStatement; + } + } + def + (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "+"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def - (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "-"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def * (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "*"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def / (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "/"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def % (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "%"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def ^ (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "^"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def not : StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "!"; + val operatorIsLeft = false; + val operand = StatementExpression.this.toStatement; + } + } + def || (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "||"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def like (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "LIKE"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def similar (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "SIMILAR"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = se.toStatement; + } + } + def in (se:statement.Select): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.BinaryOperator { + val operator = "IN"; + val leftOperand = StatementExpression.this.toStatement; + val rightOperand = new statement.expression.Select { + val selectStatement = se; + }; + } + } + +} + +object StatementExpression { + + def not (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "NOT"; + val operatorIsLeft = true; + val operand = se.toStatement; + } + } + def abs (se:StatementExpression): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "@"; + val operatorIsLeft = true; + val operand = se.toStatement; + } + } + def exists (se:statement.Select): StatementExpression = new StatementExpression { + val toStatement = new statement.expression.UnaryOperator { + val operator = "EXISTS"; + val operatorIsLeft = true; + val operand = new statement.expression.Select { + val selectStatement = se; + }; + } + } + + abstract class StatementField extends StatementExpression { + def fieldName: String; + def tableName: Option[String] = None; + def in (tn:String): StatementField = new StatementField { + val fieldName = StatementField.this.fieldName; + override val tableName = Some(tn); + } + def toStatement: statement.expression.Field = new statement.expression.Field { + override val schemaName = None; + val tableName = StatementField.this.tableName; + val fieldName = StatementField.this.fieldName; + } + } + + implicit def stringToStatementField (ef:String): StatementField = new StatementField { + val fieldName = ef; + } + + + + +} diff --git a/src/dbc/scala/dbc/value/ApproximateNumeric.scala b/src/dbc/scala/dbc/value/ApproximateNumeric.scala new file mode 100644 index 0000000000..5da4fec640 --- /dev/null +++ b/src/dbc/scala/dbc/value/ApproximateNumeric.scala @@ -0,0 +1,28 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +abstract class ApproximateNumeric [Type] extends Value { + + val dataType: datatype.ApproximateNumeric[Type]; + + def sqlString = nativeValue.toString(); + + } + +object ApproximateNumeric { + + implicit def approximateNumericToFloar (obj:value.ApproximateNumeric[Float]): Float = obj.nativeValue; + implicit def approximateNumericToDouble (obj:value.ApproximateNumeric[Double]): Double = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/Boolean.scala b/src/dbc/scala/dbc/value/Boolean.scala new file mode 100644 index 0000000000..fba78dcfd1 --- /dev/null +++ b/src/dbc/scala/dbc/value/Boolean.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +abstract class Boolean extends Value { + + val dataType: datatype.Boolean; + + def sqlString = if (nativeValue) "TRUE" else "FALSE"; + +} + +object Boolean { + + implicit def booleanToBoolean (obj:value.Boolean): scala.Boolean = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/Character.scala b/src/dbc/scala/dbc/value/Character.scala new file mode 100644 index 0000000000..c02a21b28e --- /dev/null +++ b/src/dbc/scala/dbc/value/Character.scala @@ -0,0 +1,35 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +/** A SQL-99 value of type character string. */ +abstract class Character extends Value { + + override val dataType: datatype.Character; + + /** An SQL-99 compliant string representation of the value. */ + def sqlString: String = { + "'" + nativeValue + "'" + } + +} + +/** An object offering transformation methods (views) on the value. + * This object must be visible in an expression to use value auto- + * conversion. */ +object Character { + + /** A character string value as a native string. */ + implicit def characterToString (obj:value.Character): String = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/CharacterLargeObject.scala b/src/dbc/scala/dbc/value/CharacterLargeObject.scala new file mode 100644 index 0000000000..61f55f868a --- /dev/null +++ b/src/dbc/scala/dbc/value/CharacterLargeObject.scala @@ -0,0 +1,35 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +/** A SQL-99 value of type character large object. */ +abstract class CharacterLargeObject extends Value { + + override val dataType: datatype.CharacterLargeObject; + + /** An SQL-99 compliant string representation of the value. */ + def sqlString: String = { + "'" + nativeValue + "'" + } + +} + +/** An object offering transformation methods (views) on the value. + * This object must be visible in an expression to use value auto- + * conversion. */ +object CharacterLargeObject { + + /** A character large object value as a native string. */ + implicit def characterLargeObjectToString (obj:value.CharacterLargeObject): String = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/CharacterVarying.scala b/src/dbc/scala/dbc/value/CharacterVarying.scala new file mode 100644 index 0000000000..177dbdba5b --- /dev/null +++ b/src/dbc/scala/dbc/value/CharacterVarying.scala @@ -0,0 +1,35 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +/** A SQL-99 value of type character varying string. */ +abstract class CharacterVarying extends Value { + + override val dataType: datatype.CharacterVarying; + + /** An SQL-99 compliant string representation of the value. */ + def sqlString: String = { + "'" + nativeValue + "'" + } + +} + +/** An object offering transformation methods (views) on the value. + * This object must be visible in an expression to use value auto- + * conversion. */ +object CharacterVarying { + + /** A character varying string value as a native string. */ + implicit def characterVaryingToString (obj:value.CharacterVarying): String = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/Conversion.scala b/src/dbc/scala/dbc/value/Conversion.scala new file mode 100644 index 0000000000..093cf55902 --- /dev/null +++ b/src/dbc/scala/dbc/value/Conversion.scala @@ -0,0 +1,157 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +import java.math._; + +object Conversion { + + class Illegal (msg:String) extends Exception(msg); + + implicit def view1 (value:Value): Byte = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to byte: "+value) + } + } + + implicit def view2 (value:Value): Short = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.SHORT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to short: "+value) + } + } + + implicit def view3 (value:Value): Int = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.SHORT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.INT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to int: "+value) + } + } + + implicit def view4 (value:Value): Long = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.SHORT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.INT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.LONG) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to long: "+value) + } + } + + implicit def view5 (value:Value): BigInteger = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + new BigInteger(v.nativeValue.toString(),10) + } else if (value.dataType.nativeTypeId == DataType.SHORT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; + new BigInteger(v.nativeValue.toString(),10) + } else if (value.dataType.nativeTypeId == DataType.INT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; + new BigInteger(v.nativeValue.toString(),10) + } else if (value.dataType.nativeTypeId == DataType.LONG) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; + new BigInteger(v.nativeValue.toString(),10) + } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to big integer: "+value) + } + } + + implicit def view6 (value:Value): BigDecimal = { + if (value.dataType.nativeTypeId == DataType.BYTE) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; + new BigDecimal(v.nativeValue.toString()) + } else if (value.dataType.nativeTypeId == DataType.SHORT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; + new BigDecimal(v.nativeValue.toString()) + } else if (value.dataType.nativeTypeId == DataType.INT) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; + new BigDecimal(v.nativeValue.toString()) + } else if (value.dataType.nativeTypeId == DataType.LONG) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; + new BigDecimal(v.nativeValue.toString()) + } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]]; + new BigDecimal(v.nativeValue) + } else if (value.dataType.nativeTypeId == DataType.BIG_DECIMAL) { + val v = value.asInstanceOf[dbc.value.ExactNumeric[BigDecimal]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to big decimal: "+value) + } + } + + implicit def view7 (value:Value): Float = { + if (value.dataType.nativeTypeId == DataType.FLOAT) { + val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to float: "+value) + } + } + + implicit def view8 (value:Value): Double = { + if (value.dataType.nativeTypeId == DataType.FLOAT) { + val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]]; + v.nativeValue.coerce + } else if (value.dataType.nativeTypeId == DataType.DOUBLE) { + val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Double]]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to double: "+value) + } + } + + implicit def view9 (value:Value): scala.Boolean = { + if (value.dataType.nativeTypeId == DataType.BOOLEAN) { + val v = value.asInstanceOf[dbc.value.Boolean]; + v.nativeValue + } else { + throw new Illegal("Cannot convert value to boolean: "+value) + } + } + + implicit def view10 (value:Value): String = value match { + case v:dbc.value.Character => v.nativeValue; + case v:dbc.value.CharacterLargeObject => v.nativeValue; + case v:dbc.value.CharacterVarying => v.nativeValue; + case _ => throw new Illegal("Cannot convert value to string") + } + +} diff --git a/src/dbc/scala/dbc/value/ExactNumeric.scala b/src/dbc/scala/dbc/value/ExactNumeric.scala new file mode 100644 index 0000000000..1c30c89c29 --- /dev/null +++ b/src/dbc/scala/dbc/value/ExactNumeric.scala @@ -0,0 +1,35 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +import java.math.BigInteger; +import java.math.BigDecimal; + +abstract class ExactNumeric [Type] extends Value { + + val dataType: datatype.ExactNumeric[Type]; + + def sqlString = nativeValue.toString(); + +} + +object ExactNumeric { + + implicit def exactNumericToByte (obj:value.ExactNumeric[Byte]): Byte = obj.nativeValue; + implicit def exactNumericToShort (obj:value.ExactNumeric[Short]): Short = obj.nativeValue; + implicit def exactNumericToInt (obj:value.ExactNumeric[Int]): Int = obj.nativeValue; + implicit def exactNumericToLong (obj:value.ExactNumeric[Long]): Long = obj.nativeValue; + implicit def exactNumericToBigInteger (obj:value.ExactNumeric[BigInteger]): BigInteger = obj.nativeValue; + implicit def exactNumericToBigDecimal (obj:value.ExactNumeric[BigDecimal]): BigDecimal = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/value/Factory.scala b/src/dbc/scala/dbc/value/Factory.scala new file mode 100644 index 0000000000..34975937e7 --- /dev/null +++ b/src/dbc/scala/dbc/value/Factory.scala @@ -0,0 +1,95 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +import java.math.BigInteger; +import java.math.BigDecimal; + +object Factory { + + def create (result: java.sql.ResultSet, index: Int, expectedDataType: DataType): Value = { + expectedDataType.nativeTypeId match { + case DataType.OBJECT => + new value.Unknown { + val dataType = expectedDataType.asInstanceOf[datatype.Unknown]; + val nativeValue: Object = result.getObject(index); + } + case DataType.STRING => { + expectedDataType match { + case t:datatype.Character => + new value.Character { + val dataType = t; + val nativeValue: String = result.getString(index); + } + case t:datatype.CharacterVarying => + new value.CharacterVarying { + val dataType = t; + val nativeValue: String = result.getString(index); + } + case t:datatype.CharacterLargeObject => + new value.CharacterLargeObject { + val dataType = t; + val nativeValue: String = result.getString(index); + } + } + } + case DataType.BOOLEAN => + new value.Boolean { + val dataType = expectedDataType.asInstanceOf[datatype.Boolean]; + val nativeValue: scala.Boolean = result.getBoolean(index); + } + case DataType.FLOAT => + new value.ApproximateNumeric[Float] { + val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Float]]; + val nativeValue: Float = result.getFloat(index); + } + case DataType.DOUBLE => + new value.ApproximateNumeric[Double] { + val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Double]]; + val nativeValue: Double = result.getDouble(index); + } + case DataType.BYTE => + new value.ExactNumeric[Byte] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Byte]]; + val nativeValue: Byte = result.getByte(index); + } + case DataType.SHORT => + new value.ExactNumeric[Short] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Short]]; + val nativeValue: Short = result.getShort(index); + } + case DataType.INT => + new value.ExactNumeric[Int] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Int]]; + val nativeValue: Int = result.getInt(index); + } + case DataType.LONG => + new value.ExactNumeric[Long] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Long]]; + val nativeValue:Long = result.getLong(index); + } + case DataType.BIG_INTEGER => + new value.ExactNumeric[BigInteger] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigInteger]]; + val nativeValue: BigInteger = result.getBigDecimal(index).unscaledValue(); + } + case DataType.BIG_DECIMAL => + new value.ExactNumeric[BigDecimal] { + val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigDecimal]]; + val nativeValue: BigDecimal = result.getBigDecimal(index); + } + + } + } + +} diff --git a/src/dbc/scala/dbc/value/Unknown.scala b/src/dbc/scala/dbc/value/Unknown.scala new file mode 100644 index 0000000000..b1ba51d064 --- /dev/null +++ b/src/dbc/scala/dbc/value/Unknown.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.value; + + +abstract class Unknown extends Value { + + val dataType: datatype.Unknown; + + def sqlString = error ("An 'ANY' value cannot be represented."); + +} + +object UnknownType { + + def view (obj:value.Unknown): Object = obj.nativeValue; + +} diff --git a/src/dbc/scala/dbc/vendor/PostgreSQL.scala b/src/dbc/scala/dbc/vendor/PostgreSQL.scala new file mode 100644 index 0000000000..f637b32a82 --- /dev/null +++ b/src/dbc/scala/dbc/vendor/PostgreSQL.scala @@ -0,0 +1,27 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.dbc.vendor; + + +abstract class PostgreSQL extends Vendor { + + def uri:java.net.URI; + def user:String; + def pass:String; + + val retainedConnections = 5; + + val nativeDriverClass = Class.forName("org.postgresql.Driver"); + + val urlProtocolString = "jdbc:postgresql:" + +} diff --git a/src/library/scala/dbc/DataType.scala b/src/library/scala/dbc/DataType.scala deleted file mode 100644 index f9b12bc431..0000000000 --- a/src/library/scala/dbc/DataType.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -/** An ISO-9075:2003 (SQL) data type. Mappings between SQL types and - * database specific types should be provided by the database driver. - */ -abstract class DataType { - - /** Tests whether this datatype is equivalent to another. Usually, two - * types are defined as equivalent if they are equal. Two types can be - * equivalent without being equal if values of those types will be - * encoded in the same native Scala type. - */ - def isEquivalent(datatype: DataType): Boolean; - - /** Tests whether this datatype is equivalent or a subtype of another - * datatype. Type A is said to be subtype of type - * B if any value of type A can be - * represented as a value of type B. - */ - def isSubtypeOf(datatype: DataType): Boolean; - - /** The native Scala type in which values of this SQL type will be - * encoded. - */ - type NativeType <: Any; - - /** The native Scala type in which values of this SQL type will be - * encoded. This must point to the same type as NativeType. - */ - def nativeTypeId: DataType.Id; - - /** Whether the value can take the null value, None when this property is - * unknown. - */ - def nullable: Option[Boolean] = None; - - /** The SQL name of the type */ - def sqlString: String = "UNDEFINED DATA TYPE" - -} - -object DataType { - - type Id = Int; - - val OBJECT : Id = 10; - val BOOLEAN : Id = 20; - val BYTE : Id = 30; - val SHORT : Id = 31; - val INT : Id = 32; - val LONG : Id = 33; - val BIG_INTEGER: Id = 34; - val BIG_DECIMAL: Id = 35; - val FLOAT : Id = 40; - val DOUBLE : Id = 41; - val STRING : Id = 50; - -} diff --git a/src/library/scala/dbc/Database.scala b/src/library/scala/dbc/Database.scala deleted file mode 100644 index cd1ff4e6b1..0000000000 --- a/src/library/scala/dbc/Database.scala +++ /dev/null @@ -1,190 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -import java.sql._; - -/** A link to a database. The Database abstract class must - * be specialised for every different DBMS. - * - * @author Gilles Dubochet - */ -case class Database(dbms: Vendor) { - - class Closed extends Exception; - - /** A lock used for operations that need to be atomic for this database - * instance. */ - private val lock: scala.concurrent.Lock = new scala.concurrent.Lock(); - - /** The vendor of the DBMS that contains this database. */ - private val vendor: Vendor = dbms; - - /** The Database connections available to use. */ - private var availableConnections: List[Connection] = Nil; - - /** The connections that are currently in use. */ - private var usedConnections: List[Connection] = Nil; - - /** Whether the database no longer accepts new connections. */ - private var closing: Boolean = false; - - /** Retrieves a connection from the available connection pool or creates - * a new one. - * - * @returns A connection that can be used to access the database. - */ - private def getConnection: Connection = { - if (closing) { - throw new Closed; - } else { - availableConnections match { - case Nil => { - lock.acquire; - val connection = vendor.getConnection; - usedConnections = connection :: usedConnections; - lock.release; - connection - } - case connection :: cs => { - lock.acquire; - availableConnections = cs; - usedConnections = connection :: usedConnections; - lock.release; - connection; - } - } - } - } - - /** Closes a connection to this database. A closed connection might - * also return to the available connection pool if the latter is depleted. - * - * @param connection The connection that should be closed. - */ - private def closeConnection(connection: Connection): Unit = { - if (closing) { - connection.close(); - } else { - lock.acquire; - usedConnections = usedConnections.remove(e => (e.equals(connection))); - if (availableConnections.length < vendor.retainedConnections) - availableConnections = connection :: availableConnections - else - connection.close(); - lock.release; - } - } - - /** .. - */ - def close: Unit = { - closing = true; - for (val conn <- availableConnections) conn.close(); - } - - /** Executes a statement that returns a relation on this database. - * - * @param relationStatement The statement to execute. - * @return The relation returned by the database for this statement. - */ - def executeStatement(relationStatement: statement.Relation): result.Relation = - executeStatement(relationStatement, false); - - /** Executes a statement that returns a relation on this database. - * - * @param relationStatement The statement to execute. - * @param debug Whether debugging information should be printed on the console. - * @return The relation returned by the database for this statement. - */ - def executeStatement(relationStatement: statement.Relation, - debug: Boolean): result.Relation = - new scala.dbc.result.Relation { - val statement = relationStatement; - if (debug) Console.println("## " + statement.sqlString); - private val connection = getConnection; - val sqlResult = connection.createStatement().executeQuery(statement.sqlString); - closeConnection(connection); - statement.typeCheck(this); - } - - /** Executes a statement that updates the state of the database. - * - * @param statusStatement The statement to execute. - * @return The status of the database after the statement has been executed. - */ - def executeStatement(statusStatement: statement.Status): result.Status[Unit] = - executeStatement(statusStatement, false); - - /** Executes a statement that updates the state of the database. - * - * @param statusStatement The statement to execute. - * @param debug Whether debugging information should be printed on the console. - * @return The status of the database after the statement has been executed. - */ - def executeStatement(statusStatement: statement.Status, - debug: Boolean): result.Status[Unit] = - new scala.dbc.result.Status[Unit] { - val statement = statusStatement; - if (debug) Console.println("## " + statement.sqlString); - def result = (); - private val connection = getConnection; - val jdbcStatement: java.sql.Statement = connection.createStatement(); - jdbcStatement.execute(statement.sqlString); - val touchedCount = Some(jdbcStatement.getUpdateCount()); - closeConnection(connection); - } - - /** Executes a list of statements or other operations inside a transaction. - * Only statements are protected in a transaction, other Scala code is not. - * - * @param transactionStatement The transaction to execute as a closure. - * @return The status of the database after the transaction has been executed. - */ - def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType]): result.Status[ResultType] = - executeStatement(transactionStatement, false); - - /** Executes a list of statements or other operations inside a transaction. - * Only statements are protected in a transaction, other Scala code is not. - * - * @param transactionStatement The transaction to execute as a closure. - * @param debug Whether debugging information should be printed on the console. - * @return The status of the database after the transaction has been executed. - */ - def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType], debug: Boolean): result.Status[ResultType] = { - new scala.dbc.result.Status[ResultType] { - val touchedCount = None; - val statement = transactionStatement; - private val connection = getConnection; - connection.setAutoCommit(false); - val jdbcStatement: java.sql.Statement = connection.createStatement(); - if (debug) Console.println("## " + transactionStatement.sqlStartString); - jdbcStatement.execute(transactionStatement.sqlStartString); - val result: ResultType = try { - val buffer = transactionStatement.transactionBody(Database.this); - if (debug) Console.println("## " + transactionStatement.sqlCommitString); - jdbcStatement.execute(transactionStatement.sqlCommitString); - buffer - } catch { - case e: Throwable => { - if (debug) Console.println("## " + transactionStatement.sqlAbortString); - jdbcStatement.execute(transactionStatement.sqlAbortString); - throw e; - } - } - connection.setAutoCommit(true); - closeConnection(connection); - } - } - -} diff --git a/src/library/scala/dbc/Syntax.scala b/src/library/scala/dbc/Syntax.scala deleted file mode 100644 index d8ed87740a..0000000000 --- a/src/library/scala/dbc/Syntax.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -import java.math.{BigDecimal, BigInteger}; - - -/** This class .. - * - */ -object Syntax { - - import syntax.DataTypeUtil; - - /* Data types */ - def boolean = DataTypeUtil.boolean; - def tinyint = DataTypeUtil.tinyint; - def smallint = DataTypeUtil.smallint; - def integer = DataTypeUtil.integer; - def bigint = DataTypeUtil.bigint; - def real = DataTypeUtil.real; - - def numeric(precision: Int) = DataTypeUtil.numeric(precision); - def numeric(precision: Int, scale: Int) = DataTypeUtil.numeric(precision, scale); - - def doublePrecision = DataTypeUtil.doublePrecision; - def character(length: Int) = DataTypeUtil.character(length); - def characterVarying(length: Int) = DataTypeUtil.characterVarying(length); - def characterLargeObject = DataTypeUtil.characterLargeObject; - - /* Statements */ - //def select - - /* Other stuff */ - def database (server: String, username: String, password: String): dbc.Database = - syntax.Database.database(server, username, password); - -} diff --git a/src/library/scala/dbc/Utilities.scala b/src/library/scala/dbc/Utilities.scala deleted file mode 100644 index c2691143f3..0000000000 --- a/src/library/scala/dbc/Utilities.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -/** An object offering transformation methods (views) on various values. - * This object's members must be visible in an expression to use value - * auto-conversion. - */ -object Utilities { - - implicit def constantToValue (obj: statement.expression.Constant): Value = - obj.constantValue; - - implicit def valueToConstant (obj: Value): statement.expression.Constant = - new statement.expression.Constant { - val constantValue = obj; - } - -} diff --git a/src/library/scala/dbc/Value.scala b/src/library/scala/dbc/Value.scala deleted file mode 100644 index 13a7678928..0000000000 --- a/src/library/scala/dbc/Value.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -/** A SQL-99 value of any type. */ -abstract class Value { - - /** The SQL-99 type of the value. */ - val dataType: DataType; - - type NativeType = dataType.type#NativeType; - - val nativeValue: NativeType; - - /** A SQL-99 compliant string representation of the value. */ - def sqlString: String; - -} diff --git a/src/library/scala/dbc/Vendor.scala b/src/library/scala/dbc/Vendor.scala deleted file mode 100644 index b9b3595d95..0000000000 --- a/src/library/scala/dbc/Vendor.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc; - - -import java.sql.{Connection, Driver}; - - -/** This class .. - */ -abstract class Vendor { - - def nativeDriverClass: Class; - def uri: java.net.URI; - def user: String; - def pass: String; - def nativeProperties: java.util.Properties = { - val properties = new java.util.Properties(); - properties.setProperty("user", user); - properties.setProperty("password", pass); - properties - } - - def retainedConnections: Int; - - def getConnection: Connection = { - val driver = nativeDriverClass.newInstance().asInstanceOf[Driver]; - driver.connect(uri.toString(),nativeProperties) - } - - def urlProtocolString: String; - -} diff --git a/src/library/scala/dbc/datatype/ApproximateNumeric.scala b/src/library/scala/dbc/datatype/ApproximateNumeric.scala deleted file mode 100644 index 8943f46364..0000000000 --- a/src/library/scala/dbc/datatype/ApproximateNumeric.scala +++ /dev/null @@ -1,57 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A type category for all SQL types that store varying-precision - * numbers. - */ -abstract class ApproximateNumeric[Type] ( - override val nativeTypeId: DataType.Id -) extends datatype.Numeric[Type](nativeTypeId) { - - def isEquivalent(datatype: DataType) = datatype match { - case dt: ApproximateNumeric[Type] => - (nativeTypeId == dt.nativeTypeId && - precisionRadix == dt.precisionRadix && - precision == dt.precision && - signed == dt.signed) - case _ => - false - } - - def isSubtypeOf (datatype:DataType) = datatype match { - case dt:ApproximateNumeric[Type] => - (nativeTypeId == dt.nativeTypeId && - precisionRadix == dt.precisionRadix && - precision <= dt.precision && - signed == dt.signed) - case _ => - false - } - - /** A SQL-99 compliant string representation of the type. - *

Compatibility notice

This method assumes that a real - * uses 32 bits and a double 64. This is not defined in the - * standard but is usually the case. - */ - override def sqlString: java.lang.String = Tuple2(precisionRadix,precision) match { - case Tuple2(2,64) => "REAL" - case Tuple2(2,128) => "DOUBLE PRECISION" - case Tuple2(2,p) => - throw exception.UnsupportedFeature("SQL-99 does not support an approximate numeric type with a binary defined precision other than 16, 32 and 64 bits"); - case Tuple2(10,p) => "FLOAT (" + p.toString() + ")" - case Tuple2(pr,_) => - throw exception.UnsupportedFeature("SQL-99 does not support the precision of an approximate numeric type to be defined in a radix other than 2 or 10"); - } - -} diff --git a/src/library/scala/dbc/datatype/Boolean.scala b/src/library/scala/dbc/datatype/Boolean.scala deleted file mode 100644 index c4a880885e..0000000000 --- a/src/library/scala/dbc/datatype/Boolean.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** The SQL type for a truth value. */ -class Boolean extends DataType { - - def isEquivalent (datatype:DataType) = datatype match { - case dt:Boolean => true - case _ => false - } - - def isSubtypeOf (datatype:DataType) = isEquivalent(datatype); - - type NativeType = scala.Boolean; - val nativeTypeId = DataType.BOOLEAN; - - /** A SQL-99 compliant string representation of the type. */ - override def sqlString: java.lang.String = "BOOLEAN"; - -} diff --git a/src/library/scala/dbc/datatype/Character.scala b/src/library/scala/dbc/datatype/Character.scala deleted file mode 100644 index 02b4b182e0..0000000000 --- a/src/library/scala/dbc/datatype/Character.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A SQL type for a string of characters of arbitrary length with - * arbitrary character set. - */ -abstract class Character extends CharacterString { - - def isEquivalent(datatype: DataType) = datatype match { - case dt: Character => - length == dt.length && encoding == dt.encoding - case _ => - false - } - - def isSubtypeOf(datatype: DataType) = datatype match { - case dt: Character => - length >= dt.length && encoding == dt.encoding - case _ => - false - } - - /** The length of the string defined in characters. */ - def length: Int; - - /** A SQL-99 compliant string representation of the type. */ - override def sqlString: java.lang.String = "CHARACTER (" + length.toString() + ")"; - -} diff --git a/src/library/scala/dbc/datatype/CharacterLargeObject.scala b/src/library/scala/dbc/datatype/CharacterLargeObject.scala deleted file mode 100644 index c84bb4bae9..0000000000 --- a/src/library/scala/dbc/datatype/CharacterLargeObject.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A SQL type for an unbounded length string of characters with arbitrary - * character set. */ -class CharacterLargeObject extends CharacterString { - - def isEquivalent (datatype:DataType) = datatype match { - case dt:CharacterLargeObject => { - encoding == dt.encoding - } - case _ => false - } - - def isSubtypeOf (datatype:DataType) = isEquivalent(datatype); - - /** A SQL-99 compliant string representation of the type. */ - override def sqlString: java.lang.String = "CHARACTER LARGE OBJECT"; - -} diff --git a/src/library/scala/dbc/datatype/CharacterString.scala b/src/library/scala/dbc/datatype/CharacterString.scala deleted file mode 100644 index 1f250475b3..0000000000 --- a/src/library/scala/dbc/datatype/CharacterString.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A type category for all SQL types that store strings of characters. */ -abstract class CharacterString extends String { - - type NativeType = java.lang.String; - val nativeTypeId = DataType.STRING; - - /** The name of the character set in which the string is encoded. */ - def encoding: Option[java.lang.String] = None; - -} diff --git a/src/library/scala/dbc/datatype/CharacterVarying.scala b/src/library/scala/dbc/datatype/CharacterVarying.scala deleted file mode 100644 index e0cdbc819b..0000000000 --- a/src/library/scala/dbc/datatype/CharacterVarying.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A SQL type for a varying length string of characters with arbitrary - * maximal length and arbitrary character set. - */ -abstract class CharacterVarying extends CharacterString { - - def isEquivalent(datatype: DataType) = datatype match { - case dt: CharacterVarying => - length == dt.length && encoding == dt.encoding - case _ => - false - } - - def isSubtypeOf(datatype: DataType) = datatype match { - case dt: CharacterVarying => - length >= dt.length && encoding == dt.encoding - case _ => - false - } - - /** The maximal length of the string defined in characters. */ - def length: Int; - - /** A SQL-99 compliant string representation of the type. */ - override def sqlString: java.lang.String = - "CHARACTER VARYING (" + length.toString() + ")"; - -} diff --git a/src/library/scala/dbc/datatype/ExactNumeric.scala b/src/library/scala/dbc/datatype/ExactNumeric.scala deleted file mode 100644 index 331cf866e1..0000000000 --- a/src/library/scala/dbc/datatype/ExactNumeric.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A type category for all SQL types that store constant-precision - * numbers. - */ -abstract class ExactNumeric[Type]( - override val nativeTypeId: DataType.Id -) extends datatype.Numeric[Type](nativeTypeId) { - - def isEquivalent(datatype: DataType) = datatype match { - case dt: ExactNumeric[Type] => - (nativeTypeId == dt.nativeTypeId && - precisionRadix == dt.precisionRadix && - precision == dt.precision && - scale == dt.scale && - signed == dt.signed) - case _ => - false - } - - def isSubtypeOf(datatype: DataType) = datatype match { - case dt: ExactNumeric[Type] => - (nativeTypeId == dt.nativeTypeId && - precisionRadix == dt.precisionRadix && - precision <= dt.precision && - scale <= dt.scale && - signed == dt.signed) - case _ => - false - } - - /** The number of digits used after the decimal point. */ - def scale: Int; - - /** A SQL-99 compliant string representation of the type. - *

Compatibility notice

This method assumes that an integer - * uses 32 bits, a small 16 and a big 64. This is not defined in the - * standard but is usually the case. - */ - override def sqlString: java.lang.String = Tuple3(precisionRadix,precision,scale) match { - case Tuple3(2,16,0) => "SMALLINT" - case Tuple3(2,32,0) => "INTEGER" - case Tuple3(2,64,0) => "BIGINT" - case Tuple3(2,java.lang.Integer.MAX_VALUE,0) => "BIGINT" - case Tuple3(2,p,s) => - throw exception.UnsupportedFeature("SQL-99 does not support an exact numeric type with a binary defined precision other than 16, 32 and 64 bits"); - case Tuple3(10,p,0) => "NUMERIC (" + p.toString() + ")" - case Tuple3(10,p,s) => "NUMERIC (" + p.toString() + ", " + s.toString() + ")" - case Tuple3(pr,_,_) => - throw exception.UnsupportedFeature("SQL-99 does not support the precision of an exact numeric type to be defined in a radix other than 2 or 10"); - } - -} diff --git a/src/library/scala/dbc/datatype/Factory.scala b/src/library/scala/dbc/datatype/Factory.scala deleted file mode 100644 index a4a9672184..0000000000 --- a/src/library/scala/dbc/datatype/Factory.scala +++ /dev/null @@ -1,250 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -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.") - } - } -} diff --git a/src/library/scala/dbc/datatype/Numeric.scala b/src/library/scala/dbc/datatype/Numeric.scala deleted file mode 100644 index d086ecdfff..0000000000 --- a/src/library/scala/dbc/datatype/Numeric.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A type category for all SQL types that store numbers. */ -abstract class Numeric[Type](_nativeTypeId: DataType.Id) extends DataType { - - type NativeType = Type; - val nativeTypeId = _nativeTypeId; - - /** The radix in which the precision (and scale when appliable) is defined. - * ISO-9075 only allows 2 and 10 for this value. - */ - def precisionRadix: Int; - - /** The number of significant digits for that number. */ - def precision: Int; - - /** Whether the number is signed or not. */ - def signed: scala.Boolean; - -} diff --git a/src/library/scala/dbc/datatype/String.scala b/src/library/scala/dbc/datatype/String.scala deleted file mode 100644 index 878bea7061..0000000000 --- a/src/library/scala/dbc/datatype/String.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** A type category for all SQL types that store strings of elements. - */ -abstract class String extends DataType { - - /** The maximal possible length of the string defined in characters. - * This is an implementation-specific value. - */ - def maxLength: Option[Int] = None; - -} diff --git a/src/library/scala/dbc/datatype/Unknown.scala b/src/library/scala/dbc/datatype/Unknown.scala deleted file mode 100644 index 4ab1db59f8..0000000000 --- a/src/library/scala/dbc/datatype/Unknown.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.datatype; - - -/** The SQL type for a truth value. */ -class Unknown extends DataType { - - def isEquivalent(datatype: DataType) = datatype match { - case dt: Unknown => - nativeTypeId == dt.nativeTypeId - case _ => - false - } - - def isSubtypeOf(datatype: DataType) = true; - - type NativeType = Object; - val nativeTypeId = DataType.OBJECT; - - /** A SQL-99 compliant string representation of the type. */ - override def sqlString: java.lang.String = - error("The 'UNKNOWN' data type cannot be represented."); - -} diff --git a/src/library/scala/dbc/exception/IncompatibleSchema.scala b/src/library/scala/dbc/exception/IncompatibleSchema.scala deleted file mode 100644 index bb566ff6f2..0000000000 --- a/src/library/scala/dbc/exception/IncompatibleSchema.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.exception; - - -/** A type category for all SQL types that store constant-precision numbers. */ -case class IncompatibleSchema ( - expectedSchema: List[DataType], - foundSchema: List[DataType] -) extends Exception; diff --git a/src/library/scala/dbc/exception/UnsupportedFeature.scala b/src/library/scala/dbc/exception/UnsupportedFeature.scala deleted file mode 100644 index 073bd8ab32..0000000000 --- a/src/library/scala/dbc/exception/UnsupportedFeature.scala +++ /dev/null @@ -1,16 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.exception; - - -/** A type category for all SQL types that store constant-precision numbers. */ -case class UnsupportedFeature (msg: String) extends Exception; diff --git a/src/library/scala/dbc/result/Field.scala b/src/library/scala/dbc/result/Field.scala deleted file mode 100644 index 75c9898076..0000000000 --- a/src/library/scala/dbc/result/Field.scala +++ /dev/null @@ -1,63 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.result; - - -import scala.dbc.datatype._; -import scala.dbc.value._; - -/** An ISO-9075:2003 (SQL) table field. */ -abstract class Field { - - /** The content (value) of the field. The type of this value is undefined, - * transformation into a useful type will be done by an automatic view - * function defined in the field object. */ - def content: Value; - - final def value[Type <: Value]: Type = - content.asInstanceOf[Type]; - - final def exactNumericValue[NativeType] = - content.asInstanceOf[dbc.value.ExactNumeric[NativeType]]; - - final def approximateNumericValue[NativeType] = - content.asInstanceOf[dbc.value.ApproximateNumeric[NativeType]]; - - final def booleanValue = - content.asInstanceOf[dbc.value.Boolean]; - - final def characterValue = - content.asInstanceOf[dbc.value.Character]; - - final def characterLargeObjectValue = - content.asInstanceOf[dbc.value.CharacterLargeObject]; - - final def characterVaryingValue = - content.asInstanceOf[dbc.value.CharacterVarying]; - - final def unknownValue = - content.asInstanceOf[dbc.value.Unknown]; - - /** The tuple that contains this field. */ - def originatingTuple: Tuple; - - /** The field metadata attached to this field. */ - def metadata: FieldMetadata; - -} - -object Field { - - implicit def fieldToValue (field:Field): Value = field.content; - - -} diff --git a/src/library/scala/dbc/result/FieldMetadata.scala b/src/library/scala/dbc/result/FieldMetadata.scala deleted file mode 100644 index a3117a262c..0000000000 --- a/src/library/scala/dbc/result/FieldMetadata.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.result; - - -/** Informations attached to a field about its content and its relationship to the originating database. */ -abstract class FieldMetadata { - - /** The name of the field. */ - def name: String; - - /** The index of the field in the tuple. */ - def index: Int; - - /** The expected type of the field. This information is used for automatic transformation of the field value into a usable type. */ - def datatype: DataType; - - /** The name of the catalog in the database from which the field originates */ - def catalog: String; - - /** The name of the schema in the database from which the field originates */ - def schema: String; - - /** The name of the table in the database from which the field originates */ - def table: String; - -} diff --git a/src/library/scala/dbc/result/Relation.scala b/src/library/scala/dbc/result/Relation.scala deleted file mode 100644 index 218f8ff825..0000000000 --- a/src/library/scala/dbc/result/Relation.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.result; - - -/** An ISO-9075:2003 (SQL) table. This is equivalent to a relation in the - * relational model. */ -abstract class Relation extends Object with Iterable[Tuple] { - - /** The statement that generated this relation. */ - def statement: scala.dbc.statement.Relation; - - /** A JDBC result containing this relation. */ - protected def sqlResult: java.sql.ResultSet; - - /** A JDBC metadata object attached to the relation. */ - protected def sqlMetadata: java.sql.ResultSetMetaData = sqlResult.getMetaData(); - - /** Metadata about all fields in a tuple of the relation. */ - def metadata: List[FieldMetadata] = - for (val count <- List.range(1, sqlMetadata.getColumnCount()+1)) yield - new FieldMetadata { - val name: String = sqlMetadata.getColumnName(count); - val index: Int = count; - val datatype: DataType = dbc.datatype.Factory.create(sqlMetadata,count); - val catalog: String = sqlMetadata.getCatalogName(count); - val schema: String = sqlMetadata.getSchemaName(count); - val table: String = sqlMetadata.getTableName(count); - } - - /** Metadata about the field at the given index. If there is no such - * field None is returned instead. */ - def metadataFor (index:Int): Option[FieldMetadata] = - try {Some(metadata(index))} catch {case e => None} - - /** Metadata about the field with the given column name. If there is no - * such field, None is returned instead. */ - def metadataFor (name:String): Option[FieldMetadata] = - metadata.find(f=>(f.name==name)); - - /** An iterator on the tuples of the relation. - *

Caution

A Relation only has one single iterator, due to limitations - * in DBMS. This means that if this method is called multiple times, all returned - * iterators will share the same state. */ - def elements: Iterator[Tuple] = new Iterator[Tuple] { - protected val result: java.sql.ResultSet = Relation.this.sqlResult; - def hasNext: Boolean = !(result.isLast()); - def next: Tuple = { - if (result.next()) { - new Tuple { - val me = this; - val originatingRelation = Relation.this; - val fields: List[Field] = for (val fieldMetadata <- metadata) yield - new Field { - val metadata = fieldMetadata; - val content = dbc.value.Factory.create(result,metadata.index,metadata.datatype); - val originatingTuple = me; - } - } - } else error("next on empty iterator") - } - } -} diff --git a/src/library/scala/dbc/result/Status.scala b/src/library/scala/dbc/result/Status.scala deleted file mode 100644 index c8a2370819..0000000000 --- a/src/library/scala/dbc/result/Status.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.result; - - -import scala.dbc.datatype._; - -/** An object containing the status of a query */ -abstract class Status[ResultType] { - - /** The statement that generated this status result. */ - def statement: scala.dbc.statement.Statement; - - /** The number of elements modified or added by this statement. */ - def touchedCount: Option[Int]; - - def result: ResultType; - -} diff --git a/src/library/scala/dbc/result/Tuple.scala b/src/library/scala/dbc/result/Tuple.scala deleted file mode 100644 index 6ed8955951..0000000000 --- a/src/library/scala/dbc/result/Tuple.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.result; - - -/** An ISO-9075:2003 (SQL) table row. This is equivalent to a tuple in the relational model. */ -abstract class Tuple { - - /** All the fields contained in the tuple. */ - def fields: List[Field]; - - /** The relation that contains the tuple. */ - def originatingRelation: Relation; - - /** The field at the given index. If there is no such field (that is the index is out of bounds), None is returned instead. */ - def apply (index:Int): Field = - try { - fields(index) - } catch { - case e => - throw new java.lang.IndexOutOfBoundsException("Field at index "+index+" does not exist in relation"); - } - - /** The field with the given column name. If there is no such field, None is returned instead. */ - def apply (name:String): Field = { - def findField (fields: List[Field], name:String): Field = fields match { - case Nil => throw new java.lang.IndexOutOfBoundsException("Field '"+name+"' does not exist in relation") - case field :: _ if (field.metadata.name == name) => field - case field :: fields => findField (fields, name) - } - findField (fields, name); - } -} diff --git a/src/library/scala/dbc/statement/AccessMode.scala b/src/library/scala/dbc/statement/AccessMode.scala deleted file mode 100644 index 16f778b35e..0000000000 --- a/src/library/scala/dbc/statement/AccessMode.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -abstract class AccessMode { - def sqlString: String; -} - -object AccessMode { - case object ReadOnly extends AccessMode { - def sqlString = "READ ONLY"; - } - case object ReadWrite extends AccessMode { - def sqlString = "READ WRITE" - } -} diff --git a/src/library/scala/dbc/statement/DerivedColumn.scala b/src/library/scala/dbc/statement/DerivedColumn.scala deleted file mode 100644 index 653ce75698..0000000000 --- a/src/library/scala/dbc/statement/DerivedColumn.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -abstract class DerivedColumn { - - /** The value for the column. This value can be of any type but must be - * calculated from fields that appear in a relation that takes part - * in the query. */ - def valueExpression: Expression; - - /** A new name for this field. This name must be unique for the query in - * which the column takes part. */ - def asClause: Option[String]; - - /** A SQL-99 compliant string representation of the derived column - * sub-statement. This only has a meaning inside a select statement. */ - def sqlString: String = ( - valueExpression.sqlInnerString + - (asClause match { - case None => "" - case Some(ac) => " AS " + ac - }) - ); - -} diff --git a/src/library/scala/dbc/statement/Expression.scala b/src/library/scala/dbc/statement/Expression.scala deleted file mode 100644 index 6243564311..0000000000 --- a/src/library/scala/dbc/statement/Expression.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** An expression that calculates some value from fields. */ -abstract class Expression extends Relation { - - def fieldTypes: List[DataType] = Nil; - - /** A SQL-99 compliant string representation of the expression. */ - def sqlString: String = { - "SELECT " + sqlInnerString - } - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String; - -} diff --git a/src/library/scala/dbc/statement/Insert.scala b/src/library/scala/dbc/statement/Insert.scala deleted file mode 100644 index 19d236d2fb..0000000000 --- a/src/library/scala/dbc/statement/Insert.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -import scala.dbc.statement.expression._; - -/** An insertion of values into a table. */ -case class Insert ( - insertionTarget: String, - insertionData: InsertionData -) extends Status { - - /** A SQL-99 compliant string representation of the select statement. */ - def sqlString: String = ( - "INSERT INTO " + - insertionTarget + - " " + insertionData.sqlString - ); - - /** The name of the table where the data should be added. */ - //def insertionTarget: String; - - /** The data that will be added tot he table. */ - //def insertionData: InsertionData; - -} diff --git a/src/library/scala/dbc/statement/InsertionData.scala b/src/library/scala/dbc/statement/InsertionData.scala deleted file mode 100644 index c36dde0fb7..0000000000 --- a/src/library/scala/dbc/statement/InsertionData.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -import scala.dbc.statement.expression._; - -/** Data to be inserted into a table in an Insert. */ -abstract class InsertionData { - def sqlString: String; -} - -object InsertionData { - /** Insertion of data resulting from a query on the database. */ - case class Subquery (query:Relation) extends InsertionData { - def sqlString = query.sqlString; - } - /** Insertion of data as explicitly defined values. */ - case class Constructor ( - columnNames:Option[List[String]], - columnValues:List[Expression] - ) extends InsertionData { - def sqlString = ( - (columnNames match { - case None => "" - case Some(cn) => cn.mkString(" (",", ",")") - }) + - " VALUES" + - columnValues.map(e=>e.sqlInnerString).mkString(" (",", ",")") - ) - } -} diff --git a/src/library/scala/dbc/statement/IsolationLevel.scala b/src/library/scala/dbc/statement/IsolationLevel.scala deleted file mode 100644 index 4d1d2ef2de..0000000000 --- a/src/library/scala/dbc/statement/IsolationLevel.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -abstract class IsolationLevel { - def sqlString: String; -} - -object IsolationLevel { - case object ReadUncommitted extends IsolationLevel { - def sqlString = "ISOLATION LEVEL READ UNCOMMITTED" - } - case object ReadCommitted extends IsolationLevel { - def sqlString = "ISOLATION LEVEL READ COMMITTED" - } - case object RepeatableRead extends IsolationLevel { - def sqlString = "ISOLATION LEVEL REPEATABLE READ" - } - case object Serializable extends IsolationLevel { - def sqlString = "ISOLATION LEVEL SERIALIZABLE" - } -} diff --git a/src/library/scala/dbc/statement/JoinType.scala b/src/library/scala/dbc/statement/JoinType.scala deleted file mode 100644 index 77befa5607..0000000000 --- a/src/library/scala/dbc/statement/JoinType.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A join behaviour in a Jointure. */ -abstract class JoinType { - /** A SQL-99 string representation of the join behaviour. */ - def sqlString: String; -} - -object JoinType { - /** A join behaviour where a joined tuple is created only when a - * corresponding tuple exists in both original relations. */ - case object Inner extends JoinType { - val sqlString = "INNER JOIN" - } - /** A join behaviour family where a joined tuple is created even when a - * tuple has no corresponding tuple in the other relation. The fields - * populated by values of the other tuple will receive the NULL value. - */ - abstract class Outer extends JoinType; - object Outer { - /** An outer join behaviour where there will be at least on tuple for - * every tuple in the left relation. */ - case object Left extends Outer { - val sqlString = "LEFT OUTER JOIN" - } - /** An outer join behaviour where there will be at least on tuple for - * every tuple in the right relation. */ - case object Right extends Outer { - val sqlString = "RIGHT OUTER JOIN" - } - /** An outer join behaviour where there will be at least on tuple for - * every tuple in both right and left relations. */ - case object Full extends Outer { - val sqlString = "FULL OUTER JOIN" - } - } -} diff --git a/src/library/scala/dbc/statement/Jointure.scala b/src/library/scala/dbc/statement/Jointure.scala deleted file mode 100644 index 471626ab05..0000000000 --- a/src/library/scala/dbc/statement/Jointure.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A jointure between two relations. */ -abstract class Jointure extends Relation { - - /** The relation on the left part of the join. */ - def leftRelation: Relation; - - /** The relation on the right part of the join. */ - def rightRelation: Relation; - - /** The type of the jointure. */ - def joinType: JoinType; - - /** The condition on which the jointure needs be done. */ - def joinCondition: Option[Expression]; - - /** A SQL-99 compliant string representation of the relation statement. */ - def sqlString: String = { - "SELECT * FROM " + sqlInnerString - } - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside a query. */ - def sqlInnerString: String = ( - leftRelation.sqlInnerString + " " + - joinType.sqlString + " " + - rightRelation.sqlInnerString + - (joinCondition match { - case Some(jc) => jc.sqlString - case None => "" - }) - ) - -} diff --git a/src/library/scala/dbc/statement/Relation.scala b/src/library/scala/dbc/statement/Relation.scala deleted file mode 100644 index d6e86b39a5..0000000000 --- a/src/library/scala/dbc/statement/Relation.scala +++ /dev/null @@ -1,55 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A statement that returns a relation. */ -abstract class Relation extends Statement { - - def isCompatibleType: (DataType,DataType)=>Boolean = - ((dt,wdt)=>dt.isSubtypeOf(wdt)); - - def typeCheck (relation: result.Relation): Unit = { - val sameType: Boolean = ( - relation.metadata.length == fieldTypes.length && - (relation.metadata.zip(fieldTypes).forall({case Pair(field,expectedType) => - isCompatibleType(field.datatype, expectedType)})) - ); - if (!sameType) - throw new exception.IncompatibleSchema(fieldTypes,relation.metadata.map(field=>field.datatype)); - } - - def fieldTypes: List[DataType]; - - def sqlTypeString: String = - if (fieldTypes.isEmpty) - "UNTYPED" - else - fieldTypes.map(dt=>dt.sqlString).mkString("RELATION (",", ",")"); - - /** A SQL-99 compliant string representation of the statement. */ - def sqlString: String; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String; - - /** Executes the statement on the given database. */ - def execute (database: scala.dbc.Database): scala.dbc.result.Relation = { - database.executeStatement(this); - } - - def execute (database:scala.dbc.Database, debug:Boolean): scala.dbc.result.Relation = { - database.executeStatement(this,debug); - } - -} diff --git a/src/library/scala/dbc/statement/Select.scala b/src/library/scala/dbc/statement/Select.scala deleted file mode 100644 index 4da6b9e571..0000000000 --- a/src/library/scala/dbc/statement/Select.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A statement that when executed on a database will return a relation. - * The returned relation will be a subset of a table in the database or - * a jointure between such subsets. */ -abstract class Select extends Relation { - - /** Defines if duplicated tuples should be removed from the returned - * relation.

Compatibility notice

Some DBMS (PostgreSQL) allow - * uniqueness constrains on an arbitrary field instead of the entire - * tuple. */ - def setQuantifier: Option[SetQuantifier]; - - /** Defines the output fields that a tuple in the returned relation will - * contain, and their content with respect to the tables in the - * database. If the fields are not specified (that is the list is - * empty), all possible input fields will be returned.

Compatibility - * notice

SQL's qualified asterisk select sublist is not - * available. */ - def selectList: List[DerivedColumn]; - - /** Defines the relations from which the query will obtain its data.*/ - def fromClause: List[Relation]; - - /** Defines condition that must be true in the returned relation's tuples. - * This value expression must return a boolean or boolean-compatible - * value. This condition is applied before any GROUP BY clause. */ - def whereClause: Option[Expression]; - - /** Defines the grouping of the returned relation's tuples. One tuple is - * returned for every group. The value of selectList must - * use aggregate functions for calculation. */ - def groupByClause: Option[List[Expression]]; - - /** Defines conditions that must be true in the returned relation's tuples. - * The value expression must return a boolean can only refer to fields - * that are grouped or to any field from inside an aggregate function. */ - def havingClause: Option[Expression]; - - /* def windowClause: Option[_]; */ - - /** A SQL-99 compliant string representation of the select statement. */ - def sqlString: String = ( - "SELECT" + - (setQuantifier match { - case None => "" - case Some(sq) => " " + sq.sqlString - }) + - (selectList match { - case Nil => " *" - case _ => (" " + selectList.tail.foldLeft(selectList.head.sqlString) - ((name:String, dc:DerivedColumn) => name + ", " + dc.sqlString)) - }) + - (fromClause match { - case Nil => error("Empty from clause is not allowed") - case _ => (" FROM " + fromClause.tail.foldLeft(fromClause.head.sqlInnerString) - ((name:String, rel:Relation) => name + ", " + rel.sqlInnerString)) - }) + - (whereClause match { - case None => "" - case Some(expr) => " WHERE " + expr.sqlInnerString - }) + - (groupByClause match { - case None => "" - case Some(gbl) => gbl match { - case Nil => error("Empty group by clause is not allowed") - case _ => - (" GROUP BY " + - gbl.tail.foldLeft(gbl.head.sqlInnerString) - ((name:String, gb) => name + ", " + gb.sqlInnerString)) - } - }) + - (havingClause match { - case None => "" - case Some(expr) => " HAVING " + expr.sqlString - }) - ); - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside a query. */ - def sqlInnerString: String = "("+sqlString+")"; - -} diff --git a/src/library/scala/dbc/statement/SetClause.scala b/src/library/scala/dbc/statement/SetClause.scala deleted file mode 100644 index e6a55ae846..0000000000 --- a/src/library/scala/dbc/statement/SetClause.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -import scala.dbc.statement.expression._; - -/** Data to be inserted into a table in an Insert. */ -case class SetClause (name:String, expr:Expression) { - val value: Pair[String,Expression] = Pair(name,expr); - def sqlString: String = - value._1 + " = " + value._2.sqlInnerString; -} diff --git a/src/library/scala/dbc/statement/SetQuantifier.scala b/src/library/scala/dbc/statement/SetQuantifier.scala deleted file mode 100644 index ad7c2238c8..0000000000 --- a/src/library/scala/dbc/statement/SetQuantifier.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A set quantifier that defines the collection type of a relation. */ -abstract class SetQuantifier { - /** A SQL-99 compliant string representation of the set quantifier. */ - def sqlString: String; -} - -object SetQuantifier { - /** A set quantifier that defines a relation as being a bag. That means - * that duplicates are allowed. */ - case object AllTuples extends SetQuantifier { - /** A SQL-99 compliant string representation of the set quantifier. */ - def sqlString: String = "ALL"; - } - /** A set quantifier that defines a relation as being a set. That means - * that duplicates are not allowed and will be pruned. */ - case object DistinctTuples extends SetQuantifier { - /** A SQL-99 compliant string representation of the set quantifier. */ - def sqlString: String = "DISTINCT"; - } -} diff --git a/src/library/scala/dbc/statement/Statement.scala b/src/library/scala/dbc/statement/Statement.scala deleted file mode 100644 index 5c78b075b7..0000000000 --- a/src/library/scala/dbc/statement/Statement.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** An ISO-9075:2003 (SQL) statement. */ -abstract class Statement { - -} diff --git a/src/library/scala/dbc/statement/Status.scala b/src/library/scala/dbc/statement/Status.scala deleted file mode 100644 index 3065ec5f7a..0000000000 --- a/src/library/scala/dbc/statement/Status.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A statement that changes the status of the database. */ -abstract class Status extends Statement { - - /** A SQL-99 compliant string representation of the statement. */ - def sqlString: String; - - /** Executes the statement on the given database. */ - def execute (database: scala.dbc.Database): scala.dbc.result.Status[Unit] = { - database.executeStatement(this); - } - - def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[Unit] = { - database.executeStatement(this,debug); - } - -} diff --git a/src/library/scala/dbc/statement/Table.scala b/src/library/scala/dbc/statement/Table.scala deleted file mode 100644 index 17015a6c73..0000000000 --- a/src/library/scala/dbc/statement/Table.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A reference to a table in the database. - * @author Gilles Dubochet - * @version 1.0 */ -abstract class Table extends Relation { - - /** The name of the table in the database. */ - def tableName: String; - - /** The name that the table will be called in the enclosing statement. */ - def tableRename: Option[String]; - - /** A SQL-99 compliant string representation of the relation statement. */ - def sqlString: String = { - "SELECT * FROM " + tableName - } - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside a query. */ - def sqlInnerString: String = ( - tableName + - (tableRename match { - case None => "" - case Some(rename) => " AS " + rename - }) - ) -} diff --git a/src/library/scala/dbc/statement/Transaction.scala b/src/library/scala/dbc/statement/Transaction.scala deleted file mode 100644 index a802aa82fa..0000000000 --- a/src/library/scala/dbc/statement/Transaction.scala +++ /dev/null @@ -1,55 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -/** A statement that changes the status of the database. */ -case class Transaction [ResultType] ( - transactionBody: (scala.dbc.Database=>ResultType), - accessMode: Option[AccessMode], - isolationLevel: Option[IsolationLevel] -) extends Statement { - - /** A SQL-99 compliant string representation of the statement. */ - def sqlStartString: String = ( - "START TRANSACTION" + - (Pair(accessMode,isolationLevel) match { - case Pair(None,None) => "" - case Pair(Some(am),None) => " " + am.sqlString - case Pair(None,Some(il)) => " " + il.sqlString - case Pair(Some(am),Some(il)) => " " + am.sqlString + ", " + il.sqlString - }) - ); - - def sqlCommitString: String = { - "COMMIT" - } - - def sqlAbortString: String = { - "ROLLBACK" - } - - //def transactionBody: (()=>Unit); - - //def accessMode: Option[AccessMode]; - - //def isolationLevel: Option[IsolationLevel]; - - def execute (database: scala.dbc.Database): scala.dbc.result.Status[ResultType] = { - database.executeStatement(this); - } - - def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[ResultType] = { - database.executeStatement(this,debug); - } - -} diff --git a/src/library/scala/dbc/statement/Update.scala b/src/library/scala/dbc/statement/Update.scala deleted file mode 100644 index cf8a3c9b6f..0000000000 --- a/src/library/scala/dbc/statement/Update.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement; - - -import scala.dbc.statement.expression._; - -/** An update of the state of a table. */ -case class Update ( - updateTarget: String, - setClauses: List[SetClause], - whereClause: Option[Expression] -) extends Status { - - - /** A SQL-99 compliant string representation of the select statement. */ - def sqlString: String = ( - "UPDATE " + - updateTarget + - " SET " + setClauses.map(sc=>sc.sqlString).mkString("",", ","") + - (whereClause match { - case None => "" - case Some(expr) => " WHERE " + expr.sqlString - }) - ); - - /** The name of the table that should be updated. */ - //def updateTarget: String; - - /** The data that will be added tot he table. */ - //def setClauses: List[SetClause]; - - /** Defines condition that must be true in the tuples that will be updated. - * This value expression must return a boolean or boolean-compatible - * value. */ - //def whereClause: Option[scala.dbc.statement.expression.Expression]; - -} diff --git a/src/library/scala/dbc/statement/expression/Aggregate.scala b/src/library/scala/dbc/statement/expression/Aggregate.scala deleted file mode 100644 index 3a93864475..0000000000 --- a/src/library/scala/dbc/statement/expression/Aggregate.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class Aggregate extends Expression { - - def aggregateName: String; - - def setFunction: SetFunction; - - def filterClause: Option[Expression]; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = ( - aggregateName + - "(" + setFunction.sqlString + ")" + - (filterClause match { - case None => "" - case Some(fc) => " FILTER (WHERE " + fc.sqlString + ")" - }) - ) - -} diff --git a/src/library/scala/dbc/statement/expression/BinaryOperator.scala b/src/library/scala/dbc/statement/expression/BinaryOperator.scala deleted file mode 100644 index 3b3ac6f0fe..0000000000 --- a/src/library/scala/dbc/statement/expression/BinaryOperator.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class BinaryOperator extends Expression { - - /** The name of the operator. */ - def operator: String; - - /** The expression applied on the left of the operator. */ - def leftOperand: Expression; - - /** The expression applied on the right of the operator. */ - def rightOperand: Expression; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = { - leftOperand.sqlInnerString + " " + operator + " " + rightOperand.sqlInnerString - } - -} diff --git a/src/library/scala/dbc/statement/expression/Constant.scala b/src/library/scala/dbc/statement/expression/Constant.scala deleted file mode 100644 index 6ee665c97d..0000000000 --- a/src/library/scala/dbc/statement/expression/Constant.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class Constant extends Expression { - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = constantValue.sqlString; - - /** The value of the constant. */ - def constantValue: Value; -} diff --git a/src/library/scala/dbc/statement/expression/Default.scala b/src/library/scala/dbc/statement/expression/Default.scala deleted file mode 100644 index 7d03872ab5..0000000000 --- a/src/library/scala/dbc/statement/expression/Default.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -case object Default extends Expression { - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = "DEFAULT"; - -} diff --git a/src/library/scala/dbc/statement/expression/Field.scala b/src/library/scala/dbc/statement/expression/Field.scala deleted file mode 100644 index b005f024bd..0000000000 --- a/src/library/scala/dbc/statement/expression/Field.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class Field extends Expression { - - /** The name of the schema in the database where the field is located. */ - def schemaName: Option[String] = None; - - /** The name of the table in the database where the field is located. */ - def tableName: Option[String]; - - /** The name of the field in the database. */ - def fieldName: String; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = ( - (schemaName match { - case None => "" - case Some(sn) => sn + "." - }) + - (tableName match { - case None => "" - case Some(tn) => tn + "." - }) + fieldName - ) - -} diff --git a/src/library/scala/dbc/statement/expression/FunctionCall.scala b/src/library/scala/dbc/statement/expression/FunctionCall.scala deleted file mode 100644 index bfee8701dd..0000000000 --- a/src/library/scala/dbc/statement/expression/FunctionCall.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -case class FunctionCall ( - functionName: String, - arguments: List[Expression] -) extends Expression { - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = { - functionName + "(" + arguments.mkString("",", ","") + ")" - } - - /** The name of the function to call. */ - //def functionName: String; - - /** A list of all argument expressions to pass to the function, in order. */ - //def arguments: List[Expression]; - -} diff --git a/src/library/scala/dbc/statement/expression/Select.scala b/src/library/scala/dbc/statement/expression/Select.scala deleted file mode 100644 index 44c14e8474..0000000000 --- a/src/library/scala/dbc/statement/expression/Select.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class Select extends Expression { - - /** The actual select statement */ - def selectStatement: statement.Select; - - /** A SQL-99 compliant string representation of the expression. */ - override def sqlString: String = selectStatement.sqlString; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = "("+selectStatement.sqlString+")"; - -} diff --git a/src/library/scala/dbc/statement/expression/SetFunction.scala b/src/library/scala/dbc/statement/expression/SetFunction.scala deleted file mode 100644 index b58850df12..0000000000 --- a/src/library/scala/dbc/statement/expression/SetFunction.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class SetFunction { - /** A SQL-99 compliant string representation of the set quantifier. */ - def sqlString: String; -} - -object SetFunction { - abstract class Asterisk extends SetFunction { - def sqlString = "(*)"; - } - abstract class General extends SetFunction { - def setQuantifier: Option[SetQuantifier]; - def valueExpression: Expression; - def sqlString = ( - "(" + - (setQuantifier match { - case None => "" - case Some(sq) => sq.sqlString + " " - }) + - valueExpression.sqlString + ")" - ); - } - abstract class Binary extends SetFunction { - def sqlString = error("Binary set function is not supported yet."); - } -} diff --git a/src/library/scala/dbc/statement/expression/TypeCast.scala b/src/library/scala/dbc/statement/expression/TypeCast.scala deleted file mode 100644 index 5c9cbddebe..0000000000 --- a/src/library/scala/dbc/statement/expression/TypeCast.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -case class TypeCast ( - expression: Expression, - castType: DataType -) extends Expression { - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = { - "CAST (" + expression.sqlInnerString + " AS " + castType.sqlString + ")"; - } - - /** The expression that will be casted. */ - //def expression: Expression; - - /** The type to which to cast. */ - //def castType: scala.dbc.datatype.DataType; -} diff --git a/src/library/scala/dbc/statement/expression/UnaryOperator.scala b/src/library/scala/dbc/statement/expression/UnaryOperator.scala deleted file mode 100644 index 9068595f77..0000000000 --- a/src/library/scala/dbc/statement/expression/UnaryOperator.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.statement.expression; - - -abstract class UnaryOperator extends Expression { - - /** The name of the operator */ - def operator: String; - - /** Whether the operator comes before the operand or not. */ - def operatorIsLeft: Boolean; - - /** The operand applied to the operator. */ - def operand: Expression; - - /** A SQL-99 compliant string representation of the relation sub- - * statement. This only has a meaning inside another statement. */ - def sqlInnerString: String = operatorIsLeft match { - case true => operator + " " + operand.sqlInnerString; - case false => operand.sqlInnerString + " " + operator; - } -} diff --git a/src/library/scala/dbc/syntax/DataTypeUtil.scala b/src/library/scala/dbc/syntax/DataTypeUtil.scala deleted file mode 100644 index c42efb082f..0000000000 --- a/src/library/scala/dbc/syntax/DataTypeUtil.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.syntax; - - -import java.math.BigDecimal; -import java.math.BigInteger; - -object DataTypeUtil { - - final val java_lang_Integer_SIZE = 32; - final val java_lang_Long_SIZE = 64; - - def boolean = new datatype.Boolean; - def tinyint = new datatype.ExactNumeric[Byte](dbc.DataType.BYTE) { - val precisionRadix = 2; - val precision = 8; - val signed = true; - val scale = 0; - } - def smallint = new datatype.ExactNumeric[Short](dbc.DataType.SHORT) { - val precisionRadix = 2; - val precision = 16; - val signed = true; - val scale = 0; - } - def integer = new datatype.ExactNumeric[Int](dbc.DataType.INT) { - val precisionRadix = 2; - val precision = 32; - val signed = true; - val scale = 0; - } - def bigint = new datatype.ExactNumeric[Long](dbc.DataType.LONG) { - val precisionRadix = 2; - val precision = 64; - val signed = true; - val scale = 0; - } - def numeric (_precision:Int): DataType = numeric(_precision,0); - def numeric (_precision:Int, _scale:Int): DataType = - Pair(datatype.Factory.bytePrecision(_precision,true,true),_scale == 0) match { - case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) => - new datatype.ExactNumeric[Int](DataType.INT) { - val precisionRadix = 10; - val precision = _precision; - val signed = true; - val scale = 0; - } - case Pair(bp,true) if (bp <= java_lang_Long_SIZE) => - new datatype.ExactNumeric[Long](DataType.LONG) { - val precisionRadix = 10; - val precision = _precision; - val signed = true; - val scale = 0; - } - case Pair(_,true) => - new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) { - val precisionRadix = 10; - val precision = _precision; - val signed = true; - val scale = 0; - } - case Pair(_,false) => - new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) { - val precisionRadix = 10; - val precision = _precision; - val signed = true; - val scale = _scale; - } - } - def real = new datatype.ApproximateNumeric[Float](DataType.FLOAT) { - val precisionRadix = 2; - val precision = 64; - val signed = true; - } - def doublePrecision = new datatype.ApproximateNumeric[Double](DataType.DOUBLE) { - val precisionRadix = 2; - val precision = 128; - val signed = true; - } - def character (_length: Int) = new datatype.Character { - val length = _length; - } - def characterVarying (_length: Int) = new datatype.CharacterVarying { - def length = _length; - } - def characterLargeObject = new datatype.CharacterLargeObject; - -} diff --git a/src/library/scala/dbc/syntax/Database.scala b/src/library/scala/dbc/syntax/Database.scala deleted file mode 100644 index 31a04b1129..0000000000 --- a/src/library/scala/dbc/syntax/Database.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.syntax; - - -import java.net.URI; - -object Database { - - def database (server:String, username:String, password:String): dbc.Database = { - val uri = new URI(server); - // Java 1.5 if (uri.toString().contains("postgres")) { - if (uri.toString().indexOf("postgres") != -1) { - new dbc.Database(new vendor.PostgreSQL { - val uri = new URI(server); - val user = username; - val pass = password; - }) - } else { - throw new Exception("No DBMS vendor support could be found for the given URI"); - } - } - -} diff --git a/src/library/scala/dbc/syntax/Statement.scala b/src/library/scala/dbc/syntax/Statement.scala deleted file mode 100644 index 027a05b8fc..0000000000 --- a/src/library/scala/dbc/syntax/Statement.scala +++ /dev/null @@ -1,274 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.syntax; - - -import java.math.BigDecimal; -import java.math.BigInteger; - -import StatementExpression._; - -/* - -ASSUMPTIONS: - -IMPROVABLE: -For type safety, all types must be defined. If one is missing, none is taken into account. -It is possible to redefine many types or renamings for a field, in that case, - only the last one is taken into account ("a" as "b" as "c" of boolean as "e" of integer - is equivalent to "a" as "e" of integer). - -FIXED: - -*/ - -object Statement { - - // SELECT ZYGOTE ... - - def select: SelectZygote = new SelectZygote { - val setQuantifier = None; - } - def selectBag: SelectZygote = new SelectZygote { - val setQuantifier = Some(statement.SetQuantifier.AllTuples); - } - def selectSet: SelectZygote = new SelectZygote { - val setQuantifier = Some(statement.SetQuantifier.DistinctTuples); - } - - abstract class SelectZygote { - def setQuantifier: Option[statement.SetQuantifier]; - def fields (sdc:SelectDerivedColumns): SelectOf = new SelectOf { - val setQuantifier = SelectZygote.this.setQuantifier; - val selectList = sdc.selectList; - val selectTypes = sdc.selectTypes; - } - } - - abstract class SelectDerivedField { - def fieldValue: StatementField; - def fieldRename: Option[String] = {val x = None; x} - def fieldType: Option[dbc.DataType] = {val x = None; x} - def as (rename:String): SelectDerivedField = new SelectDerivedField { - val fieldValue = SelectDerivedField.this.fieldValue; - override val fieldRename = Some(rename); - override val fieldType = SelectDerivedField.this.fieldType; - } - def of (datatype:dbc.DataType): SelectDerivedField = new SelectDerivedField { - val fieldValue = SelectDerivedField.this.fieldValue; - override val fieldRename = SelectDerivedField.this.fieldRename; - override val fieldType = Some(datatype); - } - } - - implicit def statementFieldToSelectDerivedField (fv:StatementField): SelectDerivedField = new SelectDerivedField { - val fieldValue = fv; - } - - implicit def stringToSelectDerivedField (fv:String): SelectDerivedField = new SelectDerivedField { - val fieldValue: StatementField = StatementExpression.stringToStatementField(fv); - } - - abstract class SelectDerivedColumns { - def selectList: List[statement.DerivedColumn]; - def selectTypes: List[DataType]; - def and (sdc:SelectDerivedColumns): SelectDerivedColumns = new SelectDerivedColumns { - val selectList = SelectDerivedColumns.this.selectList ::: sdc.selectList; - val selectTypes = - if (SelectDerivedColumns.this.selectTypes.isEmpty | sdc.selectTypes.isEmpty) - Nil - else - SelectDerivedColumns.this.selectTypes ::: sdc.selectTypes; - } - } - - implicit def selectDerivedFieldToSelectDerivedColumns (sdf:SelectDerivedField): SelectDerivedColumns = new SelectDerivedColumns { - val selectList = List(new statement.DerivedColumn { - val valueExpression = sdf.fieldValue.toStatement; - val asClause = sdf.fieldRename; - }); - val selectTypes = if (sdf.fieldType.isEmpty) Nil else List(sdf.fieldType.get); - } - - implicit def stringToSelectDerivedColumns (sdfs:String): SelectDerivedColumns = { - val sdf: SelectDerivedField = sdfs; - selectDerivedFieldToSelectDerivedColumns(sdf); - } - - // SELECT OF ... - - abstract class SelectOf { - def setQuantifier: Option[statement.SetQuantifier]; - def selectList: List[statement.DerivedColumn]; - def selectTypes: List[DataType]; - def from (sst:SelectSourceTables): SelectBeyond = new SelectBeyond { - val setQuantifier = SelectOf.this.setQuantifier; - val selectList = SelectOf.this.selectList; - val selectTypes = SelectOf.this.selectTypes; - val fromClause = sst.fromClause; - val whereClause = None; - val groupByClause = None; - val havingClause = None; - } - } - - abstract class SelectSourceTable { - def fromRelation: statement.Relation; - def innerJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { - val fromRelation = new statement.Jointure { - val leftRelation = SelectSourceTable.this.fromRelation; - val rightRelation = sst.fromRelation; - val joinType = statement.JoinType.Inner; - val joinCondition = None; - val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; - } - } - def leftOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { - val fromRelation = new statement.Jointure { - val leftRelation = SelectSourceTable.this.fromRelation; - val rightRelation = sst.fromRelation; - val joinType = statement.JoinType.Outer.Left; - val joinCondition = None; - val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; - } - } - def rightOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { - val fromRelation = new statement.Jointure { - val leftRelation = SelectSourceTable.this.fromRelation; - val rightRelation = sst.fromRelation; - val joinType = statement.JoinType.Outer.Right; - val joinCondition = None; - val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; - } - } - def fullOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable { - val fromRelation = new statement.Jointure { - val leftRelation = SelectSourceTable.this.fromRelation; - val rightRelation = sst.fromRelation; - val joinType = statement.JoinType.Outer.Full; - val joinCondition = None; - val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes; - } - } - } - - implicit def stringToSelectSourceTable (sct:String): SelectSourceTable = new SelectSourceTable { - val fromRelation = new statement.Table { - val tableName = sct; - val tableRename = None; - val fieldTypes = Nil; - } - } - - implicit def selectToSelectSourceTable (sct:statement.Select): SelectSourceTable = new SelectSourceTable { - val fromRelation = sct; - } - - abstract class SelectSourceTables { - def fromClause: List[statement.Relation]; - def join (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables { - val fromClause = SelectSourceTables.this.fromClause ::: List(sct.fromRelation); - } - } - - implicit def stringToSelectSourceTables (sct:String): SelectSourceTables = new SelectSourceTables { - val fromClause = List(new statement.Table { - val tableName = sct; - val tableRename = None; - val fieldTypes = Nil; - }); - } - - implicit def selectToSelectSourceTables (sct:statement.Select): SelectSourceTables = new SelectSourceTables { - val fromClause = List(sct); - } - - implicit def selectSourceTableToSelectSourceTables (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables { - val fromClause = List(sct.fromRelation); - } - - // SELECT BEYOND ... - - abstract class SelectBeyond { - def setQuantifier: Option[statement.SetQuantifier]; - def selectList: List[statement.DerivedColumn]; - def selectTypes: List[DataType]; - def fromClause: List[statement.Relation]; - def whereClause: Option[statement.Expression]; - def groupByClause: Option[List[statement.Expression]]; - def havingClause: Option[statement.Expression]; - def where (se:StatementExpression): SelectBeyond = new SelectBeyond { - val setQuantifier = SelectBeyond.this.setQuantifier; - val selectList = SelectBeyond.this.selectList; - val selectTypes = SelectBeyond.this.selectTypes; - val fromClause = SelectBeyond.this.fromClause; - val whereClause = Some(se.toStatement); - val groupByClause = SelectBeyond.this.groupByClause; - val havingClause = SelectBeyond.this.havingClause; - } - def groupBy (sgb:SelectGroupBy): SelectBeyond = new SelectBeyond { - val setQuantifier = SelectBeyond.this.setQuantifier; - val selectList = SelectBeyond.this.selectList; - val selectTypes = SelectBeyond.this.selectTypes; - val fromClause = SelectBeyond.this.fromClause; - val whereClause = SelectBeyond.this.whereClause; - val groupByClause = Some(sgb.groupByClause); - val havingClause = SelectBeyond.this.havingClause; - } - def having (se:StatementExpression): SelectBeyond = new SelectBeyond { - val setQuantifier = SelectBeyond.this.setQuantifier; - val selectList = SelectBeyond.this.selectList; - val selectTypes = SelectBeyond.this.selectTypes; - val fromClause = SelectBeyond.this.fromClause; - val whereClause = SelectBeyond.this.whereClause; - val groupByClause = SelectBeyond.this.groupByClause; - val havingClause = Some(se.toStatement); - } - } - - implicit def selectBeyondToStatementSelect (sb:SelectBeyond): statement.Select = new statement.Select { - val setQuantifier = sb.setQuantifier; - val selectList = sb.selectList; - val fromClause = sb.fromClause; - val whereClause = sb.whereClause; - val groupByClause = sb.groupByClause; - val havingClause = sb.havingClause; - val fieldTypes = sb.selectTypes; - } - - abstract class SelectGroupBy { - def groupByClause: List[statement.Expression]; - def then (se:StatementExpression): SelectGroupBy = new SelectGroupBy { - val groupByClause = - SelectGroupBy.this.groupByClause ::: List(se.toStatement); - } - def then (se:String): SelectGroupBy = new SelectGroupBy { - val groupByClause = - SelectGroupBy.this.groupByClause ::: List(new statement.expression.Field { - val tableName = None; - val fieldName = se; - }); - } - } - - implicit def statementExpressionToSelectGroupBy (se:StatementExpression): SelectGroupBy = new SelectGroupBy { - val groupByClause = List(se.toStatement); - } - - implicit def stringToSelectGroupBy (se:String): SelectGroupBy = new SelectGroupBy { - val groupByClause = List(new statement.expression.Field { - val tableName = None; - val fieldName = se; - }); - } - -} diff --git a/src/library/scala/dbc/syntax/StatementExpression.scala b/src/library/scala/dbc/syntax/StatementExpression.scala deleted file mode 100644 index 78c75ae174..0000000000 --- a/src/library/scala/dbc/syntax/StatementExpression.scala +++ /dev/null @@ -1,221 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.syntax; - - -import java.math.BigDecimal; -import java.math.BigInteger; - -abstract class StatementExpression { - - def toStatement: statement.Expression; - - def and (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "AND"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def or (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "OR"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def == (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "="; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def < (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "<"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def > (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = ">"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def <= (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "<="; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def >= (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = ">="; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def <> (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "<>"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def isNull: StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "IS NULL"; - val operatorIsLeft = false; - val operand = StatementExpression.this.toStatement; - } - } - def isNotNull: StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "IS NOT NULL"; - val operatorIsLeft = false; - val operand = StatementExpression.this.toStatement; - } - } - def + (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "+"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def - (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "-"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def * (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "*"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def / (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "/"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def % (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "%"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def ^ (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "^"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def not : StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "!"; - val operatorIsLeft = false; - val operand = StatementExpression.this.toStatement; - } - } - def || (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "||"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def like (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "LIKE"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def similar (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "SIMILAR"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = se.toStatement; - } - } - def in (se:statement.Select): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.BinaryOperator { - val operator = "IN"; - val leftOperand = StatementExpression.this.toStatement; - val rightOperand = new statement.expression.Select { - val selectStatement = se; - }; - } - } - -} - -object StatementExpression { - - def not (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "NOT"; - val operatorIsLeft = true; - val operand = se.toStatement; - } - } - def abs (se:StatementExpression): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "@"; - val operatorIsLeft = true; - val operand = se.toStatement; - } - } - def exists (se:statement.Select): StatementExpression = new StatementExpression { - val toStatement = new statement.expression.UnaryOperator { - val operator = "EXISTS"; - val operatorIsLeft = true; - val operand = new statement.expression.Select { - val selectStatement = se; - }; - } - } - - abstract class StatementField extends StatementExpression { - def fieldName: String; - def tableName: Option[String] = None; - def in (tn:String): StatementField = new StatementField { - val fieldName = StatementField.this.fieldName; - override val tableName = Some(tn); - } - def toStatement: statement.expression.Field = new statement.expression.Field { - override val schemaName = None; - val tableName = StatementField.this.tableName; - val fieldName = StatementField.this.fieldName; - } - } - - implicit def stringToStatementField (ef:String): StatementField = new StatementField { - val fieldName = ef; - } - - - - -} diff --git a/src/library/scala/dbc/value/ApproximateNumeric.scala b/src/library/scala/dbc/value/ApproximateNumeric.scala deleted file mode 100644 index 5da4fec640..0000000000 --- a/src/library/scala/dbc/value/ApproximateNumeric.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -abstract class ApproximateNumeric [Type] extends Value { - - val dataType: datatype.ApproximateNumeric[Type]; - - def sqlString = nativeValue.toString(); - - } - -object ApproximateNumeric { - - implicit def approximateNumericToFloar (obj:value.ApproximateNumeric[Float]): Float = obj.nativeValue; - implicit def approximateNumericToDouble (obj:value.ApproximateNumeric[Double]): Double = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/Boolean.scala b/src/library/scala/dbc/value/Boolean.scala deleted file mode 100644 index fba78dcfd1..0000000000 --- a/src/library/scala/dbc/value/Boolean.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -abstract class Boolean extends Value { - - val dataType: datatype.Boolean; - - def sqlString = if (nativeValue) "TRUE" else "FALSE"; - -} - -object Boolean { - - implicit def booleanToBoolean (obj:value.Boolean): scala.Boolean = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/Character.scala b/src/library/scala/dbc/value/Character.scala deleted file mode 100644 index c02a21b28e..0000000000 --- a/src/library/scala/dbc/value/Character.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -/** A SQL-99 value of type character string. */ -abstract class Character extends Value { - - override val dataType: datatype.Character; - - /** An SQL-99 compliant string representation of the value. */ - def sqlString: String = { - "'" + nativeValue + "'" - } - -} - -/** An object offering transformation methods (views) on the value. - * This object must be visible in an expression to use value auto- - * conversion. */ -object Character { - - /** A character string value as a native string. */ - implicit def characterToString (obj:value.Character): String = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/CharacterLargeObject.scala b/src/library/scala/dbc/value/CharacterLargeObject.scala deleted file mode 100644 index 61f55f868a..0000000000 --- a/src/library/scala/dbc/value/CharacterLargeObject.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -/** A SQL-99 value of type character large object. */ -abstract class CharacterLargeObject extends Value { - - override val dataType: datatype.CharacterLargeObject; - - /** An SQL-99 compliant string representation of the value. */ - def sqlString: String = { - "'" + nativeValue + "'" - } - -} - -/** An object offering transformation methods (views) on the value. - * This object must be visible in an expression to use value auto- - * conversion. */ -object CharacterLargeObject { - - /** A character large object value as a native string. */ - implicit def characterLargeObjectToString (obj:value.CharacterLargeObject): String = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/CharacterVarying.scala b/src/library/scala/dbc/value/CharacterVarying.scala deleted file mode 100644 index 177dbdba5b..0000000000 --- a/src/library/scala/dbc/value/CharacterVarying.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -/** A SQL-99 value of type character varying string. */ -abstract class CharacterVarying extends Value { - - override val dataType: datatype.CharacterVarying; - - /** An SQL-99 compliant string representation of the value. */ - def sqlString: String = { - "'" + nativeValue + "'" - } - -} - -/** An object offering transformation methods (views) on the value. - * This object must be visible in an expression to use value auto- - * conversion. */ -object CharacterVarying { - - /** A character varying string value as a native string. */ - implicit def characterVaryingToString (obj:value.CharacterVarying): String = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/Conversion.scala b/src/library/scala/dbc/value/Conversion.scala deleted file mode 100644 index 093cf55902..0000000000 --- a/src/library/scala/dbc/value/Conversion.scala +++ /dev/null @@ -1,157 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -import java.math._; - -object Conversion { - - class Illegal (msg:String) extends Exception(msg); - - implicit def view1 (value:Value): Byte = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to byte: "+value) - } - } - - implicit def view2 (value:Value): Short = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.SHORT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to short: "+value) - } - } - - implicit def view3 (value:Value): Int = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.SHORT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.INT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to int: "+value) - } - } - - implicit def view4 (value:Value): Long = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.SHORT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.INT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.LONG) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to long: "+value) - } - } - - implicit def view5 (value:Value): BigInteger = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - new BigInteger(v.nativeValue.toString(),10) - } else if (value.dataType.nativeTypeId == DataType.SHORT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; - new BigInteger(v.nativeValue.toString(),10) - } else if (value.dataType.nativeTypeId == DataType.INT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; - new BigInteger(v.nativeValue.toString(),10) - } else if (value.dataType.nativeTypeId == DataType.LONG) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; - new BigInteger(v.nativeValue.toString(),10) - } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to big integer: "+value) - } - } - - implicit def view6 (value:Value): BigDecimal = { - if (value.dataType.nativeTypeId == DataType.BYTE) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]]; - new BigDecimal(v.nativeValue.toString()) - } else if (value.dataType.nativeTypeId == DataType.SHORT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]]; - new BigDecimal(v.nativeValue.toString()) - } else if (value.dataType.nativeTypeId == DataType.INT) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]]; - new BigDecimal(v.nativeValue.toString()) - } else if (value.dataType.nativeTypeId == DataType.LONG) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]]; - new BigDecimal(v.nativeValue.toString()) - } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]]; - new BigDecimal(v.nativeValue) - } else if (value.dataType.nativeTypeId == DataType.BIG_DECIMAL) { - val v = value.asInstanceOf[dbc.value.ExactNumeric[BigDecimal]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to big decimal: "+value) - } - } - - implicit def view7 (value:Value): Float = { - if (value.dataType.nativeTypeId == DataType.FLOAT) { - val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to float: "+value) - } - } - - implicit def view8 (value:Value): Double = { - if (value.dataType.nativeTypeId == DataType.FLOAT) { - val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]]; - v.nativeValue.coerce - } else if (value.dataType.nativeTypeId == DataType.DOUBLE) { - val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Double]]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to double: "+value) - } - } - - implicit def view9 (value:Value): scala.Boolean = { - if (value.dataType.nativeTypeId == DataType.BOOLEAN) { - val v = value.asInstanceOf[dbc.value.Boolean]; - v.nativeValue - } else { - throw new Illegal("Cannot convert value to boolean: "+value) - } - } - - implicit def view10 (value:Value): String = value match { - case v:dbc.value.Character => v.nativeValue; - case v:dbc.value.CharacterLargeObject => v.nativeValue; - case v:dbc.value.CharacterVarying => v.nativeValue; - case _ => throw new Illegal("Cannot convert value to string") - } - -} diff --git a/src/library/scala/dbc/value/ExactNumeric.scala b/src/library/scala/dbc/value/ExactNumeric.scala deleted file mode 100644 index 1c30c89c29..0000000000 --- a/src/library/scala/dbc/value/ExactNumeric.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -import java.math.BigInteger; -import java.math.BigDecimal; - -abstract class ExactNumeric [Type] extends Value { - - val dataType: datatype.ExactNumeric[Type]; - - def sqlString = nativeValue.toString(); - -} - -object ExactNumeric { - - implicit def exactNumericToByte (obj:value.ExactNumeric[Byte]): Byte = obj.nativeValue; - implicit def exactNumericToShort (obj:value.ExactNumeric[Short]): Short = obj.nativeValue; - implicit def exactNumericToInt (obj:value.ExactNumeric[Int]): Int = obj.nativeValue; - implicit def exactNumericToLong (obj:value.ExactNumeric[Long]): Long = obj.nativeValue; - implicit def exactNumericToBigInteger (obj:value.ExactNumeric[BigInteger]): BigInteger = obj.nativeValue; - implicit def exactNumericToBigDecimal (obj:value.ExactNumeric[BigDecimal]): BigDecimal = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/value/Factory.scala b/src/library/scala/dbc/value/Factory.scala deleted file mode 100644 index 34975937e7..0000000000 --- a/src/library/scala/dbc/value/Factory.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -import java.math.BigInteger; -import java.math.BigDecimal; - -object Factory { - - def create (result: java.sql.ResultSet, index: Int, expectedDataType: DataType): Value = { - expectedDataType.nativeTypeId match { - case DataType.OBJECT => - new value.Unknown { - val dataType = expectedDataType.asInstanceOf[datatype.Unknown]; - val nativeValue: Object = result.getObject(index); - } - case DataType.STRING => { - expectedDataType match { - case t:datatype.Character => - new value.Character { - val dataType = t; - val nativeValue: String = result.getString(index); - } - case t:datatype.CharacterVarying => - new value.CharacterVarying { - val dataType = t; - val nativeValue: String = result.getString(index); - } - case t:datatype.CharacterLargeObject => - new value.CharacterLargeObject { - val dataType = t; - val nativeValue: String = result.getString(index); - } - } - } - case DataType.BOOLEAN => - new value.Boolean { - val dataType = expectedDataType.asInstanceOf[datatype.Boolean]; - val nativeValue: scala.Boolean = result.getBoolean(index); - } - case DataType.FLOAT => - new value.ApproximateNumeric[Float] { - val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Float]]; - val nativeValue: Float = result.getFloat(index); - } - case DataType.DOUBLE => - new value.ApproximateNumeric[Double] { - val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Double]]; - val nativeValue: Double = result.getDouble(index); - } - case DataType.BYTE => - new value.ExactNumeric[Byte] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Byte]]; - val nativeValue: Byte = result.getByte(index); - } - case DataType.SHORT => - new value.ExactNumeric[Short] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Short]]; - val nativeValue: Short = result.getShort(index); - } - case DataType.INT => - new value.ExactNumeric[Int] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Int]]; - val nativeValue: Int = result.getInt(index); - } - case DataType.LONG => - new value.ExactNumeric[Long] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Long]]; - val nativeValue:Long = result.getLong(index); - } - case DataType.BIG_INTEGER => - new value.ExactNumeric[BigInteger] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigInteger]]; - val nativeValue: BigInteger = result.getBigDecimal(index).unscaledValue(); - } - case DataType.BIG_DECIMAL => - new value.ExactNumeric[BigDecimal] { - val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigDecimal]]; - val nativeValue: BigDecimal = result.getBigDecimal(index); - } - - } - } - -} diff --git a/src/library/scala/dbc/value/Unknown.scala b/src/library/scala/dbc/value/Unknown.scala deleted file mode 100644 index b1ba51d064..0000000000 --- a/src/library/scala/dbc/value/Unknown.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.value; - - -abstract class Unknown extends Value { - - val dataType: datatype.Unknown; - - def sqlString = error ("An 'ANY' value cannot be represented."); - -} - -object UnknownType { - - def view (obj:value.Unknown): Object = obj.nativeValue; - -} diff --git a/src/library/scala/dbc/vendor/PostgreSQL.scala b/src/library/scala/dbc/vendor/PostgreSQL.scala deleted file mode 100644 index f637b32a82..0000000000 --- a/src/library/scala/dbc/vendor/PostgreSQL.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.dbc.vendor; - - -abstract class PostgreSQL extends Vendor { - - def uri:java.net.URI; - def user:String; - def pass:String; - - val retainedConnections = 5; - - val nativeDriverClass = Class.forName("org.postgresql.Driver"); - - val urlProtocolString = "jdbc:postgresql:" - -} -- cgit v1.2.3