v0.3.4-pre.002
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
DO $ksp$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'pk_ksp_raw_account_states'
|
||||
AND conrelid = to_regclass('ksp_raw_account_states')
|
||||
) THEN
|
||||
ALTER TABLE ksp_raw_account_states ADD CONSTRAINT pk_ksp_raw_account_states PRIMARY KEY (pubkey, slot, state_hash);
|
||||
END IF;
|
||||
END
|
||||
$ksp$;
|
||||
@@ -0,0 +1,12 @@
|
||||
DO $ksp$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'pk_ksp_raw_account_observations'
|
||||
AND conrelid = to_regclass('ksp_raw_account_observations')
|
||||
) THEN
|
||||
ALTER TABLE ksp_raw_account_observations ADD CONSTRAINT pk_ksp_raw_account_observations PRIMARY KEY (observation_key);
|
||||
END IF;
|
||||
END
|
||||
$ksp$;
|
||||
@@ -0,0 +1,14 @@
|
||||
DO $ksp$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'fk_ksp_raw_account_observations_state'
|
||||
AND conrelid = to_regclass('ksp_raw_account_observations')
|
||||
) THEN
|
||||
ALTER TABLE ksp_raw_account_observations
|
||||
ADD CONSTRAINT fk_ksp_raw_account_observations_state FOREIGN KEY (account_pubkey, account_slot, account_state_hash)
|
||||
REFERENCES ksp_raw_account_states(pubkey, slot, state_hash) ON DELETE RESTRICT;
|
||||
END IF;
|
||||
END
|
||||
$ksp$;
|
||||
@@ -0,0 +1,19 @@
|
||||
CREATE TABLE IF NOT EXISTS ksp_raw_account_states (
|
||||
pubkey BYTEA NOT NULL,
|
||||
slot NUMERIC(20, 0) NOT NULL,
|
||||
state_hash BYTEA NOT NULL,
|
||||
lamports NUMERIC(20, 0) NOT NULL,
|
||||
owner BYTEA NOT NULL,
|
||||
executable BOOLEAN NOT NULL,
|
||||
rent_epoch NUMERIC(20, 0) NOT NULL,
|
||||
data BYTEA NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS pubkey BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS slot NUMERIC(20, 0) NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS state_hash BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS lamports NUMERIC(20, 0) NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS owner BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS executable BOOLEAN NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS rent_epoch NUMERIC(20, 0) NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_states ADD COLUMN IF NOT EXISTS data BYTEA NOT NULL;
|
||||
@@ -0,0 +1,41 @@
|
||||
CREATE TABLE IF NOT EXISTS ksp_raw_account_observations (
|
||||
observation_key BYTEA NOT NULL,
|
||||
account_pubkey BYTEA NOT NULL,
|
||||
account_slot NUMERIC(20, 0) NOT NULL,
|
||||
account_state_hash BYTEA NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
protocol TEXT NOT NULL,
|
||||
acquisition_method TEXT NOT NULL,
|
||||
origin TEXT NOT NULL,
|
||||
received_at_unix_millis BIGINT NOT NULL,
|
||||
capture_session_id TEXT NULL,
|
||||
commitment TEXT NULL,
|
||||
endpoint_id TEXT NULL,
|
||||
filter_id TEXT NULL,
|
||||
observed_at_unix_millis BIGINT NULL,
|
||||
source_payload_hash BYTEA NULL,
|
||||
source_payload_size_bytes BIGINT NULL,
|
||||
is_startup BOOLEAN NULL,
|
||||
transaction_signature BYTEA NULL,
|
||||
write_version NUMERIC(20, 0) NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS observation_key BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS account_pubkey BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS account_slot NUMERIC(20, 0) NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS account_state_hash BYTEA NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS provider TEXT NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS protocol TEXT NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS acquisition_method TEXT NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS origin TEXT NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS received_at_unix_millis BIGINT NOT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS capture_session_id TEXT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS commitment TEXT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS endpoint_id TEXT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS filter_id TEXT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS observed_at_unix_millis BIGINT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS source_payload_hash BYTEA NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS source_payload_size_bytes BIGINT NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS is_startup BOOLEAN NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS transaction_signature BYTEA NULL;
|
||||
ALTER TABLE ksp_raw_account_observations ADD COLUMN IF NOT EXISTS write_version NUMERIC(20, 0) NULL;
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/src/lib.rs
|
||||
// version: 14
|
||||
// version: 15
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -21,6 +21,8 @@
|
||||
//! with compare-and-transition outcomes and explicit rejection of `Compacted`.
|
||||
//! `0.3.3-pre.008` implements all six `RawTransaction*` capabilities directly on
|
||||
//! `PostgresBackend` while preserving the existing narrow backend bridge.
|
||||
//! `0.3.4-pre.002` registers additive V002 and its two minimal RAW account
|
||||
//! tables with canonical state/observation PKs and the observation-state FK.
|
||||
//!
|
||||
//! This crate depends on `ksp-store-api` and never on `ksp-store-lib`. The
|
||||
//! common facade consumes only this crate's narrow backend bridge and never
|
||||
@@ -93,6 +95,8 @@ pub(crate) use self::schema::SchemaResourceState;
|
||||
pub(crate) use self::schema::V000_RESOURCES;
|
||||
/// Private V001 schema resource inventory consumed by the migration engine.
|
||||
pub(crate) use self::schema::V001_RESOURCES;
|
||||
/// Private V002 schema resource inventory consumed by the migration engine.
|
||||
pub(crate) use self::schema::V002_RESOURCES;
|
||||
/// Private physical schema resource inspector consumed by the migration engine.
|
||||
pub(crate) use self::schema::inspect_resource;
|
||||
/// Private V001 adoption probe consumed by the migration engine.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/src/migration.rs
|
||||
// version: 7
|
||||
// version: 8
|
||||
|
||||
use sha2::Digest; // rust-rules: trait-import
|
||||
|
||||
@@ -19,6 +19,13 @@ const EMBEDDED_MIGRATIONS: &[EmbeddedMigration] = &[
|
||||
resources: crate::V001_RESOURCES,
|
||||
version: 1,
|
||||
},
|
||||
EmbeddedMigration {
|
||||
checksum: MigrationChecksum::Resources,
|
||||
hook: MigrationHook::None,
|
||||
name: "raw_account_state",
|
||||
resources: crate::V002_RESOURCES,
|
||||
version: 2,
|
||||
},
|
||||
];
|
||||
const HEX_LOWER: &[u8; 16] = b"0123456789abcdef";
|
||||
const HISTORY_INSERT_SQL: &str = "INSERT INTO ksp_store_schema_migrations (version, name, checksum, applied_at) VALUES ($1, $2, $3, CURRENT_TIMESTAMP)";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/src/schema.rs
|
||||
// version: 7
|
||||
// version: 8
|
||||
|
||||
/// Immutable V000 physical schema resource inventory.
|
||||
pub(crate) const V000_RESOURCES: &[SchemaResource] = &[SchemaResource {
|
||||
@@ -378,6 +378,55 @@ pub(crate) const V001_RESOURCES: &[SchemaResource] = &[
|
||||
sql: include_str!("../migrations/v001_raw_transaction/indexes/001_ix_ksp_raw_transactions_slot_signature.sql"),
|
||||
},
|
||||
];
|
||||
/// V002 physical schema resource inventory for the minimal RAW account state foundation.
|
||||
pub(crate) const V002_RESOURCES: &[SchemaResource] = &[
|
||||
SchemaResource {
|
||||
id: "tables/001_ksp_raw_account_states.sql",
|
||||
object: SchemaObjectContract::Table(TableContract {
|
||||
columns: RAW_ACCOUNT_STATES_COLUMNS,
|
||||
name: "ksp_raw_account_states",
|
||||
primary_key_columns: std::option::Option::None,
|
||||
}),
|
||||
repair_existing: true,
|
||||
sql: include_str!("../migrations/v002_raw_account_state/tables/001_ksp_raw_account_states.sql"),
|
||||
},
|
||||
SchemaResource {
|
||||
id: "tables/002_ksp_raw_account_observations.sql",
|
||||
object: SchemaObjectContract::Table(TableContract {
|
||||
columns: RAW_ACCOUNT_OBSERVATIONS_COLUMNS,
|
||||
name: "ksp_raw_account_observations",
|
||||
primary_key_columns: std::option::Option::None,
|
||||
}),
|
||||
repair_existing: true,
|
||||
sql: include_str!("../migrations/v002_raw_account_state/tables/002_ksp_raw_account_observations.sql"),
|
||||
},
|
||||
SchemaResource {
|
||||
id: "constraints/001_pk_ksp_raw_account_states.sql",
|
||||
object: SchemaObjectContract::Constraint(ConstraintContract { kind: "p", name: "pk_ksp_raw_account_states", table: "ksp_raw_account_states" }),
|
||||
repair_existing: true,
|
||||
sql: include_str!("../migrations/v002_raw_account_state/constraints/001_pk_ksp_raw_account_states.sql"),
|
||||
},
|
||||
SchemaResource {
|
||||
id: "constraints/002_pk_ksp_raw_account_observations.sql",
|
||||
object: SchemaObjectContract::Constraint(ConstraintContract {
|
||||
kind: "p",
|
||||
name: "pk_ksp_raw_account_observations",
|
||||
table: "ksp_raw_account_observations",
|
||||
}),
|
||||
repair_existing: true,
|
||||
sql: include_str!("../migrations/v002_raw_account_state/constraints/002_pk_ksp_raw_account_observations.sql"),
|
||||
},
|
||||
SchemaResource {
|
||||
id: "constraints/003_fk_ksp_raw_account_observations_state.sql",
|
||||
object: SchemaObjectContract::Constraint(ConstraintContract {
|
||||
kind: "f",
|
||||
name: "fk_ksp_raw_account_observations_state",
|
||||
table: "ksp_raw_account_observations",
|
||||
}),
|
||||
repair_existing: true,
|
||||
sql: include_str!("../migrations/v002_raw_account_state/constraints/003_fk_ksp_raw_account_observations_state.sql"),
|
||||
},
|
||||
];
|
||||
|
||||
const COLUMN_LOAD_SQL: &str = r#"SELECT column_name::TEXT, udt_name::TEXT, (is_nullable = 'YES') AS nullable, numeric_precision::INTEGER, numeric_scale::INTEGER, column_default::TEXT, is_identity::TEXT, is_generated::TEXT
|
||||
FROM information_schema.columns
|
||||
@@ -710,6 +759,199 @@ const RAW_TRANSACTION_OBSERVATIONS_COLUMNS: &[ColumnContract] = &[
|
||||
udt_name: "int8",
|
||||
},
|
||||
];
|
||||
const RAW_ACCOUNT_STATES_COLUMNS: &[ColumnContract] = &[
|
||||
ColumnContract {
|
||||
name: "pubkey",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "slot",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::Some(20),
|
||||
numeric_scale: std::option::Option::Some(0),
|
||||
udt_name: "numeric",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "state_hash",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "lamports",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::Some(20),
|
||||
numeric_scale: std::option::Option::Some(0),
|
||||
udt_name: "numeric",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "owner",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "executable",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bool",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "rent_epoch",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::Some(20),
|
||||
numeric_scale: std::option::Option::Some(0),
|
||||
udt_name: "numeric",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "data",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
];
|
||||
const RAW_ACCOUNT_OBSERVATIONS_COLUMNS: &[ColumnContract] = &[
|
||||
ColumnContract {
|
||||
name: "observation_key",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "account_pubkey",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "account_slot",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::Some(20),
|
||||
numeric_scale: std::option::Option::Some(0),
|
||||
udt_name: "numeric",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "account_state_hash",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "provider",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "protocol",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "acquisition_method",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "origin",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "received_at_unix_millis",
|
||||
nullable: false,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "int8",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "capture_session_id",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "commitment",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "endpoint_id",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "filter_id",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "text",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "observed_at_unix_millis",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "int8",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "source_payload_hash",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "source_payload_size_bytes",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "int8",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "is_startup",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bool",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "transaction_signature",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::None,
|
||||
numeric_scale: std::option::Option::None,
|
||||
udt_name: "bytea",
|
||||
},
|
||||
ColumnContract {
|
||||
name: "write_version",
|
||||
nullable: true,
|
||||
numeric_precision: std::option::Option::Some(20),
|
||||
numeric_scale: std::option::Option::Some(0),
|
||||
udt_name: "numeric",
|
||||
},
|
||||
];
|
||||
const RAW_TRANSACTION_ARCHIVE_PAYLOADS_COLUMNS: &[ColumnContract] = &[
|
||||
ColumnContract {
|
||||
name: "signature",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/dependency_boundary.rs
|
||||
// version: 14
|
||||
// version: 15
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -23,6 +23,7 @@ fn pre_005_backend_owns_exact_physical_runtime_dependencies_without_reverse_faca
|
||||
let bootstrap_sql = include_str!("../migrations/v000_bootstrap/tables/001_ksp_store_schema_migrations.sql");
|
||||
assert!(migration.contains("crate::V000_RESOURCES"));
|
||||
assert!(migration.contains("crate::V001_RESOURCES"));
|
||||
assert!(migration.contains("crate::V002_RESOURCES"));
|
||||
assert!(schema.contains("../migrations/v000_bootstrap/tables/001_ksp_store_schema_migrations.sql"));
|
||||
assert!(schema.contains("../migrations/v001_raw_transaction/tables/001_ksp_store_identity.sql"));
|
||||
assert!(bootstrap_sql.contains("ksp_store_schema_migrations"));
|
||||
@@ -113,7 +114,7 @@ fn pre_003_fix_001_migration_engine_uses_split_schema_contract_and_binds_network
|
||||
assert!(observation_table.contains("CREATE TABLE IF NOT EXISTS ksp_raw_transaction_observations"));
|
||||
assert!(archive_table.contains("CREATE TABLE IF NOT EXISTS ksp_raw_transaction_archive_payloads"));
|
||||
assert!(index.contains("CREATE INDEX IF NOT EXISTS ix_ksp_raw_transactions_slot_signature"));
|
||||
for forbidden in ["impl ksp_store_api::RawTransaction", "repository", "sqlx", "RawAccountState"] {
|
||||
for forbidden in ["impl ksp_store_api::RawTransaction", "impl ksp_store_api::RawAccount", "repository", "sqlx"] {
|
||||
assert!(!migration.contains(forbidden), "repository/cross-scope implementation leaked into migration engine: {forbidden}");
|
||||
assert!(!schema.contains(forbidden), "repository/cross-scope implementation leaked into schema contract: {forbidden}");
|
||||
}
|
||||
@@ -124,6 +125,25 @@ fn pre_003_fix_001_migration_engine_uses_split_schema_contract_and_binds_network
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_v002_is_migration_only_and_does_not_open_account_repository_or_runtime_dispatch() {
|
||||
let crate_root = include_str!("../src/lib.rs");
|
||||
let migration = include_str!("../src/migration.rs");
|
||||
let schema = include_str!("../src/schema.rs");
|
||||
let runtime = include_str!("../src/runtime.rs");
|
||||
let states = include_str!("../migrations/v002_raw_account_state/tables/001_ksp_raw_account_states.sql");
|
||||
let observations = include_str!("../migrations/v002_raw_account_state/tables/002_ksp_raw_account_observations.sql");
|
||||
assert!(migration.contains("name: \"raw_account_state\""));
|
||||
assert!(migration.contains("resources: crate::V002_RESOURCES"));
|
||||
assert!(schema.contains("pub(crate) const V002_RESOURCES"));
|
||||
assert!(states.contains("ksp_raw_account_states"));
|
||||
assert!(observations.contains("ksp_raw_account_observations"));
|
||||
assert!(!crate_root.contains("mod raw_account;"));
|
||||
assert!(!runtime.contains("impl ksp_store_api::RawAccount"));
|
||||
assert!(!std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/raw_account.rs").exists());
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_004_raw_read_sql_and_mapping_remain_backend_private() {
|
||||
let crate_root = include_str!("../src/lib.rs");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
|
||||
// version: 11
|
||||
// version: 12
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -279,7 +279,9 @@ fn pre_010_raw_transaction_capability_implementation_inventory_is_exact_and_raw_
|
||||
assert!(!runtime.contains(forbidden), "RawAccountState scope opened during RawTransaction hardening: {forbidden}");
|
||||
}
|
||||
let migration = include_str!("../src/migration.rs");
|
||||
assert!(!migration.contains("ksp_raw_account"));
|
||||
assert!(migration.contains("raw_account_state"));
|
||||
assert!(migration.contains("crate::V002_RESOURCES"));
|
||||
assert!(!runtime.contains("mod raw_account"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/postgres_foundation_live.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -153,7 +153,7 @@ async fn run_foundation_scenario(admin: &mut tokio_postgres::Client, uri: &str,
|
||||
}
|
||||
*owns_schema = true;
|
||||
let initial_health = initial.health().await;
|
||||
if !initial_health.is_ready() || initial_health.migration_version() != std::option::Option::Some(1) || initial_health.pending_migration_count() != 0 {
|
||||
if !initial_health.is_ready() || initial_health.migration_version() != std::option::Option::Some(2) || initial_health.pending_migration_count() != 0 {
|
||||
return std::result::Result::Err(LiveFailure::new("initial_health"));
|
||||
}
|
||||
let initial_close = close_backend(initial).await;
|
||||
@@ -167,7 +167,7 @@ async fn run_foundation_scenario(admin: &mut tokio_postgres::Client, uri: &str,
|
||||
};
|
||||
let idempotent_health = idempotent.health().await;
|
||||
if !idempotent_health.is_ready()
|
||||
|| idempotent_health.migration_version() != std::option::Option::Some(1)
|
||||
|| idempotent_health.migration_version() != std::option::Option::Some(2)
|
||||
|| idempotent_health.pending_migration_count() != 0
|
||||
{
|
||||
return std::result::Result::Err(LiveFailure::new("idempotent_health"));
|
||||
@@ -250,7 +250,7 @@ async fn run_foundation_scenario(admin: &mut tokio_postgres::Client, uri: &str,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let final_health = final_backend.health().await;
|
||||
if !final_health.is_ready() || final_health.migration_version() != std::option::Option::Some(1) || final_health.pending_migration_count() != 0 {
|
||||
if !final_health.is_ready() || final_health.migration_version() != std::option::Option::Some(2) || final_health.pending_migration_count() != 0 {
|
||||
return std::result::Result::Err(LiveFailure::new("final_health"));
|
||||
}
|
||||
return close_backend(final_backend).await;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/postgres_raw_transaction_live.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -150,7 +150,7 @@ async fn run_raw_transaction_scenario(admin: &mut tokio_postgres::Client, uri: &
|
||||
};
|
||||
*owns_schema = true;
|
||||
let initial_health = initial.health().await;
|
||||
if !initial_health.is_ready() || initial_health.migration_version() != std::option::Option::Some(1) || initial_health.pending_migration_count() != 0 {
|
||||
if !initial_health.is_ready() || initial_health.migration_version() != std::option::Option::Some(2) || initial_health.pending_migration_count() != 0 {
|
||||
return std::result::Result::Err(LiveFailure::new("initial_health"));
|
||||
}
|
||||
let wrong_network_result = open_backend_result(uri, "testnet", true, true).await;
|
||||
@@ -211,7 +211,7 @@ async fn run_raw_transaction_scenario(admin: &mut tokio_postgres::Client, uri: &
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let reopened_health = reopened.health().await;
|
||||
if !reopened_health.is_ready() || reopened_health.migration_version() != std::option::Option::Some(1) {
|
||||
if !reopened_health.is_ready() || reopened_health.migration_version() != std::option::Option::Some(2) {
|
||||
return std::result::Result::Err(LiveFailure::new("reopen_health"));
|
||||
}
|
||||
let reference_result = raw_reference(10);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/unit_tests/migration.rs
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
fn applied(version: i64, name: &str, checksum: &str) -> super::AppliedMigration {
|
||||
return super::AppliedMigration { checksum: checksum.to_owned(), name: name.to_owned(), version };
|
||||
@@ -17,7 +17,7 @@ fn embedded(version: i64, name: &'static str, resources: &'static [crate::Schema
|
||||
|
||||
#[test]
|
||||
fn pre_003_fix_001_embedded_registry_keeps_v000_checksum_and_uses_resource_owned_v001() {
|
||||
assert_eq!(super::EMBEDDED_MIGRATIONS.len(), 2);
|
||||
assert!(super::EMBEDDED_MIGRATIONS.len() >= 2);
|
||||
let v000 = &super::EMBEDDED_MIGRATIONS[0];
|
||||
assert_eq!(v000.version, 0);
|
||||
assert_eq!(v000.name, "bootstrap");
|
||||
@@ -32,7 +32,29 @@ fn pre_003_fix_001_embedded_registry_keeps_v000_checksum_and_uses_resource_owned
|
||||
assert_eq!(v001.resources.len(), 40);
|
||||
assert_eq!(super::migration_checksum(v001), "31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51");
|
||||
assert!(super::validate_embedded_registry(super::EMBEDDED_MIGRATIONS).is_ok());
|
||||
assert_eq!(crate::current_migration_version(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_v002_registry_is_additive_minimal_and_keeps_v000_v001_checksums_stable() {
|
||||
assert_eq!(super::EMBEDDED_MIGRATIONS.len(), 3);
|
||||
let v000 = &super::EMBEDDED_MIGRATIONS[0];
|
||||
let v001 = &super::EMBEDDED_MIGRATIONS[1];
|
||||
let v002 = &super::EMBEDDED_MIGRATIONS[2];
|
||||
assert_eq!(super::migration_checksum(v000), "d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450");
|
||||
assert_eq!(super::migration_checksum(v001), "31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51");
|
||||
assert_eq!(v002.version, 2);
|
||||
assert_eq!(v002.name, "raw_account_state");
|
||||
assert_eq!(v002.hook, super::MigrationHook::None);
|
||||
assert_eq!(v002.resources.len(), 5);
|
||||
assert!(super::validate_embedded_registry(super::EMBEDDED_MIGRATIONS).is_ok());
|
||||
assert_eq!(crate::current_migration_version(), 2);
|
||||
let full = [
|
||||
applied(0, v000.name, super::migration_checksum(v000).as_str()),
|
||||
applied(1, v001.name, super::migration_checksum(v001).as_str()),
|
||||
applied(2, v002.name, super::migration_checksum(v002).as_str()),
|
||||
];
|
||||
assert_eq!(super::validate_history(&full, super::EMBEDDED_MIGRATIONS).ok(), std::option::Option::Some(3));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/unit_tests/schema.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
fn actual_column(name: &str, udt_name: &str, nullable: bool) -> super::ActualColumn {
|
||||
return super::ActualColumn {
|
||||
@@ -48,6 +48,37 @@ fn pre_003_fix_001_v001_resources_are_split_and_idempotent_by_object_family() {
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_v002_resources_are_exactly_two_tables_plus_base_pk_fk_without_indexes_or_domain_checks() {
|
||||
assert_eq!(crate::V002_RESOURCES.len(), 5);
|
||||
let ids = crate::V002_RESOURCES.iter().map(|resource| return resource.id).collect::<std::vec::Vec<_>>();
|
||||
assert_eq!(ids[..2], ["tables/001_ksp_raw_account_states.sql", "tables/002_ksp_raw_account_observations.sql"]);
|
||||
assert_eq!(
|
||||
ids[2..],
|
||||
[
|
||||
"constraints/001_pk_ksp_raw_account_states.sql",
|
||||
"constraints/002_pk_ksp_raw_account_observations.sql",
|
||||
"constraints/003_fk_ksp_raw_account_observations_state.sql",
|
||||
]
|
||||
);
|
||||
let sql = crate::V002_RESOURCES.iter().map(|resource| return resource.sql).collect::<std::vec::Vec<_>>().concat();
|
||||
for required in [
|
||||
"CREATE TABLE IF NOT EXISTS ksp_raw_account_states",
|
||||
"CREATE TABLE IF NOT EXISTS ksp_raw_account_observations",
|
||||
"slot NUMERIC(20, 0) NOT NULL",
|
||||
"write_version NUMERIC(20, 0) NULL",
|
||||
"PRIMARY KEY (pubkey, slot, state_hash)",
|
||||
"PRIMARY KEY (observation_key)",
|
||||
"FOREIGN KEY (account_pubkey, account_slot, account_state_hash) REFERENCES ksp_raw_account_states(pubkey, slot, state_hash) ON DELETE RESTRICT",
|
||||
] {
|
||||
assert!(sql.contains(required), "V002 pre.002 physical foundation is missing: {required}");
|
||||
}
|
||||
for forbidden in ["CREATE INDEX", " CHECK ", "ON DELETE CASCADE", "BIGSERIAL", "slot BIGINT", "data TEXT"] {
|
||||
assert!(!sql.contains(forbidden), "pre.002 advanced V002 beyond the minimal table/PK/FK scope: {forbidden}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_003_fix_001_external_extra_columns_are_accepted_only_when_they_cannot_block_ksp_inserts() {
|
||||
let nullable = actual_column("external_nullable", "text", true);
|
||||
|
||||
Reference in New Issue
Block a user