Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: binary storage db #153

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

nuts-rice
Copy link

Feature

addresses #141
provides option to store objects as binary instead of hex strings for no-code projects

How?

config field for PostgresDetails , wrapping objects using sql_wrapper types

Copy link

vercel bot commented Jan 7, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
rindexer-documentation ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 15, 2025 10:23pm

@joshstevens19
Copy link
Owner

joshstevens19 commented Jan 7, 2025

great thanks for this its not a hard PR if you wanted to do it:

pub fn map_log_params_to_ethereum_wrapper(
    abi_inputs: &[ABIInput],
    params: &[LogParam],
    binary_mode: bool,
) -> Vec<EthereumSqlTypeWrapper> {

we can then create a new method which is called map_ethereum_wrapper_to_byte which maps the type to the byte type which can be done when binary_mode is true

pub fn map_log_params_to_ethereum_wrapper(
    abi_inputs: &[ABIInput],
    params: &[LogParam],
    binary_mode: bool,
) -> Vec<EthereumSqlTypeWrapper> {
    let mut wrappers = vec![];

    for (index, param) in params.iter().enumerate() {
        if let Some(abi_input) = abi_inputs.get(index) {
            match &param.value {
                Token::Tuple(tuple) => {
                
                   // TODO: CHECK IF binary_mode IS TRUE AND IF SO WRAP process_tuple RESULT IN map_ethereum_wrapper_to_byte
                 
                    wrappers.extend(process_tuple(
                        abi_input
                            .components
                            .as_ref()
                            .expect("tuple should have a component ABI on"),
                        tuple,
                    ));
                }
                _ => {
                    // TODO: CHECK IF binary_mode IS TRUE AND IF SO WRAP map_log_token_to_ethereum_wrapper RESULT IN map_ethereum_wrapper_to_byte
                    
                    wrappers.push(map_log_token_to_ethereum_wrapper(abi_input, &param.value));
                }
            }
        } else {
            panic!("No ABI input found for log param at index: {}", index)
        }
    }

    wrappers
}

we then just need to change https://github.com/joshstevens19/rindexer/blob/master/core/src/database/postgres/generate.rs#L42

extending it to have a binary_mode: bool, and if thats the case we can change the generate_columns_with_data_types to consider the types possible to be binary and if so use BYTEA instead

then thats it bingo - we bring in the config setting you put above and add to docs @nuts-rice fancy it?

@nuts-rice
Copy link
Author

Yup ill get to it 😎

@nuts-rice nuts-rice marked this pull request as ready for review January 9, 2025 13:32
Copy link
Owner

@joshstevens19 joshstevens19 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh sorry i think you went a bit crazy with the bytes

the only thing which can be bytes are address (handle array), bytes (handle array), + main tables tx hash, block hash, contract address so this is why i suggest above we turn this to max_optimisation we can then make:

uint256 NUMERIC(80) as well (fixing the VARCHAR(78)) we use

and then pass in optimisations on the solidity_type_to_db_type alongside fix the other bits

@@ -170,6 +170,7 @@ pub fn handle_new_command(
postgres: if postgres_enabled {
Some(PostgresDetails {
enabled: true,
binary_storage: None,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should actually be called "max_optimisation"

@@ -53,7 +54,15 @@ fn generate_event_table_sql_with_comments(
let event_columns = if event_info.inputs.is_empty() {
"".to_string()
} else {
generate_columns_with_data_types(&event_info.inputs).join(", ") + ","
if binary_mode {
generate_columns_with_data_types(&event_info.inputs)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not everything can be stored in bytes like booleans etc we only want to store hex stuff as bytes so i think you need to filter out based on the solidity type which ones to do?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use a .filter() or .filter_map() for this? I'm not sure exactly

.expect("tuple should have a component ABI on"),
tuple,
));
map_ethereum_wrapper_to_byte(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be in wrappers.extend

@@ -960,6 +980,20 @@ pub fn map_log_params_to_ethereum_wrapper(
));
}
_ => {
if binary_mode {
wrappers.push(map_log_token_to_ethereum_wrapper(abi_input, &param.value));
map_ethereum_wrapper_to_byte(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be in wrappers.extend

if binary_mode {
generate_columns_with_data_types(&event_info.inputs)
.iter()
.map(|column| format!("{} BYTEA", column))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for arrays it has to be BYTEA[]

let bytes = bytes::Bytes::from(bytes);
bytes
}
EthereumSqlTypeWrapper::String(s) |
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we wouldnt convert strings to bytea i dont think - just hex string values because it wont be about to handle UTF8 and graphql wont be able to get the correct values back

let bytes = bytes::Bytes::from(buf);
bytes
}
EthereumSqlTypeWrapper::DateTime(date_time) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not turn datetime to bytea

let bytes = bytes::Bytes::from(date_time.to_rfc3339().as_bytes().to_vec());
bytes
}
EthereumSqlTypeWrapper::JSONB(json) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not convert JSONB to bytea

@@ -971,6 +1005,373 @@ pub fn map_log_params_to_ethereum_wrapper(
wrappers
}

pub fn map_ethereum_wrapper_to_byte(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only thing which can be bytes are address (handle array), bytes, + main tables tx hash, block hash, contract address so this is why i suggest above we turn this to max_optimisation we can then make:

uint256 NUMBER(80)

and then pass in optimisations on the solidity_type_to_db_type

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so should solidity_type_to_db_type have the max_optimisation field too?

@nuts-rice nuts-rice marked this pull request as draft January 11, 2025 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants