Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/android/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ runs:
- name: Setup
shell: bash
run: |
rustup toolchain install nightly-2025-10-31-x86_64-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-2025-10-31-x86_64-unknown-linux-gnu
rustup toolchain install nightly-2025-12-05-x86_64-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-2025-12-05-x86_64-unknown-linux-gnu
rustup target add \
aarch64-linux-android \
armv7-linux-androideabi \
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/linux/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src
targets: aarch64-unknown-linux-gnu,x86_64-unknown-linux-gnu,i686-unknown-linux-gnu,riscv64gc-unknown-linux-gnu,armv7-unknown-linux-gnueabihf

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/macos/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src
targets: x86_64-apple-darwin,aarch64-apple-darwin

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/wasm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src

- name: Setup emsdk
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src
targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc,i686-pc-windows-msvc

Expand Down
4 changes: 2 additions & 2 deletions .github/actions/xcframework/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ runs:
- name: Setup
shell: bash
run: |
rustup toolchain install nightly-2025-10-31-aarch64-apple-darwin
rustup component add rust-src --toolchain nightly-2025-10-31-aarch64-apple-darwin
rustup toolchain install nightly-2025-12-05-aarch64-apple-darwin
rustup component add rust-src --toolchain nightly-2025-12-05-aarch64-apple-darwin
rustup target add \
x86_64-apple-darwin \
aarch64-apple-darwin \
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src,rustfmt,clippy

- name: Check formatting
Expand Down Expand Up @@ -201,15 +201,17 @@ jobs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
toolchain: nightly-2025-12-05
components: rust-src

- name: Install valgrind
run: sudo apt update && sudo apt install -y valgrind

- name: Install Cargo Valgrind
run: |
cargo install cargo-valgrind
# TODO: Use released version. Currently we rely on the git version while we wait for this
# to be released: https://github.com/jfrimmel/cargo-valgrind/commit/408c0b4fb56e84eddc2bb09c88a11ba3adc0c188
run: cargo install --git https://github.com/jfrimmel/cargo-valgrind cargo-valgrind
#run: cargo install cargo-valgrind

- name: Test Core
run: |
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/crud_vtab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::error::PowerSyncError;
use crate::ext::SafeManagedStmt;
use crate::schema::TableInfoFlags;
use crate::state::DatabaseState;
use crate::util::MAX_OP_ID;
use crate::utils::MAX_OP_ID;
use crate::vtab_util::*;

const MANUAL_NAME: &CStr = c"powersync_crud_";
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/fix_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use alloc::string::String;
use crate::create_sqlite_optional_text_fn;
use crate::error::{PSResult, PowerSyncError};
use crate::schema::inspection::ExistingTable;
use crate::utils::SqlBuffer;
use powersync_sqlite_nostd::{self as sqlite, ColumnType, Value};
use powersync_sqlite_nostd::{Connection, Context, ResultCode};

use crate::ext::SafeManagedStmt;
use crate::util::quote_identifier;

// Apply a data migration to fix any existing data affected by the issue
// fixed in v0.3.5.
Expand All @@ -33,7 +33,7 @@ pub fn apply_v035_fix(db: *mut sqlite::sqlite3) -> Result<i64, PowerSyncError> {
continue;
};

let quoted = quote_identifier(full_name);
let quoted = SqlBuffer::quote_identifier(full_name);

