Permalink
Browse files

Fix default value generation for postgresql columns include #1123, te…

…stcase.
  • Loading branch information...
1 parent 8dcb5e3 commit d11238e88d752042dae8dd81572c6288ca3ae8ab @AtkinsChang AtkinsChang committed Jul 31, 2016
@@ -170,6 +170,7 @@ class $name(_tableTag: Tag) extends profile.api.Table[$elementType](_tableTag, $
}
def defaultCode = {
case Some(v) => s"Some(${defaultCode(v)})"
+ case v:String if model.tpe == "scala.math.BigDecimal" => s"""new scala.math.BigDecimal(new java.math.BigDecimal("$v"))"""
case s:String => "\""+s+"\""
case None => s"None"
case v:Byte => s"$v"
@@ -180,7 +181,7 @@ class $name(_tableTag: Tag) extends profile.api.Table[$elementType](_tableTag, $
case v:Boolean => s"$v"
case v:Short => s"$v"
case v:Char => s"'$v'"
- case v:BigDecimal => s"new scala.math.BigDecimal(new java.math.BigDecimal($v))"
+ case v:BigDecimal => s"""new scala.math.BigDecimal(new java.math.BigDecimal("$v"))"""
case v => throw new SlickException( s"Dont' know how to generate code for default value $v of ${v.getClass}. Override def defaultCode to render the value." )
}
// Explicit type to allow overloading existing Slick method names.
@@ -0,0 +1,53 @@
+DROP TABLE IF EXISTS "test";
+CREATE TABLE "test" ("smallint_auto_inc" SMALLSERIAL,
+ "smallint_no_default" SMALLINT,
+ "smallint_default_zero" SMALLINT DEFAULT 0,
+ "smallint_default_pos" SMALLINT DEFAULT 1,
+ "smallint_default_neg" SMALLINT DEFAULT -1,
+ "smallint_default_max" SMALLINT DEFAULT 32767,
+ "smallint_default_min" SMALLINT DEFAULT -32768,
+ "int_auto_inc" SERIAL,
+ "int_no_default" INT,
+ "int_default_zero" INT DEFAULT 0,
+ "int_default_pos" INT DEFAULT 1,
+ "int_default_neg" INT DEFAULT -1,
+ "int_default_max" INT DEFAULT 2147483647,
+ "int_default_min" INT DEFAULT -2147483648,
+ "bigint_auto_inc" BIGSERIAL,
+ "bigint_no_default" BIGINT,
+ "bigint_default_zero" BIGINT DEFAULT 0,
+ "bigint_default_pos" BIGINT DEFAULT 1,
+ "bigint_default_neg" BIGINT DEFAULT -1,
+ "bigint_default_max" BIGINT DEFAULT 9223372036854775807,
+ "bigint_default_min" BIGINT DEFAULT -9223372036854775808,
+ "real_no_default" REAL,
+ "real_default_int_zero" REAL DEFAULT 0,
+ "real_default_int_pos" REAL DEFAULT 1,
+ "real_default_int_neg" REAL DEFAULT -1,
+ "real_default_int_pos2" REAL DEFAULT 9223372036854775807,
+ "real_default_int_neg2" REAL DEFAULT -9223372036854775808,
+ "real_default_zero" REAL DEFAULT 0.0,
+ "real_default_pos" REAL DEFAULT 1.1,
+ "real_default_neg" REAL DEFAULT -1.1,
+ "double_precision_no_default" DOUBLE PRECISION,
+ "double_precision_default_int_zero" DOUBLE PRECISION DEFAULT 0,
+ "double_precision_default_int_pos" DOUBLE PRECISION DEFAULT 1,
+ "double_precision_default_int_neg" DOUBLE PRECISION DEFAULT -1,
+ "double_precision_default_int_pos2" DOUBLE PRECISION DEFAULT 9223372036854775807,
+ "double_precision_default_int_neg2" DOUBLE PRECISION DEFAULT -9223372036854775808,
+ "double_precision_default_zero" DOUBLE PRECISION DEFAULT 0.0,
+ "double_precision_default_pos" DOUBLE PRECISION DEFAULT 1.1,
+ "double_precision_default_neg" DOUBLE PRECISION DEFAULT -1.1,
+ "numeric_no_default" NUMERIC,
+ "numeric_default_int_zero" NUMERIC DEFAULT 0,
+ "numeric_default_int_pos" NUMERIC DEFAULT 1,
+ "numeric_default_int_neg" NUMERIC DEFAULT -1,
+ "numeric_default_int_pos2" NUMERIC DEFAULT 9223372036854775807,
+ "numeric_default_int_neg2" NUMERIC DEFAULT -9223372036854775808,
+ "numeric_default_zero" NUMERIC DEFAULT 0.0,
+ "numeric_default_pos" NUMERIC DEFAULT 1.1,
+ "numeric_default_neg" NUMERIC DEFAULT -1.1,
+ "char_dafault" CHAR(5) DEFAULT 'abcde',
+ "varchar_default" VARCHAR DEFAULT 'abcde',
+ "text_default" TEXT DEFAULT 'abcde'
+ );
@@ -104,6 +104,7 @@ val SimpleA = CustomTyping.SimpleA
""".stripMargin
},
new UUIDConfig("Postgres2", StandardTestDBs.Postgres, "Postgres", Seq("/dbs/uuid-postgres.sql")),
+ new Config("Postgres3", StandardTestDBs.Postgres, "Postgres", Seq("/dbs/postgres.sql")),
new Config("EmptyDB", StandardTestDBs.H2Mem, "H2Mem", Nil),
new Config("Oracle1", StandardTestDBs.Oracle, "Oracle", Seq("/dbs/oracle1.sql")) {
override def useSingleLineStatements = true
@@ -97,7 +97,7 @@ trait TestCodeGenerator {
| import scala.concurrent.ExecutionContext.Implicits.global
| $testCode
|}
- """.stripMargin + super.code
+ |""".stripMargin + super.code
}
}
}
@@ -1,12 +1,13 @@
package slick.test.codegen
import scala.concurrent.ExecutionContext.Implicits.global
-import slick.ast.{Node, Select}
+import slick.ast.{FieldSymbol, Node, Select}
import slick.jdbc.JdbcProfile
import slick.jdbc.meta.MTable
import slick.test.codegen.generated._
import com.typesafe.slick.testkit.util.{TestCodeRunner, JdbcTestDB}
import org.junit.Assert._
+import slick.relational.RelationalProfile
/** Test files generated by CodeGeneratorTest */
class GeneratedCodeTest extends TestCodeRunner(AllTests)
@@ -50,7 +51,7 @@ object GeneratedCodeTest {
assertTrue("Indices should refer to correct field", dIdxFieldsName sameElements List("f1", "f2"))
def optionsOfColumn(c: slick.lifted.Rep[_]) =
- c.toNode.asInstanceOf[Select].field.asInstanceOf[slick.ast.FieldSymbol].options.toList
+ c.toNode.asInstanceOf[Select].field.asInstanceOf[FieldSymbol].options.toList
val k1Options = optionsOfColumn(E.baseTableRow.k1)
val k2Options = optionsOfColumn(E.baseTableRow.k2)
val sOptions = optionsOfColumn(E.baseTableRow.s)
@@ -134,6 +135,30 @@ object GeneratedCodeTest {
)
}
+ def testPostgres3 = {
+ import Postgres3._
+ import profile.api._
+ DBIO.seq(
+ schema.create,
+ MTable.getTables(Some(""), Some("public"), None, None).map { tables =>
+ def optionsOfColumn(c: slick.lifted.Rep[_]) =
+ c.toNode.asInstanceOf[Select].field.asInstanceOf[FieldSymbol].options.toList
+ val smallserialOptions = optionsOfColumn(Test.baseTableRow.smallintAutoInc)
+ val serialOptions = optionsOfColumn(Test.baseTableRow.intAutoInc)
+ val bigserialOptions = optionsOfColumn(Test.baseTableRow.bigintAutoInc)
+ val charEmptyOptions = optionsOfColumn(Test.baseTableRow.charDefaultEmpty)
+ val charValidOptions = optionsOfColumn(Test.baseTableRow.charDefaultValid)
+ val charInvalidOptions = optionsOfColumn(Test.baseTableRow.charDefaultInvalid)
+ assertTrue("smallint_auto_inc should be AutoInc", smallserialOptions.exists(option => (option equals Test.baseTableRow.O.AutoInc)))
+ assertTrue("int_auto_inc should be AutoInc", serialOptions.exists(option => (option equals Test.baseTableRow.O.AutoInc)))
+ assertTrue("bigint_auto_inc should be AutoInc", bigserialOptions.exists(option => (option equals Test.baseTableRow.O.AutoInc)))
+ assertTrue("default value of char_default_empty should be ' '", charEmptyOptions.exists(option => (option equals Test.baseTableRow.O.Default(' '))))
+ assertTrue("default value of char_default_valid should be 'a'", charValidOptions.exists(option => (option equals Test.baseTableRow.O.Default('a'))))
+ assertTrue("default value of char_default_invalid should not exist", charInvalidOptions.forall(option => (option.isInstanceOf[RelationalProfile.ColumnOption.Default[_]])))
+ }
+ )
+ }
+
def testEmptyDB = slick.dbio.DBIO.successful(())
def tableName( node:Node ) : String = {
@@ -63,25 +63,27 @@ trait PostgresProfile extends JdbcProfile {
override def schema = super.schema.filter(_ != "public") // remove default schema
}
override def createColumnBuilder(tableBuilder: TableBuilder, meta: MColumn): ColumnBuilder = new ColumnBuilder(tableBuilder, meta) {
- val VarCharPattern = "^'(.*)'::character varying$".r
- val TextPattern = "^'(.*)'::text".r
- val IntPattern = "^\\((-?[0-9]*)\\)$".r
+ val NumericPattern = "^'(-?[0-9]+.?[0-9]*)'::(?:numeric|bigint|integer)".r
+ val TextPattern = "^'(.*)'::(?:bpchar|character varying|text)".r
+ val UUIDPattern = "^'(.*)'::uuid".r
override def default = meta.columnDef.map((_,tpe)).collect{
case ("true","Boolean") => Some(Some(true))
case ("false","Boolean") => Some(Some(false))
- case (VarCharPattern(str),"String") => Some(Some(str))
case (TextPattern(str),"String") => Some(Some(str))
- case (IntPattern(v),"Int") => Some(Some(v.toInt))
- case (IntPattern(v),"Long") => Some(Some(v.toLong))
- case ("NULL::character varying","String") => Some(None)
- case (v,"java.util.UUID") => {
- if (v.matches("^['\"].*['\"](::uuid)?$")) {
- val uuid = v.replaceAll("[\'\"]", "") //strip quotes
- .stripSuffix("::uuid") //strip suffix
- Some(Some(java.util.UUID.fromString(uuid)))
- } else
- None // The UUID is generated through a function - treat it as if there was no default.
+ case (TextPattern(str),"Char") => str.length match {
+ case 0 => Some(Some(' ')) // Default to one space, as the char will be space padded anyway
+ case 1 => Some(Some(str.head))
+ case _ => None // This is invalid, so let's not supply any default
}
+ case (NumericPattern(v),"Short") => Some(Some(v.toShort))
+ case (NumericPattern(v),"Int") => Some(Some(v.toInt))
+ case (NumericPattern(v),"Long") => Some(Some(v.toLong))
+ case (NumericPattern(v),"Float") => Some(Some(v.toFloat))
+ case (NumericPattern(v),"Double") => Some(Some(v.toDouble))
+ case (NumericPattern(v), "scala.math.BigDecimal") => Some(Some(v))
+ case (v, "scala.math.BigDecimal") => Some(Some(v))
+ case (UUIDPattern(v),"java.util.UUID") => Some(Some(java.util.UUID.fromString(v)))
+ case (_,"java.util.UUID") => None // The UUID is generated through a function - treat it as if there was no default.
}.getOrElse{
val d = super.default
if(meta.nullable == Some(true) && d == None){

0 comments on commit d11238e

Please sign in to comment.