src/Pure/Tools/sql.scala
changeset 63781 af9fe0b6b78e
parent 63780 163244cefb4e
child 63783 baa20f3b6cea
equal deleted inserted replaced
63780:163244cefb4e 63781:af9fe0b6b78e
    40 
    40 
    41   /* columns */
    41   /* columns */
    42 
    42 
    43   object Column
    43   object Column
    44   {
    44   {
    45     def int(name: String, strict: Boolean = true): Column[Int] = new Column_Int(name, strict)
    45     def int(name: String, strict: Boolean = true, primary_key: Boolean = false): Column[Int] =
    46     def long(name: String, strict: Boolean = true): Column[Long] = new Column_Long(name, strict)
    46       new Column_Int(name, strict, primary_key)
    47     def double(name: String, strict: Boolean = true): Column[Double] = new Column_Double(name, strict)
    47     def long(name: String, strict: Boolean = true, primary_key: Boolean = false): Column[Long] =
    48     def string(name: String, strict: Boolean = true): Column[String] = new Column_String(name, strict)
    48       new Column_Long(name, strict, primary_key)
    49     def bytes(name: String, strict: Boolean = true): Column[Bytes] = new Column_Bytes(name, strict)
    49     def double(name: String, strict: Boolean = true, primary_key: Boolean = false): Column[Double] =
       
    50       new Column_Double(name, strict, primary_key)
       
    51     def string(name: String, strict: Boolean = true, primary_key: Boolean = false): Column[String] =
       
    52       new Column_String(name, strict, primary_key)
       
    53     def bytes(name: String, strict: Boolean = true, primary_key: Boolean = false): Column[Bytes] =
       
    54       new Column_Bytes(name, strict, primary_key)
    50   }
    55   }
    51 
    56 
    52   abstract class Column[+A] private[SQL](val name: String, val strict: Boolean)
    57   abstract class Column[+A] private[SQL](
       
    58     val name: String, val strict: Boolean, val primary_key: Boolean)
    53   {
    59   {
    54     def sql_name: String = quote_ident(name)
    60     def sql_name: String = quote_ident(name)
    55     def sql_type: String
    61     def sql_type: String
    56     def sql_decl: String = sql_name + " " + sql_type + (if (strict) " NOT NULL" else "")
    62     def sql_decl: String =
       
    63       sql_name + " " + sql_type +
       
    64       (if (strict) " NOT NULL" else "") +
       
    65       (if (primary_key) " PRIMARY KEY" else "")
       
    66 
    57     def string(rs: ResultSet): String =
    67     def string(rs: ResultSet): String =
    58     {
    68     {
    59       val s = rs.getString(name)
    69       val s = rs.getString(name)
    60       if (s == null) "" else s
    70       if (s == null) "" else s
    61     }
    71     }
    67     }
    77     }
    68 
    78 
    69     override def toString: String = sql_decl
    79     override def toString: String = sql_decl
    70   }
    80   }
    71 
    81 
    72   class Column_Int private[SQL](name: String, strict: Boolean)
    82   class Column_Int private[SQL](name: String, strict: Boolean, primary_key: Boolean)
    73     extends Column[Int](name, strict)
    83     extends Column[Int](name, strict, primary_key)
    74   {
    84   {
    75     def sql_type: String = "INTEGER"
    85     def sql_type: String = "INTEGER"
    76     def apply(rs: ResultSet): Int = rs.getInt(name)
    86     def apply(rs: ResultSet): Int = rs.getInt(name)
    77   }
    87   }
    78 
    88 
    79   class Column_Long private[SQL](name: String, strict: Boolean)
    89   class Column_Long private[SQL](name: String, strict: Boolean, primary_key: Boolean)
    80     extends Column[Long](name, strict)
    90     extends Column[Long](name, strict, primary_key)
    81   {
    91   {
    82     def sql_type: String = "INTEGER"
    92     def sql_type: String = "INTEGER"
    83     def apply(rs: ResultSet): Long = rs.getLong(name)
    93     def apply(rs: ResultSet): Long = rs.getLong(name)
    84   }
    94   }
    85 
    95 
    86   class Column_Double private[SQL](name: String, strict: Boolean)
    96   class Column_Double private[SQL](name: String, strict: Boolean, primary_key: Boolean)
    87     extends Column[Double](name, strict)
    97     extends Column[Double](name, strict, primary_key)
    88   {
    98   {
    89     def sql_type: String = "REAL"
    99     def sql_type: String = "REAL"
    90     def apply(rs: ResultSet): Double = rs.getDouble(name)
   100     def apply(rs: ResultSet): Double = rs.getDouble(name)
    91   }
   101   }
    92 
   102 
    93   class Column_String private[SQL](name: String, strict: Boolean)
   103   class Column_String private[SQL](name: String, strict: Boolean, primary_key: Boolean)
    94     extends Column[String](name, strict)
   104     extends Column[String](name, strict, primary_key)
    95   {
   105   {
    96     def sql_type: String = "TEXT"
   106     def sql_type: String = "TEXT"
    97     def apply(rs: ResultSet): String =
   107     def apply(rs: ResultSet): String =
    98     {
   108     {
    99       val s = rs.getString(name)
   109       val s = rs.getString(name)
   100       if (s == null) "" else s
   110       if (s == null) "" else s
   101     }
   111     }
   102   }
   112   }
   103 
   113 
   104   class Column_Bytes private[SQL](name: String, strict: Boolean)
   114   class Column_Bytes private[SQL](name: String, strict: Boolean, primary_key: Boolean)
   105     extends Column[Bytes](name, strict)
   115     extends Column[Bytes](name, strict, primary_key)
   106   {
   116   {
   107     def sql_type: String = "BLOB"
   117     def sql_type: String = "BLOB"
   108     def apply(rs: ResultSet): Bytes =
   118     def apply(rs: ResultSet): Bytes =
   109     {
   119     {
   110       val bs = rs.getBytes(name)
   120       val bs = rs.getBytes(name)
   113   }
   123   }
   114 
   124 
   115 
   125 
   116   /* tables */
   126   /* tables */
   117 
   127 
   118   sealed case class Table(name: String, columns: Column[Any]*)
   128   sealed case class Table(name: String, columns: List[Column[Any]])
   119   {
   129   {
       
   130     Library.duplicates(columns.map(_.name)) match {
       
   131       case Nil =>
       
   132       case bad => error("Duplicate column names " + commas_quote(bad) + " for table " + quote(name))
       
   133     }
       
   134 
       
   135     columns.filter(_.primary_key) match {
       
   136       case bad if bad.length > 1 =>
       
   137         error("Multiple primary keys " + commas_quote(bad.map(_.name)) + " for table " + quote(name))
       
   138       case _ =>
       
   139     }
       
   140 
   120     def sql_create(strict: Boolean, rowid: Boolean): String =
   141     def sql_create(strict: Boolean, rowid: Boolean): String =
   121       "CREATE TABLE " + (if (strict) "" else " IF NOT EXISTS ") +
   142       "CREATE TABLE " + (if (strict) "" else " IF NOT EXISTS ") +
   122         quote_ident(name) + " " + columns.map(_.sql_decl).mkString("(", ", ", ")") +
   143         quote_ident(name) + " " + columns.map(_.sql_decl).mkString("(", ", ", ")") +
   123         (if (rowid) "" else " WITHOUT ROWID")
   144         (if (rowid) "" else " WITHOUT ROWID")
   124 
   145