Skip to content

Commit a682c10

Browse files
committed
Support raw tables
1 parent 6882e9b commit a682c10

File tree

6 files changed

+117
-9
lines changed

6 files changed

+117
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Changelog
22

3-
## 1.2.2 (unreleased)
3+
## 1.3.0
44

55
* Use version `0.4.2` of the PowerSync core extension, which improves the reliability
66
of the new Rust client implementation.
7+
* Add support for [raw tables](https://docs.powersync.com/usage/use-case-examples/raw-tables), which
8+
are custom tables managed by the user instead of JSON-based views managed by the SDK.
79
* Fix attachments never downloading again when the sandbox path of the app (e.g. on the simulator)
810
changes.
911

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ if let kotlinSdkPath = localKotlinSdkOverride {
3131
// Not using a local build, so download from releases
3232
conditionalTargets.append(.binaryTarget(
3333
name: "PowerSyncKotlin",
34-
url: "https://github.com/powersync-ja/powersync-kotlin/releases/download/v1.2.2/PowersyncKotlinRelease.zip",
35-
checksum: "51ddc7d48fa85e881c33a26ca63e4aae694ae16789368f9fbba20a467279fb97"
34+
url: "https://github.com/powersync-ja/powersync-kotlin/releases/download/v1.3.0/PowersyncKotlinRelease.zip",
35+
checksum: "5351c0a89e74ceaad570cd5c016c8ea4b8e10dc404daff3c20485ae0b6b989fa"
3636
))
3737
}
3838

Sources/PowerSync/Kotlin/KotlinAdapter.swift

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,30 @@ enum KotlinAdapter {
4444
ignoreEmptyUpdates: table.ignoreEmptyUpdates
4545
)
4646
}
47+
48+
static func toKotlin(_ table: RawTable) -> PowerSyncKotlin.RawTable {
49+
return PowerSyncKotlin.RawTable(
50+
name: table.name,
51+
put: translateStatement(table.put),
52+
delete: translateStatement(table.delete),
53+
);
54+
}
55+
56+
private static func translateStatement(_ stmt: PendingStatement) -> PowerSyncKotlin.PendingStatement {
57+
return PowerSyncKotlin.PendingStatement(
58+
sql: stmt.sql,
59+
parameters: stmt.parameters.map(translateParameter)
60+
)
61+
}
62+
63+
private static func translateParameter(_ param: PendingStatementParameter) -> PowerSyncKotlin.PendingStatementParameter {
64+
switch param {
65+
case .id:
66+
return PowerSyncKotlin.PendingStatementParameterId.shared
67+
case .column(let name):
68+
return PowerSyncKotlin.PendingStatementParameterColumn(name: name)
69+
}
70+
}
4771
}
4872