// language=SQLite
let statement = db.prepare_v2(&format!(
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod state;
mod sync;
mod sync_local;
mod update_hooks;
mod util;
mod utils;
mod uuid;
mod version;
mod view_admin;
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/schema/inspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use powersync_sqlite_nostd::Connection;
use powersync_sqlite_nostd::{self as sqlite, ResultCode};

use crate::error::{PSResult, PowerSyncError};
use crate::util::quote_identifier;
use crate::utils::SqlBuffer;

/// An existing PowerSync-managed view that was found in the schema.
#[derive(PartialEq)]
Expand Down Expand Up @@ -64,7 +64,7 @@ SELECT
}

pub fn drop_by_name(db: *mut sqlite::sqlite3, name: &str) -> Result<(), PowerSyncError> {
let q = format!("DROP VIEW IF EXISTS {:}", quote_identifier(name));
let q = format!("DROP VIEW IF EXISTS {:}", SqlBuffer::quote_identifier(name));
db.exec_safe(&q)?;
Ok(())
}
Expand Down
103 changes: 75 additions & 28 deletions crates/core/src/schema/management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use alloc::string::String;
use alloc::vec::Vec;
use alloc::{format, vec};
use core::ffi::c_int;
use core::fmt::Write;

use powersync_sqlite_nostd as sqlite;
use powersync_sqlite_nostd::Context;
Expand All @@ -15,8 +16,9 @@ use sqlite::{Connection, ResultCode, Value};
use crate::error::{PSResult, PowerSyncError};
use crate::ext::ExtendedDatabase;
use crate::schema::inspection::{ExistingTable, ExistingView};
use crate::schema::table_info::Index;
use crate::state::DatabaseState;
use crate::util::{quote_identifier, quote_json_path};
use crate::utils::SqlBuffer;
use crate::views::{
powersync_trigger_delete_sql, powersync_trigger_insert_sql, powersync_trigger_update_sql,
powersync_view_sql,
Expand Down Expand Up @@ -54,7 +56,7 @@ fn update_tables(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), PowerS
}

// New table.
let quoted_internal_name = quote_identifier(&table.internal_name());
let quoted_internal_name = SqlBuffer::quote_identifier(&table.internal_name());

db.exec_safe(&format!(
"CREATE TABLE {:}(id TEXT PRIMARY KEY NOT NULL, data TEXT)",
Expand Down Expand Up @@ -88,7 +90,7 @@ fn update_tables(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), PowerS
db.exec_text(
&format!(
"INSERT INTO ps_untyped(type, id, data) SELECT ?, id, data FROM {:}",
quote_identifier(&remaining.internal_name)
SqlBuffer::quote_identifier(&remaining.internal_name)
),
&remaining.name,
)
Expand All @@ -100,13 +102,39 @@ fn update_tables(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), PowerS
// We cannot have any open queries on sqlite_master at the point that we drop tables, otherwise
// we get "table is locked" errors.
for remaining in existing_tables.values() {
let q = format!("DROP TABLE {:}", quote_identifier(&remaining.internal_name));
let q = format!(
"DROP TABLE {:}",
SqlBuffer::quote_identifier(&remaining.internal_name)
);
db.exec_safe(&q).into_db_result(db)?;
}

Ok(())
}

fn create_index_stmt(table_name: &str, index_name: &str, index: &Index) -> String {
let mut sql = SqlBuffer::new();
sql.push_str("CREATE INDEX ");
let _ = sql.identifier().write_str(&index_name);
sql.push_str(" ON ");
let _ = sql.identifier().write_str(&table_name);
sql.push_char('(');
{
let mut sql = sql.comma_separated();
for indexed_column in &index.columns {
let sql = sql.element();
sql.json_extract_and_cast("data", &indexed_column.name, &indexed_column.type_name);

if !indexed_column.ascending {
sql.push_str(" DESC");
}
}
}
sql.push_char(')');

sql.sql
}

fn update_indexes(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), PowerSyncError> {
let mut statements: Vec<String> = alloc::vec![];
let mut expected_index_names: Vec<String> = vec![];
Expand Down Expand Up @@ -136,32 +164,14 @@ fn update_indexes(db: *mut sqlite::sqlite3, schema: &Schema) -> Result<(), Power
result
};

let mut column_values: Vec<String> = alloc::vec![];
for indexed_column in &index.columns {
let mut value = format!(
"CAST(json_extract(data, {:}) as {:})",
quote_json_path(&indexed_column.name),
&indexed_column.type_name
);

if !indexed_column.ascending {
value += " DESC";
}

column_values.push(value);
}

let sql = format!(
"CREATE INDEX {} ON {}({})",
quote_identifier(&index_name),
quote_identifier(&table_name),
column_values.join(", ")
);

let sql = create_index_stmt(&table_name, &index_name, index);
if existing_sql.is_none() {
statements.push(sql);
} else if existing_sql != Some(&sql) {
statements.push(format!("DROP INDEX {}", quote_identifier(&index_name)));
statements.push(format!(
"DROP INDEX {}",
SqlBuffer::quote_identifier(&index_name)
));
statements.push(sql);
}

Expand Down Expand Up @@ -190,7 +200,7 @@ SELECT
while statement.step()? == ResultCode::ROW {
let name = statement.column_text(0)?;

statements.push(format!("DROP INDEX {}", quote_identifier(name)));
statements.push(format!("DROP INDEX {}", SqlBuffer::quote_identifier(name)));
}
}

Expand Down Expand Up @@ -294,3 +304,40 @@ pub fn register(db: *mut sqlite::sqlite3, state: Rc<DatabaseState>) -> Result<()

Ok(())
}

#[cfg(test)]
mod test {
use alloc::{string::ToString, vec};

use crate::schema::table_info::{Index, IndexedColumn};

use super::create_index_stmt;

#[test]
fn test_create_index() {
let stmt = create_index_stmt(
"table",
"index",
&Index {
name: "unused".to_string(),
columns: vec![
IndexedColumn {
name: "a".to_string(),
ascending: true,
type_name: "text".to_string(),
},
IndexedColumn {
name: "b".to_string(),
ascending: false,
type_name: "integer".to_string(),
},
],
},
);

assert_eq!(
stmt,
r#"CREATE INDEX "index" ON "table"(CAST(json_extract(data, '$.a') as text), CAST(json_extract(data, '$.b') as integer) DESC)"#
)
}
}
6 changes: 6 additions & 0 deletions crates/core/src/schema/table_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ impl TableInfoFlags {
}

pub const fn insert_only(self) -> bool {
// Note: insert_only is incompatible with local_only. For backwards compatibility, we want
// to silently ignore insert_only if local_only is set.
if self.local_only() {
return false;
}

self.0 & Self::INSERT_ONLY != 0
}

Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/sync/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use serde_json::value::RawValue;
use sqlite::{ResultCode, Value};

use crate::sync::BucketPriority;
use crate::util::JsonString;
use crate::utils::JsonString;

/// Payload provided by SDKs when requesting a sync iteration.
#[derive(Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/sync/storage_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
sync_status::{ActiveStreamSubscription, DownloadSyncStatus, SyncPriorityStatus},
},
sync_local::{PartialSyncOperation, SyncOperation},
util::{JsonString, column_nullable},
utils::{JsonString, column_nullable},
};

use super::{
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/sync/subscriptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
error::{PSResult, PowerSyncError},
ext::SafeManagedStmt,
sync::BucketPriority,
util::JsonString,
utils::JsonString,
};

/// A row in the `ps_stream_subscriptions` table.
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/sync/sync_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
checkpoint::OwnedBucketChecksum, storage_adapter::StorageAdapter,
subscriptions::LocallyTrackedSubscription,
},
util::JsonString,
utils::JsonString,
};

use super::{
Expand Down
Loading