Skip to content

Commit

Permalink
Issue #60: PrimaryKey documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed May 28, 2016
1 parent fc8b2ee commit 8d54075
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
40 changes: 37 additions & 3 deletions GRDB/Core/Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,41 @@ extension Database {
}
}

/// A primary key
/// You get primary keys from table names, with the Database.primaryKey(_)
/// method.
///
/// Primary key is nil when table has no primary key:
///
/// // CREATE TABLE items (name TEXT)
/// let itemPk = try db.primaryKey("items") // nil
///
/// Primary keys have one or several columns. When the primary key has a single
/// column, it may contain the row id:
///
/// // CREATE TABLE persons (
/// // id INTEGER PRIMARY KEY,
/// // name TEXT
/// // )
/// let personPk = try db.primaryKey("persons")!
/// personPk.columns // ["id"]
/// personPk.rowIDColumn // "id"
///
/// // CREATE TABLE countries (
/// // isoCode TEXT NOT NULL PRIMARY KEY
/// // name TEXT
/// // )
/// let countryPk = db.primaryKey("countries")!
/// countryPk.columns // ["isoCode"]
/// countryPk.rowIDColumn // nil
///
/// // CREATE TABLE citizenships (
/// // personID INTEGER NOT NULL REFERENCES persons(id)
/// // countryIsoCode TEXT NOT NULL REFERENCES countries(isoCode)
/// // PRIMARY KEY (personID, countryIsoCode)
/// // )
/// let citizenshipsPk = db.primaryKey("citizenships")!
/// citizenshipsPk.columns // ["personID", "countryIsoCode"]
/// citizenshipsPk.rowIDColumn // nil
public struct PrimaryKey {
private enum Impl {
/// An INTEGER PRIMARY KEY column that aliases the Row ID.
Expand All @@ -955,7 +989,7 @@ public struct PrimaryKey {
return PrimaryKey(impl: .Regular(columns))
}

/// The columns in the primary key. Can not be empty.
/// The columns in the primary key; this array is never empty.
public var columns: [String] {
switch impl {
case .RowID(let column):
Expand All @@ -965,7 +999,7 @@ public struct PrimaryKey {
}
}

/// The name of the INTEGER PRIMARY KEY
/// When not nil, the name of the column that contains the INTEGER PRIMARY KEY.
public var rowIDColumn: String? {
switch impl {
case .RowID(let column):
Expand Down
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ Advanced topics:
- [Custom Value Types](#custom-value-types)
- [Prepared Statements](#prepared-statements)
- [Custom SQL Functions](#custom-sql-functions)
- [Database Schema Introspection](#database-schema-introspection)
- [Row Adapters](#row-adapters)
- [Raw SQLite Pointers](#raw-sqlite-pointers)

Expand Down Expand Up @@ -1216,6 +1217,70 @@ Person.select(reverseString.apply(nameColumn))
**GRDB ships with built-in SQL functions that perform unicode-aware string transformations.** See [Unicode](#unicode).


## Database Schema Introspection

**SQLite provides database schema introspection tools**, such as the [sqlite_master](https://www.sqlite.org/faq.html#q7) table, and the pragma [table_info](https://www.sqlite.org/pragma.html#pragma_table_info):

```swift
try db.execute("CREATE TABLE persons(id INTEGER PRIMARY KEY, name TEXT)")

// <Row type:"table" name:"persons" tbl_name:"persons" rootpage:2
// sql:"CREATE TABLE persons(id INTEGER PRIMARY KEY, name TEXT)">
for row in Row.fetch(db, "SELECT * FROM sqlite_master") {
print(row)
}

// <Row cid:0 name:"id" type:"INTEGER" notnull:0 dflt_value:NULL pk:1>
// <Row cid:1 name:"name" type:"TEXT" notnull:0 dflt_value:NULL pk:0>
for row in Row.fetch(db, "PRAGMA table_info('persons')") {
print(row)
}
```

GRDB provides two high-level methods as well:

```swift
db.tableExists("persons") // Bool, true if the table exists
try db.primaryKey("persons") // PrimaryKey?, throws if the table does not exist
```

Primary key is nil when table has no primary key:

```swift
// CREATE TABLE items (name TEXT)
let itemPk = try db.primaryKey("items") // nil
```

Primary keys have one or several columns. When the primary key has a single column, it may contain the [row id](https://www.sqlite.org/autoinc.html):

```swift
// CREATE TABLE persons (
// id INTEGER PRIMARY KEY,
// name TEXT
// )
let personPk = try db.primaryKey("persons")!
personPk.columns // ["id"]
personPk.rowIDColumn // "id"

// CREATE TABLE countries (
// isoCode TEXT NOT NULL PRIMARY KEY
// name TEXT
// )
let countryPk = db.primaryKey("countries")!
countryPk.columns // ["isoCode"]
countryPk.rowIDColumn // nil

// CREATE TABLE citizenships (
// personID INTEGER NOT NULL REFERENCES persons(id)
// countryIsoCode TEXT NOT NULL REFERENCES countries(isoCode)
// PRIMARY KEY (personID, countryIsoCode)
// )
let citizenshipsPk = db.primaryKey("citizenships")!
citizenshipsPk.columns // ["personID", "countryIsoCode"]
citizenshipsPk.rowIDColumn // nil
```


## Row Adapters

**Row adapters let you map column names for easier row consumption.**
Expand Down

0 comments on commit 8d54075

Please sign in to comment.