Skip to content

Commit cf644e3

Browse files
authored
Add Table.tableFragment to support basic virtual table syntax (#160)
1 parent e0657f0 commit cf644e3

File tree

4 files changed

+132
-3
lines changed

4 files changed

+132
-3
lines changed

Sources/StructuredQueriesCore/Statements/Select.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,7 +1752,7 @@ extension Select: SelectStatement {
17521752
if let schemaName = From.schemaName {
17531753
query.append("\(quote: schemaName).")
17541754
}
1755-
query.append("\(quote: From.tableName)")
1755+
query.append(From.tableFragment)
17561756
if let tableAlias = From.tableAlias {
17571757
query.append(" AS \(quote: tableAlias)")
17581758
}

Sources/StructuredQueriesCore/Table.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public protocol Table: QueryRepresentable where TableColumns.QueryValue == Self
2424
/// The table schema's name.
2525
static var schemaName: String? { get }
2626

27+
/// A query fragment representing the table.
28+
static var tableFragment: QueryFragment { get }
29+
2730
/// A select statement for this table.
2831
///
2932
/// The default implementation of this property returns a fully unscoped query for the table
@@ -95,6 +98,10 @@ extension Table {
9598
nil
9699
}
97100

101+
public static var tableFragment: QueryFragment {
102+
QueryFragment(quote: tableName)
103+
}
104+
98105
/// Returns a table column to the resulting value of a given key path.
99106
///
100107
/// Allows, _e.g._ `Reminder.columns.id` to be abbreviated `Reminder.id`, which is useful when

Tests/StructuredQueriesTests/SelectTests.swift

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,111 @@ extension SnapshotTests {
14371437
_ = base.count { r, _ in r.isCompleted }
14381438
_ = base.map {}
14391439
}
1440+
1441+
@Test func virtualTable() {
1442+
assertQuery(
1443+
PragmaTableInfo<Reminder>.all
1444+
) {
1445+
"""
1446+
SELECT "remindersTableInfo"."cid", "remindersTableInfo"."name", "remindersTableInfo"."type", "remindersTableInfo"."notnull", "remindersTableInfo"."dflt_value", "remindersTableInfo"."pk"
1447+
FROM pragma_table_info('reminders') AS "remindersTableInfo"
1448+
"""
1449+
} results: {
1450+
#"""
1451+
┌─────────────────────────────────────────┐
1452+
│ PragmaTableInfo( │
1453+
│ columnID: 0, │
1454+
│ name: "id", │
1455+
│ type: "INTEGER", │
1456+
│ isNotNull: true, │
1457+
│ defaultValue: nil, │
1458+
│ isPrimaryKey: true │
1459+
│ ) │
1460+
├─────────────────────────────────────────┤
1461+
│ PragmaTableInfo( │
1462+
│ columnID: 1, │
1463+
│ name: "assignedUserID", │
1464+
│ type: "INTEGER", │
1465+
│ isNotNull: false, │
1466+
│ defaultValue: nil, │
1467+
│ isPrimaryKey: false │
1468+
│ ) │
1469+
├─────────────────────────────────────────┤
1470+
│ PragmaTableInfo( │
1471+
│ columnID: 2, │
1472+
│ name: "dueDate", │
1473+
│ type: "DATE", │
1474+
│ isNotNull: false, │
1475+
│ defaultValue: nil, │
1476+
│ isPrimaryKey: false │
1477+
│ ) │
1478+
├─────────────────────────────────────────┤
1479+
│ PragmaTableInfo( │
1480+
│ columnID: 3, │
1481+
│ name: "isCompleted", │
1482+
│ type: "BOOLEAN", │
1483+
│ isNotNull: true, │
1484+
│ defaultValue: "0", │
1485+
│ isPrimaryKey: false │
1486+
│ ) │
1487+
├─────────────────────────────────────────┤
1488+
│ PragmaTableInfo( │
1489+
│ columnID: 4, │
1490+
│ name: "isFlagged", │
1491+
│ type: "BOOLEAN", │
1492+
│ isNotNull: true, │
1493+
│ defaultValue: "0", │
1494+
│ isPrimaryKey: false │
1495+
│ ) │
1496+
├─────────────────────────────────────────┤
1497+
│ PragmaTableInfo( │
1498+
│ columnID: 5, │
1499+
│ name: "remindersListID", │
1500+
│ type: "INTEGER", │
1501+
│ isNotNull: true, │
1502+
│ defaultValue: nil, │
1503+
│ isPrimaryKey: false │
1504+
│ ) │
1505+
├─────────────────────────────────────────┤
1506+
│ PragmaTableInfo( │
1507+
│ columnID: 6, │
1508+
│ name: "notes", │
1509+
│ type: "TEXT", │
1510+
│ isNotNull: true, │
1511+
│ defaultValue: "\'\'", │
1512+
│ isPrimaryKey: false │
1513+
│ ) │
1514+
├─────────────────────────────────────────┤
1515+
│ PragmaTableInfo( │
1516+
│ columnID: 7, │
1517+
│ name: "priority", │
1518+
│ type: "INTEGER", │
1519+
│ isNotNull: false, │
1520+
│ defaultValue: nil, │
1521+
│ isPrimaryKey: false │
1522+
│ ) │
1523+
├─────────────────────────────────────────┤
1524+
│ PragmaTableInfo( │
1525+
│ columnID: 8, │
1526+
│ name: "title", │
1527+
│ type: "TEXT", │
1528+
│ isNotNull: true, │
1529+
│ defaultValue: "\'\'", │
1530+
│ isPrimaryKey: false │
1531+
│ ) │
1532+
├─────────────────────────────────────────┤
1533+
│ PragmaTableInfo( │
1534+
│ columnID: 9, │
1535+
│ name: "updatedAt", │
1536+
│ type: "TEXT", │
1537+
│ isNotNull: true, │
1538+
│ defaultValue: "datetime(\'subsec\')", │
1539+
│ isPrimaryKey: false │
1540+
│ ) │
1541+
└─────────────────────────────────────────┘
1542+
"""#
1543+
}
1544+
}
14401545
}
14411546
}
14421547

@@ -1445,3 +1550,20 @@ extension Reminder.TableColumns {
14451550
self.priority == Priority.high
14461551
}
14471552
}
1553+
1554+
@Table
1555+
struct PragmaTableInfo<Base: Table> {
1556+
static var tableAlias: String? { "\(Base.tableName)TableInfo" }
1557+
static var schemaName: String? { Base.schemaName }
1558+
1559+
static var tableFragment: QueryFragment {
1560+
"pragma_table_info(\(quote: Base.tableName, delimiter: .text))"
1561+
}
1562+
1563+
@Column("cid") let columnID: Int
1564+
let name: String
1565+
let type: String
1566+
@Column("notnull") let isNotNull: Bool
1567+
@Column("dflt_value") let defaultValue: String?
1568+
@Column("pk") let isPrimaryKey: Bool
1569+
}

Tests/StructuredQueriesTests/Support/Schema.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ extension Database {
9696
try execute(
9797
"""
9898
CREATE TABLE "remindersLists" (
99-
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
99+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
100100
"color" INTEGER NOT NULL DEFAULT 4889071,
101101
"title" TEXT NOT NULL DEFAULT '',
102102
"position" INTEGER NOT NULL DEFAULT 0
@@ -111,7 +111,7 @@ extension Database {
111111
try execute(
112112
"""
113113
CREATE TABLE "reminders" (
114-
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
114+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
115115
"assignedUserID" INTEGER,
116116
"dueDate" DATE,
117117
"isCompleted" BOOLEAN NOT NULL DEFAULT 0,

0 commit comments

Comments
 (0)