4973
struct Column {
@@ -68,8 +92,12 @@ enum KotlinAdapter {
6892

6993
struct Schema {
7094
static func toKotlin(_ schema: SchemaProtocol) -> PowerSyncKotlin.Schema {
71-
PowerSyncKotlin.Schema(
72-
tables: schema.tables.map { Table.toKotlin($0) }
95+
var mappedTables: [PowerSyncKotlin.BaseTable] = []
96+
mappedTables.append(contentsOf: schema.tables.map(Table.toKotlin))
97+
mappedTables.append(contentsOf: schema.rawTables.map(Table.toKotlin))
98+
99+
return PowerSyncKotlin.Schema(
100+
tables: mappedTables
73101
)
74102
}
75103
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/// A table that is managed by the user instead of being auto-created and migrated by the PowerSync SDK.
2+
///
3+
/// These tables give application developers full control over the table (including table and column constraints).
4+
/// The ``RawTable/put`` and ``RawTable/delete`` statements used by the sync client to apply
5+
/// operations to the local database also need to be set explicitly.
6+
///
7+
/// A main benefit of raw tables is that, since they're not backed by JSON views, complex queries on them
8+
/// can be much more efficient.
9+
/// However, it's the responsibility of the developer to create these raw tables, migrate them when necessary
10+
/// and to write triggers detecting local writes. For more information, see [the documentation](https://docs.powersync.com/usage/use-case-examples/raw-tables).
11+
///
12+
/// Note that raw tables are only supported when ``ConnectOptions/newClientImplementation``
13+
/// is enabled.
14+
public struct RawTable: BaseTableProtocol {
15+
/// The name of the table as it appears in sync rules.
16+
///
17+
/// This doesn't necessarily have to match the statement that ``RawTable/put`` and ``RawTable/delete``
18+
/// write into.
19+
/// Instead, it is used by the sync client to identify which operations need to use which raw table definition.
20+
public let name: String
21+
22+
/// The statement to run when the sync client has to insert or update a row.
23+
public let put: PendingStatement
24+
25+
/// The statement to run when the sync client has to delete a row.
26+
public let delete: PendingStatement
27+
28+
public init(name: String, put: PendingStatement, delete: PendingStatement) {
29+
self.name = name;
30+
self.put = put;
31+
self.delete = delete;
32+
}
33+
}
34+
35+
/// A statement to run to sync server-side changes into a local raw table.
36+
public struct PendingStatement {
37+
/// The SQL statement to execute.
38+
public let sql: String
39+
/// For parameters in the prepared statement, the values to fill in.
40+
///
41+
/// Note that the ``RawTable/delete`` statement can only use ``PendingStatementParameter/id`` - upsert
42+
/// statements can also use ``PendingStatementParameter/column`` to refer to columns.
43+
public let parameters: [PendingStatementParameter]
44+
}
45+
46+
/// A parameter that can be used in a ``PendingStatement``.
47+
public enum PendingStatementParameter {
48+
/// A value that resolves to the textual id of the row to insert, update or delete.
49+
case id
50+
/// A value that resolves to the value of a column in a `PUT` operation for inserts or updates.
51+
///
52+
/// Note that using this parameter is not allowed for ``RawTable/delete`` statements, which only have access
53+
/// to the row's ``PendingStatementParameter/id``.
54+
case column(String)
55+
}

Sources/PowerSync/Protocol/Schema/Schema.swift

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ public protocol SchemaProtocol {
33
/// Tables used in Schema
44
///
55
var tables: [Table] { get }
6+
7+
/// Raw tables referenced in the schema.
8+
var rawTables: [RawTable] { get }
69
///
710
/// Validate tables
811
///
@@ -11,15 +14,30 @@ public protocol SchemaProtocol {
1114

1215
public struct Schema: SchemaProtocol {
1316
public let tables: [Table]
17+
public let rawTables: [RawTable]
1418

15-
public init(tables: [Table]) {
19+
public init(tables: [Table], rawTables: [RawTable] = []) {
1620
self.tables = tables
21+
self.rawTables = rawTables
1722
}
1823
///
1924
/// Convenience initializer with variadic parameters
2025
///
21-
public init(_ tables: Table...) {
22-
self.init(tables: tables)
26+
public init(_ tables: BaseTableProtocol...) {
27+
var managedTables: [Table] = []
28+
var rawTables: [RawTable] = []
29+
30+
for table in tables {
31+
if let table = table as? Table {
32+
managedTables.append(table)
33+
} else if let rawTable = table as? RawTable {
34+
rawTables.append(rawTable)
35+
} else {
36+
fatalError("BaseTableProtocol must only be implemented in Swift SDK")
37+
}
38+
}
39+
40+
self.init(tables: managedTables, rawTables: rawTables)
2341
}
2442

2543
public func validate() throws {

Sources/PowerSync/Protocol/Schema/Table.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import Foundation
22

3-
public protocol TableProtocol {
3+
/// Shared protocol for both PowerSync-managed ``Table``s as well as ``RawTable``s managed by the user.
4+
public protocol BaseTableProtocol {
45
///
56
/// The synced table name, matching sync rules.
67
///
78
var name: String { get }
9+
}
10+
11+
/// Protocol for describing ``Table``s managed by PowerSync.
12+
public protocol TableProtocol: BaseTableProtocol {
813
///
914
/// List of columns.
1015
///

0 commit comments

Comments
 (0)