Skip to content

Commit

Permalink
Merge pull request #47 from chaindexing/support-json-fields
Browse files Browse the repository at this point in the history
Support JSON fields
  • Loading branch information
Jurshsmith authored Nov 28, 2023
2 parents a8b6ec0 + 7d6b693 commit 2f76b2e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 60 deletions.
6 changes: 5 additions & 1 deletion chaindexing/src/contract_states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,11 @@ pub fn serde_map_to_string_map(
) -> HashMap<String, String> {
serde_map.iter().fold(HashMap::new(), |mut map, (key, value)| {
if !value.is_null() {
map.insert(key.to_owned(), value.to_string().replace("\"", ""));
if value.is_object() {
map.insert(key.to_owned(), value.to_string());
} else {
map.insert(key.to_owned(), value.to_string().replace("\"", ""));
}
}

map
Expand Down
106 changes: 67 additions & 39 deletions chaindexing/src/contract_states/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub trait ContractStateMigrations: Send + Sync {
let state_versions_table_name =
extract_table_name(&create_state_versions_table_migration);
let state_versions_fields =
extract_table_fields(&create_state_versions_table_migration);
extract_table_fields(&create_state_versions_table_migration, true);

let state_versions_unique_index_migration =
get_unique_index_migration_for_state_versions(
Expand Down Expand Up @@ -96,16 +96,17 @@ fn extract_table_name(migration: &str) -> String {
.to_string()
}

fn extract_table_fields(migration: &str) -> Vec<String> {
fn extract_table_fields(migration: &str, remove_json_fields: bool) -> Vec<String> {
migration
.replace(")", "")
.split("(")
.collect::<Vec<&str>>()
.last()
.unwrap()
.split(",")
.map(|each_field| {
each_field
.filter(|field| remove_json_fields && !(field.contains("JSON") || field.contains("JSONB")))
.map(|field| {
field
.split_ascii_whitespace()
.collect::<Vec<&str>>()
.first()
Expand Down Expand Up @@ -220,13 +221,13 @@ struct DefaultMigration;
impl DefaultMigration {
pub fn get() -> String {
"state_version_group_id UUID NOT NULL,
contract_address TEXT NOT NULL,
contract_address VARCHAR NOT NULL,
chain_id INTEGER NOT NULL,
block_hash TEXT NOT NULL,
block_hash VARCHAR NOT NULL,
block_number BIGINT NOT NULL,
transaction_hash TEXT NOT NULL,
transaction_index BIGINT NOT NULL,
log_index BIGINT NOT NULL)"
transaction_hash VARCHAR NOT NULL,
transaction_index INTEGER NOT NULL,
log_index INTEGER NOT NULL)"
.to_string()
}

Expand Down Expand Up @@ -287,7 +288,7 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn returns_two_more_migrations_for_create_state_migrations() {
let contract_state = test_contract_state();
let contract_state = TestContractState;

assert_eq!(
contract_state.get_migrations().len(),
Expand All @@ -297,7 +298,7 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn appends_default_migration_to_create_state_views_migrations() {
let contract_state = test_contract_state();
let contract_state = TestContractState;
let migrations = contract_state.get_migrations();
let create_state_migration = migrations.first().unwrap();

Expand All @@ -311,7 +312,7 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn removes_repeating_default_migrations_in_create_state_views_migration() {
let contract_state = test_contract_state();
let contract_state = TestContractState;
let migrations = contract_state.get_migrations();
let create_state_migration = migrations.first().unwrap();

Expand All @@ -322,7 +323,7 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn creates_an_extra_migration_for_creating_state_versions() {
let contract_state = test_contract_state();
let contract_state = TestContractState;
let mut migrations = contract_state.get_migrations();
migrations.pop();
let create_state_versions_migration = migrations.last().unwrap();
Expand All @@ -333,7 +334,7 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn normalizes_user_primary_key_column_before_creating_state_versions_migrations() {
let contract_state = test_contract_state_with_primary_key();
let contract_state = TestContractStateWithPrimaryKey;
let mut migrations = contract_state.get_migrations();
migrations.pop();
let create_state_versions_migration = migrations.last().unwrap();
Expand All @@ -360,51 +361,78 @@ mod contract_state_migrations_get_migration_test {

#[test]
fn returns_other_migrations_untouched() {
let contract_state = test_contract_state();
let contract_state = TestContractState;

assert_eq!(
contract_state.migrations().last().unwrap(),
contract_state.get_migrations().last().unwrap()
);
}

fn test_contract_state() -> impl ContractStateMigrations {
struct TestContractState;
#[test]
fn returns_unique_index_migrations_for_state_versions() {
let contract_state = TestContractState;
let migrations = contract_state.get_migrations();

let unique_index_migration = migrations.get(2);

assert!(unique_index_migration.is_some());
assert!(unique_index_migration.unwrap().contains("CREATE UNIQUE INDEX IF NOT EXISTS"));
}

#[test]
fn ignores_json_field_in_unique_index_migration() {
let contract_state = TestContractStateWithJsonField;
let migrations = contract_state.get_migrations();

let unique_index_migration = migrations.get(2);

assert!(!unique_index_migration.unwrap().contains("json_field"));
}

impl ContractStateMigrations for TestContractState {
fn migrations(&self) -> Vec<&'static str> {
vec![
"CREATE TABLE IF NOT EXISTS nft_states (
struct TestContractState;

impl ContractStateMigrations for TestContractState {
fn migrations(&self) -> Vec<&'static str> {
vec![
"CREATE TABLE IF NOT EXISTS nft_states (
token_id INTEGER NOT NULL,
contract_address TEXT NOT NULL,
owner_address TEXT NOT NULL
contract_address VARCHAR NOT NULL,
owner_address VARCHAR NOT NULL
)",
"UPDATE nft_states
"UPDATE nft_states
SET owner_address = ''
WHERE owner_address IS NULL",
]
}
]
}

TestContractState
}

fn test_contract_state_with_primary_key() -> impl ContractStateMigrations {
struct TestContractStateWithPrimaryKey;
struct TestContractStateWithPrimaryKey;

impl ContractStateMigrations for TestContractStateWithPrimaryKey {
fn migrations(&self) -> Vec<&'static str> {
vec![
"CREATE TABLE IF NOT EXISTS nft_states (
impl ContractStateMigrations for TestContractStateWithPrimaryKey {
fn migrations(&self) -> Vec<&'static str> {
vec![
"CREATE TABLE IF NOT EXISTS nft_states (
id SERIAL PRIMARY KEY,
token_id INTEGER NOT NULL,
contract_address TEXT NOT NULL,
owner_address TEXT NOT NULL
contract_address VARCHAR NOT NULL,
owner_address VARCHAR NOT NULL
)",
]
}
]
}
}

TestContractStateWithPrimaryKey
struct TestContractStateWithJsonField;

impl ContractStateMigrations for TestContractStateWithJsonField {
fn migrations(&self) -> Vec<&'static str> {
vec![
"CREATE TABLE IF NOT EXISTS nft_states (
id SERIAL PRIMARY KEY,
token_id INTEGER NOT NULL,
json_field JSON DEFAULT '{}',
)",
]
}
}
}
16 changes: 8 additions & 8 deletions chaindexing/src/diesels/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ diesel::table! {
next_block_number_to_ingest_from -> Int8,
next_block_number_to_handle_from -> Int8,
start_block_number -> Int8,
address -> Text,
contract_name -> Text,
address -> VarChar,
contract_name -> VarChar,
}
}

diesel::table! {
chaindexing_events (id) {
id -> Uuid,
chain_id -> Int4,
contract_address -> Text,
contract_name -> Text,
contract_address -> VarChar,
contract_name -> VarChar,
abi -> Text,
log_params -> Json,
parameters -> Json,
topics -> Json,
block_hash -> Text,
block_hash -> VarChar,
block_number -> Int8,
block_timestamp -> Int8,
transaction_hash -> Text,
transaction_index -> Int8,
log_index -> Int8,
transaction_hash -> VarChar,
transaction_index -> Int4,
log_index -> Int4,
removed -> Bool,
inserted_at -> Timestamptz,
}
Expand Down
8 changes: 4 additions & 4 deletions chaindexing/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ pub struct Event {
pub block_number: i64,
pub block_timestamp: i64,
pub transaction_hash: String,
pub transaction_index: i64,
pub log_index: i64,
pub transaction_index: i32,
pub log_index: i32,
removed: bool,
inserted_at: chrono::NaiveDateTime,
}
Expand Down Expand Up @@ -92,8 +92,8 @@ impl Event {
block_number: log.block_number.unwrap().as_u64() as i64,
block_timestamp,
transaction_hash: hashes::h256_to_string(&log.transaction_hash.unwrap()).to_lowercase(),
transaction_index: log.transaction_index.unwrap().as_u64() as i64,
log_index: log.log_index.unwrap().as_u64() as i64,
transaction_index: log.transaction_index.unwrap().as_u32() as i32,
log_index: log.log_index.unwrap().as_u32() as i32,
removed: log.removed.unwrap(),
inserted_at: chrono::Utc::now().naive_utc(),
}
Expand Down
16 changes: 8 additions & 8 deletions chaindexing/src/repos/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ impl SQLikeMigrations {
&[
"CREATE TABLE IF NOT EXISTS chaindexing_contract_addresses (
id SERIAL PRIMARY KEY,
address TEXT NOT NULL,
contract_name TEXT NOT NULL,
address VARCHAR NOT NULL,
contract_name VARCHAR NOT NULL,
chain_id INTEGER NOT NULL,
start_block_number BIGINT NOT NULL,
next_block_number_to_ingest_from BIGINT NULL,
Expand All @@ -213,18 +213,18 @@ impl SQLikeMigrations {
"CREATE TABLE IF NOT EXISTS chaindexing_events (
id uuid PRIMARY KEY,
chain_id INTEGER NOT NULL,
contract_address TEXT NOT NULL,
contract_name TEXT NOT NULL,
contract_address VARCHAR NOT NULL,
contract_name VARCHAR NOT NULL,
abi TEXT NOT NULL,
log_params JSON NOT NULL,
parameters JSON NOT NULL,
topics JSON NOT NULL,
block_hash TEXT NOT NULL,
block_hash VARCHAR NOT NULL,
block_number BIGINT NOT NULL,
block_timestamp BIGINT NOT NULL,
transaction_hash TEXT NOT NULL,
transaction_index BIGINT NOT NULL,
log_index BIGINT NOT NULL,
transaction_hash VARCHAR NOT NULL,
transaction_index INTEGER NOT NULL,
log_index INTEGER NOT NULL,
removed BOOLEAN NOT NULL,
inserted_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)",
Expand Down

0 comments on commit 2f76b2e

Please sign in to comment.