0
# Table Definitions
1
2
Define database tables with strongly-typed columns, constraints, and schema operations in Slick.
3
4
## Capabilities
5
6
### Table Classes
7
8
Define database tables by extending the `Table` class with column definitions and table metadata.
9
10
```scala { .api }
11
/**
12
* Base class for database table definitions
13
* @param tag Table tag for identification
14
* @param tableName Name of the database table
15
*/
16
abstract class AbstractTable[T](tag: Tag, tableName: String)
17
18
/**
19
* Concrete table class for defining database tables
20
* @param tag Table tag for identification
21
* @param tableName Name of the database table
22
*/
23
class Table[T](tag: Tag, tableName: String) extends AbstractTable[T] {
24
/** Default projection - defines which columns make up the table's row type */
25
def * : ProvenShape[T]
26
}
27
28
/**
29
* Table tag for identifying table instances
30
*/
31
final class Tag(val taggedAs: Any)
32
```
33
34
**Usage Examples:**
35
36
```scala
37
// Simple table definition
38
class Users(tag: Tag) extends Table[(Int, String)](tag, "users") {
39
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
40
def name = column[String]("name")
41
def * = (id, name)
42
}
43
44
// Table with case class mapping
45
final case class Coffee(name: String, price: Double)
46
47
class Coffees(tag: Tag) extends Table[Coffee](tag, "coffees") {
48
def name = column[String]("name")
49
def price = column[Double]("price")
50
def * = (name, price).mapTo[Coffee]
51
}
52
```
53
54
### Column Definitions
55
56
Define typed columns with constraints and options.
57
58
```scala { .api }
59
/**
60
* Define a table column with type T
61
* @param name Column name in the database
62
* @param options Column options like primary key, auto increment, etc.
63
*/
64
def column[T](name: String, options: ColumnOption[T]*): Rep[T]
65
66
/**
67
* Represents a column or expression that can be used in queries
68
*/
69
trait Rep[T] {
70
/** Column equality comparison */
71
def ===[P2, R](e: P2)(implicit om: o.=:=[Rep[P2], Rep[Option[T]]], sh: Shape[_ <: FlatShapeLevel, Rep[P2], T, Rep[P2]]): Rep[Boolean]
72
73
/** Column inequality comparison */
74
def =!=[P2, R](e: P2)(implicit om: o.=:=[Rep[P2], Rep[Option[T]]], sh: Shape[_ <: FlatShapeLevel, Rep[P2], T, Rep[P2]]): Rep[Boolean]
75
}
76
```
77
78
### Column Options
79
80
Specify column constraints and behavior using column options.
81
82
```scala { .api }
83
/**
84
* Column options for specifying constraints and behavior
85
*/
86
sealed trait ColumnOption[+T]
87
88
object O {
89
/** Primary key constraint */
90
case object PrimaryKey extends ColumnOption[Nothing]
91
92
/** Auto-increment column */
93
case object AutoInc extends ColumnOption[Nothing]
94
95
/** Unique constraint */
96
case object Unique extends ColumnOption[Nothing]
97
98
/** Not null constraint */
99
case object NotNull extends ColumnOption[Nothing]
100
101
/** Column length specification */
102
case class Length(length: Int) extends ColumnOption[Nothing]
103
104
/** Default value for column */
105
case class Default[T](defaultValue: T) extends ColumnOption[T]
106
107
/** Foreign key constraint */
108
case class ForeignKey[T](name: String, sourceColumns: Any, targetTableQuery: Any, targetColumns: Any, onUpdate: ForeignKeyAction, onDelete: ForeignKeyAction) extends ColumnOption[T]
109
}
110
```
111
112
**Usage Examples:**
113
114
```scala
115
class Products(tag: Tag) extends Table[Product](tag, "products") {
116
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
117
def name = column[String]("name", O.Length(100))
118
def description = column[Option[String]]("description")
119
def price = column[BigDecimal]("price")
120
def categoryId = column[Int]("category_id")
121
def isActive = column[Boolean]("is_active", O.Default(true))
122
def createdAt = column[Timestamp]("created_at", O.Default(new Timestamp(System.currentTimeMillis())))
123
124
def * = (id, name, description, price, categoryId, isActive, createdAt).mapTo[Product]
125
}
126
```
127
128
### TableQuery
129
130
Access and query database tables using TableQuery objects.
131
132
```scala { .api }
133
/**
134
* Represents a database table that can be queried
135
*/
136
abstract class TableQuery[E <: AbstractTable[_]] extends Query[E, E#TableElementType, Seq] {
137
/** Get the table's schema DDL */
138
def schema: SchemaDescription
139
140
/** Insert a single row */
141
def += (value: E#TableElementType): ProfileAction[Int, NoStream, Write]
142
143
/** Insert multiple rows */
144
def ++= (values: Iterable[E#TableElementType]): ProfileAction[Int, NoStream, Write]
145
146
/** Insert or update a row */
147
def insertOrUpdate(value: E#TableElementType): ProfileAction[Int, NoStream, Write]
148
}
149
150
object TableQuery {
151
/**
152
* Create a TableQuery for the given table class
153
*/
154
def apply[E <: AbstractTable[_]](cons: Tag => E): TableQuery[E]
155
}
156
```
157
158
**Usage Examples:**
159
160
```scala
161
// Create TableQuery instances
162
val users = TableQuery[Users]
163
val coffees = TableQuery[Coffees]
164
val products = TableQuery[Products]
165
166
// Insert operations
167
val insertUser = users += (0, "Alice")
168
val insertCoffee = coffees += Coffee("Latte", 2.50)
169
val insertMultiple = coffees ++= Seq(
170
Coffee("Espresso", 1.80),
171
Coffee("Cappuccino", 2.20)
172
)
173
```
174
175
### Schema Operations
176
177
Create, drop, and manage database schemas.
178
179
```scala { .api }
180
/**
181
* Schema description for DDL operations
182
*/
183
trait SchemaDescription {
184
/** Create the schema if it doesn't exist */
185
def createIfNotExists: ProfileAction[Unit, NoStream, Write]
186
187
/** Create the schema */
188
def create: ProfileAction[Unit, NoStream, Write]
189
190
/** Drop the schema if it exists */
191
def dropIfExists: ProfileAction[Unit, NoStream, Write]
192
193
/** Drop the schema */
194
def drop: ProfileAction[Unit, NoStream, Write]
195
196
/** Truncate all tables in the schema */
197
def truncate: ProfileAction[Unit, NoStream, Write]
198
}
199
```
200
201
**Usage Examples:**
202
203
```scala
204
// Create schema for single table
205
val createUsersSchema = users.schema.create
206
207
// Create schema for multiple tables
208
val schema = users.schema ++ coffees.schema ++ products.schema
209
val createAllSchema = schema.create
210
211
// Schema management
212
val setupDb = DBIO.seq(
213
schema.createIfNotExists,
214
users += (0, "admin"),
215
coffees ++= Seq(
216
Coffee("Americano", 2.00),
217
Coffee("Mocha", 3.50)
218
)
219
)
220
```
221
222
### Constraints and Indexes
223
224
Define primary keys, foreign keys, and indexes on tables.
225
226
```scala { .api }
227
/**
228
* Primary key definition
229
*/
230
def primaryKey(name: String, columns: Any): PrimaryKey
231
232
/**
233
* Foreign key definition
234
*/
235
def foreignKey(name: String, sourceColumns: Any, targetTableQuery: Any)(targetColumns: Any => Any): ForeignKeyQuery[_, _]
236
237
/**
238
* Index definition
239
*/
240
def index(name: String, columns: Any, unique: Boolean = false): Index
241
```
242
243
**Usage Examples:**
244
245
```scala
246
class Orders(tag: Tag) extends Table[Order](tag, "orders") {
247
def id = column[Int]("id", O.AutoInc)
248
def userId = column[Int]("user_id")
249
def productId = column[Int]("product_id")
250
def quantity = column[Int]("quantity")
251
def orderDate = column[Date]("order_date")
252
253
def * = (id, userId, productId, quantity, orderDate).mapTo[Order]
254
255
// Composite primary key
256
def pk = primaryKey("pk_orders", (userId, productId, orderDate))
257
258
// Foreign key constraints
259
def userFk = foreignKey("fk_order_user", userId, users)(_.id, onUpdate=ForeignKeyAction.Restrict, onDelete=ForeignKeyAction.Cascade)
260
def productFk = foreignKey("fk_order_product", productId, products)(_.id)
261
262
// Indexes
263
def userIndex = index("idx_order_user", userId)
264
def dateIndex = index("idx_order_date", orderDate)
265
def uniqueUserProductIndex = index("idx_unique_user_product", (userId, productId), unique = true)
266
}
267
```
268
269
### Sequences
270
271
Define and use database sequences for generating values.
272
273
```scala { .api }
274
/**
275
* Database sequence definition
276
*/
277
class Sequence[T](name: String, start: Long = 1, inc: Long = 1, min: Option[Long] = None, max: Option[Long] = None, cycle: Boolean = false)(implicit tpe: ColumnType[Long], integral: Integral[T])
278
279
/**
280
* Sequence operations
281
*/
282
trait SequenceOps {
283
/** Get the next value from the sequence */
284
def nextValue: Rep[T]
285
286
/** Get the current value of the sequence */
287
def currValue: Rep[T]
288
}
289
```
290
291
**Usage Examples:**
292
293
```scala
294
// Define sequences
295
val userIdSeq = Sequence[Long]("user_id_seq")
296
val orderIdSeq = Sequence[Long]("order_id_seq", start = 1000, inc = 1)
297
298
class UsersWithSequence(tag: Tag) extends Table[User](tag, "users") {
299
def id = column[Long]("id", O.Default(userIdSeq.nextValue))
300
def name = column[String]("name")
301
def * = (id, name).mapTo[User]
302
}
303
304
// Use sequence in queries
305
val nextUserId = userIdSeq.nextValue
306
val insertWithSequence = users += User(0L, "Bob") // ID will be auto-generated
307
```
308
309
## Types
310
311
```scala { .api }
312
trait ColumnOption[+T]
313
case class Sequence[T](name: String, start: Long, inc: Long, min: Option[Long], max: Option[Long], cycle: Boolean)
314
trait SchemaDescription
315
case class PrimaryKey(name: String, columns: IndexedSeq[Node])
316
case class ForeignKey(name: String, sourceTable: String, sourceColumns: Seq[String], targetTable: String, targetColumns: Seq[String], onUpdate: ForeignKeyAction, onDelete: ForeignKeyAction)
317
case class Index(name: String, table: String, on: Seq[(String, SortDirection)], unique: Boolean)
318
319
trait ForeignKeyAction
320
object ForeignKeyAction {
321
case object Cascade extends ForeignKeyAction
322
case object Restrict extends ForeignKeyAction
323
case object NoAction extends ForeignKeyAction
324
case object SetNull extends ForeignKeyAction
325
case object SetDefault extends ForeignKeyAction
326
}
327
```