### Sqllogictest .slt File Format: Create Table Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Example of a .slt file snippet demonstrating how to create a table using the 'statement ok' command. Comments are supported using '#'. ```text # Comments begin with '#' statement ok CREATE TABLE foo AS VALUES(1,2),(2,3); ``` -------------------------------- ### Install sqllogictest-bin CLI Tool Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Installs the sqllogictest-bin command-line interface tool using Cargo. This tool is used to run sqllogictest files against various SQL databases. ```sh cargo install sqllogictest-bin ``` -------------------------------- ### Sqllogictest .slt File Format: Query Success Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Example of a .slt file snippet for running a query that is expected to succeed. Specifies the output column types ('II' for two integers) and sorts the output for comparison. ```text # 'II' means two integer output columns # rowsort means to sort the output before comparing query II rowsort SELECT * FROM foo; ---- 3 4 4 5 ``` -------------------------------- ### Using Special Variables in SQL Logic Tests Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Demonstrates the use of special variables within SQL queries and statements. These variables provide access to the temporary test directory, current timestamp, and database name, simplifying test setup and data handling. Variable substitution needs to be enabled for these to work. ```sql SELECT '${UNDEFINED:$FALLBACK_VAR}' -- fallback_value COPY users TO '$__TEST_DIR__/users_backup.csv' WITH CSV INSERT INTO events(ts) VALUES ($__NOW__) SELECT current_database() -- $__DATABASE__ SELECT '\$literal_dollar' -- $literal_dollar ``` -------------------------------- ### Enable Parallel Test Execution in Rust Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Configure sqllogictest-rs to run tests in parallel, improving execution speed, especially in CI environments. Each test file can be assigned its own isolated database instance, preventing data conflicts between concurrent test runs. The `run_parallel` method facilitates this setup. ```rust use sqllogictest::{Runner, AsyncDB, DBOutput, DefaultColumnType}; use async_trait::async_trait; struct ParallelDB { db_name: String, } #[async_trait] impl AsyncDB for ParallelDB { type Error = String; type ColumnType = DefaultColumnType; async fn run(&mut self, sql: &str) -> Result, Self::Error> { // Use self.db_name for isolated database access Ok(DBOutput::StatementComplete(0)) } async fn shutdown(&mut self) {} } async fn connect(host: String, db_name: String) -> ParallelDB { ParallelDB { db_name } } #[tokio::main] async fn main() { let hosts = vec!["localhost:5432".to_string()]; let mut runner = Runner::new(|| async { Ok(ParallelDB { db_name: "default".to_string() }) }); // Run tests in parallel with 4 workers runner.run_parallel( "tests/**/*.slt", hosts, |host, db_name| connect(host, db_name), 4, // number of parallel jobs ).await.expect("parallel tests failed"); } ``` -------------------------------- ### Sqllogictest .slt File Format: System Commands Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Illustrates using the 'system ok' command in .slt files to execute external shell commands and verify their exit codes or standard output. ```text system ok exit 0 # The runner will check the exit code of the command, and this will fail. system ok exit 1 # Check the output of the command. Same as `error`, empty lines (not consecutive) are allowed, and 2 consecutive empty lines ends the result. system ok echo $'Hello\n\nWorld' ---- Hello World # The next record begins here after 2 blank lines. # Environment variables are supported. system ok echo $USER ---- xxchan ``` -------------------------------- ### Create Test Harness with sqllogictest Macro Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt The harness! macro automatically discovers and executes .slt files. It requires a struct implementing the DB trait to handle SQL execution. ```rust use sqllogictest::{DBOutput, DefaultColumnType}; pub struct TestDB; impl TestDB { fn new() -> Self { TestDB } } impl sqllogictest::DB for TestDB { type Error = String; type ColumnType = DefaultColumnType; fn run(&mut self, sql: &str) -> Result, Self::Error> { Ok(DBOutput::StatementComplete(0)) } } sqllogictest::harness!(TestDB::new, "tests/**/*.slt"); ``` -------------------------------- ### Binding Query Results to Variables with 'let' Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Explains how to use the 'let' command to execute a SQL query and bind its result to one or more variables. The query must return exactly one row, and the number of columns must match the number of variables. 'control substitution on' is required for using the bound variables in subsequent queries. ```sql control substitution on # Execute a query that returns exactly 1 row with 1 column, bind result to 'id' let id SELECT id FROM users WHERE name = 'alice' # Multiple variables can be bound from a single query let user_id, user_name, user_email SELECT id, name, email FROM users WHERE id = 1 # Use the bound variable in subsequent queries query TTT SELECT $user_id, $user_name, $user_email ---- 1 alice alice@example.com ``` -------------------------------- ### Enable Variable Substitution in .slt Files Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Variable substitution allows dynamic SQL execution using environment variables. It must be explicitly enabled using the control command. ```text control substitution on statement ok CREATE DATABASE $DB_NAME query T SELECT '${MY_VAR:default_value}' ---- default_value ``` -------------------------------- ### SQL String Substitution with Special Variables Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Demonstrates SQL string substitution using variables like '$foo', '${bar:default}', and special test-specific variables such as '$__TEST_DIR__', '$__NOW__', and '$__DATABASE__'. Substitution requires 'control substitution on'. Special characters like '$' and '\' need escaping when substitution is on. ```sql SELECT '$foo' -- short , '${foo}' -- long , '${bar:default}' -- default value , '${bar:$foo-default}' -- recursive default value FROM baz; ``` ```sql control substitution on COPY (SELECT * FROM foo) TO '$__TEST_DIR__/foo.txt'; system ok echo "foo" > "$__TEST_DIR__/foo.txt" ``` -------------------------------- ### Run sqllogictest Files with CLI Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Executes sqllogictest files using the sqllogictest CLI. Supports running tests against a specified directory and optionally overriding test files with actual output. ```sh sqllogictest './test/**/*.slt' sqllogictest './test/**/*.slt' --override ``` -------------------------------- ### Sqllogictest .slt File Format: Environment Substitution Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Enables environment variable substitution within queries and statements in .slt files by including the 'control substitution on' directive. ```text control substitution on ``` -------------------------------- ### Defining and Using Variables with Let Records Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Explains how to use 'let' records to bind SQL query results to variables for use in subsequent queries. This feature allows for complex test workflows by enabling the storage and reuse of single or multiple values from query results. Variable substitution must be enabled. ```sql control substitution on let user_id SELECT id FROM users WHERE name = 'Alice' query I SELECT age FROM users WHERE id = $user_id -- 30 let id, name, age SELECT id, name, age FROM users WHERE id = 1 query TI SELECT $name, $age -- Alice 30 let max_id SELECT MAX(id) FROM users statement ok INSERT INTO users VALUES ($max_id + 1, 'NewUser', 35) let total_users SELECT COUNT(*) FROM users query I SELECT $total_users -- 4 ``` -------------------------------- ### Sqllogictest .slt File Format: Ignore Volatile Output Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Demonstrates the '' extension in .slt files to skip volatile parts of query output, useful for statements like EXPLAIN. ```text query T EXPLAIN SELECT * FROM foo; ---- Seq Scan on t (cost= rows= width=) Filter: (x > 1) ``` -------------------------------- ### Executing System Commands in Tests Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Details how to execute shell commands directly within the test environment using the 'system' command. This is useful for file operations, interacting with external tools, and managing the test environment. The output of these commands can be captured and asserted. ```bash # Basic system command system ok echo "Hello, World!" # System command with expected output system ok echo "test output" -- test output # Use with environment variables system ok echo "$HOME" # File operations in test directory control substitution on system ok echo "data line 1" > "$__TEST_DIR__/test.txt" system ok cat "$__TEST_DIR__/test.txt" -- data line 1 # Background command execution (returns immediately) system ok sleep 10 & # Multiline expected output system ok printf "line1\nline2\nline3" -- line1 line2 line3 # System command with retry system ok retry 3 backoff 2s curl -f http://localhost:8080/health ``` -------------------------------- ### Sqllogictest .slt File Format: Retry Clause Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Demonstrates the 'retry' and 'backoff' clauses in .slt files for handling transient errors in queries, statements, or expected failures. Note: Cannot be used with single-line regex error messages. ```text query I retry 3 backoff 5s SELECT id FROM test; ---- 1 query error retry 3 backoff 5s SELECT id FROM test; ---- database error: table not found statement ok retry 3 backoff 5s UPDATE test SET id = 1; statement error UPDATE test SET value = value + 1; ---- database error: table not found ``` -------------------------------- ### Conditional Test Execution with Skipif and Onlyif Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Explains how to control test execution based on specific conditions using 'skipif' and 'onlyif' directives. These directives allow tests to be conditionally skipped or run based on labels, engine names, or environment variables, ensuring tests are relevant to the current execution context. ```sql # Skip on specific database engine skipif mysql statement ok CREATE INDEX CONCURRENTLY idx_users_name ON users(name) # Run only on specific engine onlyif postgres statement ok CREATE EXTENSION IF NOT EXISTS pg_trgm # Multiple conditions (all apply to next record) skipif sqlite skipif mysql statement ok ALTER TABLE users ALTER COLUMN name SET DATA TYPE VARCHAR(200) # Use custom labels (passed via --label flag) onlyif feature_new_syntax query I SELECT id FROM users USING NEW_SYNTAX -- 1 # Combine with statement/query skipif ci_environment statement ok VACUUM FULL users # Conditions for queries onlyif postgres query T SELECT version() -- PostgreSQL 15.0 ``` -------------------------------- ### Implement Synchronous DB Backend with `DB` Trait in Rust Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Demonstrates implementing the synchronous `DB` trait for custom database backends in sqllogictest-rs. Requires implementing the `run` method to handle SQL execution and return results or errors. Supports basic SQL commands like SELECT, INSERT, and CREATE. ```Rust use sqllogictest::{DB, DBOutput, DefaultColumnType}; pub struct MyDatabase { // your database connection fields } #[derive(Debug)] pub struct MyError(String); impl std::fmt::Display for MyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl std::error::Error for MyError {} impl DB for MyDatabase { type Error = MyError; type ColumnType = DefaultColumnType; fn run(&mut self, sql: &str) -> Result, Self::Error> { // Handle different SQL commands if sql.starts_with("SELECT") { // Return query results Ok(DBOutput::Rows { types: vec![DefaultColumnType::Text, DefaultColumnType::Integer], rows: vec![ vec!["Alice".to_string(), "30".to_string()], vec!["Bob".to_string(), "25".to_string()], ], }) } else if sql.starts_with("INSERT") || sql.starts_with("CREATE") { // Return statement completion with affected row count Ok(DBOutput::StatementComplete(1)) } else { Err(MyError(format!("Unsupported SQL: {}", sql))) } } // Optional: Extract SQL state from errors for SQLSTATE matching fn error_sql_state(err: &Self::Error) -> Option { None // Return Some("42P01") for specific SQL state codes } } ``` -------------------------------- ### Execute Tests via sqllogictest CLI Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt The CLI tool allows running tests against various database engines. It supports parallel execution, JUnit reporting, and environment variable configuration. ```bash cargo install sqllogictest-bin sqllogictest './tests/**/*.slt' --host localhost --port 5432 --user postgres --pass secret sqllogictest './tests/**/*.slt' -j 4 --override --engine mysql --junit results ``` -------------------------------- ### Manage Multiple Database Connections in a Test Case Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/CHANGELOG.md Enables the use of multiple database connections within a single test case, facilitating the testing of transaction behaviors. This is achieved by defining a 'connection ' record before queries or statements. The runner's `Runner::new` now accepts an `impl MakeConnection` for establishing these connections lazily. ```sql connection foo query TTTT SELECT 1; ``` -------------------------------- ### Sqllogictest .slt File Format: Expected Error Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/README.md Shows how to test for expected errors in .slt files. Supports matching error messages with regex, SQLSTATE codes, or exact multiline messages. ```text # Ensure that the statement errors and that the error # message contains 'Multiple object drop not supported' statement error Multiple object drop not supported DROP VIEW foo, bar; # Ensure that the statement errors and that the SQLSTATE is exactly the expected one. # (This requires the engine to expose the SQLSTATE via `DB::error_sql_state` / `AsyncDB::error_sql_state`.) statement error (42P01) SELECT * FROM non_existent_table; # The output error message must be the exact match of the expected one to pass the test, # except for the leading and trailing whitespaces. # Empty lines (not consecutive) are allowed in the expected error message. As a result, the message must end with 2 consecutive empty lines. query error SELECT 1/0; ---- db error: ERROR: Failed to execute query Caused by these errors: 1: Failed to evaluate expression: 1/0 2: Division by zero # The next record begins here after 2 blank lines. ``` -------------------------------- ### Implement Asynchronous DB Backend with `AsyncDB` Trait in Rust Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Shows how to implement the asynchronous `AsyncDB` trait for database backends, suitable for use with async database drivers. It extends the synchronous `DB` trait with async methods and includes hooks for sleep and command execution. ```Rust use sqllogictest::{AsyncDB, DBOutput, DefaultColumnType}; use async_trait::async_trait; use std::time::Duration; pub struct AsyncDatabase { // async database connection } #[derive(Debug)] pub struct AsyncError(String); impl std::fmt::Display for AsyncError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl std::error::Error for AsyncError {} #[async_trait] impl AsyncDB for AsyncDatabase { type Error = AsyncError; type ColumnType = DefaultColumnType; async fn run(&mut self, sql: &str) -> Result, Self::Error> { // Execute SQL asynchronously if sql == "SELECT * FROM users" { Ok(DBOutput::Rows { types: vec![DefaultColumnType::Integer, DefaultColumnType::Text], rows: vec![ vec!["1".to_string(), "Alice".to_string()], vec!["2".to_string(), "Bob".to_string()], ], }) } else { Ok(DBOutput::StatementComplete(0)) } } async fn shutdown(&mut self) { // Clean up connection resources } fn engine_name(&self) -> &str { "my_async_db" } // Override for tokio runtime async fn sleep(dur: Duration) { tokio::time::sleep(dur).await; } } ``` -------------------------------- ### Execute Test Files with Runner Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt The Runner struct manages database connections and executes sqllogictest files or scripts. It supports custom database implementations, runtime variables, and conditional test execution. ```rust use sqllogictest::{Runner, DBOutput, DefaultColumnType, DB}; struct SimpleDB; impl DB for SimpleDB { type Error = String; type ColumnType = DefaultColumnType; fn run(&mut self, sql: &str) -> Result, Self::Error> { match sql { "SELECT 1 + 1" => Ok(DBOutput::Rows { types: vec![DefaultColumnType::Integer], rows: vec![vec!["2".to_string()]], }), _ => Ok(DBOutput::StatementComplete(0)), } } } fn main() { let mut runner = Runner::new(|| async { Ok(SimpleDB) }); runner.add_label("my_engine"); runner.set_var("__DATABASE__".to_string(), "test_db".to_string()); runner.run_file("tests/basic.slt").expect("test failed"); runner.run_script(r#" statement ok CREATE TABLE t(x INT) query I SELECT 1 + 1 ---- 2 "#).expect("test failed"); runner.shutdown(); } ``` -------------------------------- ### Configuring Hash Threshold for Result Comparison Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Explains the 'hash-threshold' setting, which controls how large result sets are compared. When the number of values in a result set exceeds this threshold, the results are hashed rather than compared directly, improving performance for large datasets. A threshold of 0 disables hashing. ```sql # Set hash threshold to 100 values hash-threshold 100 # This query's results will be hashed if > 100 values query I SELECT generate_series(1, 1000) -- 1000 values hashing to abc123def456 # Disable hashing (compare all values directly) hash-threshold 0 query I SELECT generate_series(1, 5) -- 1 2 3 4 5 ``` -------------------------------- ### Conditional Test Execution with Labels Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/CHANGELOG.md Enhances the `skipif` and `onlyif` directives to support multiple labels. Conditions are now evaluated as true if *any* of the provided labels match. This allows for more flexible test filtering using custom labels specified via the `--label` option in the CLI. ```bash sqllogictest --label my_label test_file.sql ``` -------------------------------- ### Enable Environment Variable Substitution in Tests Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/CHANGELOG.md This feature allows environment variables to be substituted within SQL and system commands in test files. It is disabled by default and can be enabled using 'control substitution on'. Special variables like '$__TEST_DIR__' are available for test-specific directories. This change introduced breaking changes in the parser and runner. ```sql control substitution on query TTTT SELECT '$foo' -- short , '${foo}' -- long , '${bar:default}' -- default value , '${bar:$foo-default}' -- recursive default value FROM baz; ---- ``` ```sql control substitution on statement ok COPY (SELECT * FROM foo) TO '$__TEST_DIR__/foo.txt'; system ok echo "foo" > "$__TEST_DIR__/foo.txt" ``` -------------------------------- ### Implement Custom Validators and Normalizers in Rust Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Extend sqllogictest's comparison logic by implementing custom normalizers and validators. This allows for flexible data transformation before comparison and custom comparison strategies, such as approximate numeric matching. The `Runner` can be configured with these custom functions. ```rust use sqllogictest::{Runner, Normalizer, Validator, default_normalizer}; // Custom normalizer: additional whitespace handling fn custom_normalizer(s: &String) -> String { s.trim() .split_whitespace() .collect::>() .join(" ") .to_lowercase() } // Custom validator: approximate numeric comparison fn approx_validator( normalizer: Normalizer, actual: &[Vec], expected: &[String], ) -> bool { let actual_normalized: Vec = actual .iter() .map(|row| row.iter().map(normalizer).collect::>().join(" ")) .collect(); if actual_normalized.len() != expected.len() { return false; } actual_normalized .iter() .zip(expected.iter()) .all(|(a, e)| { // Try numeric comparison with tolerance match (a.parse::(), normalizer(e).parse::()) { (Ok(av), Ok(ev)) => (av - ev).abs() < 0.0001, _ => a == &normalizer(e), } }) } fn main() { let mut runner = Runner::new(|| async { Ok(MyDB) }); // Set custom normalizer runner.with_normalizer(custom_normalizer); // Set custom validator runner.with_validator(approx_validator); runner.run_file("tests/numeric.slt").unwrap(); } ``` -------------------------------- ### Define Statement Records in .slt Files Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Statement records verify SQL commands that do not return result sets. They support success checks, row counts, and error matching. ```text statement ok CREATE TABLE users(id INT PRIMARY KEY, name VARCHAR(100), age INT) statement count 3 INSERT INTO users VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Eve', 28) statement error (23505) INSERT INTO users VALUES (1, 'Duplicate', 99) ``` -------------------------------- ### Define Query Records in .slt Files Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Query records validate SQL result sets. They support column type definitions, sorting modes, error expectations, and retry logic. ```text query TII SELECT name, age, id FROM users WHERE age > 20 ---- Alice 30 1 query IT rowsort SELECT id, name FROM users ---- 1 Alice 2 Bob query I retry 3 backoff 500ms SELECT count(*) FROM async_populated_table ---- 100 ``` -------------------------------- ### Execute External System Commands in Tests Source: https://github.com/risinglightdb/sqllogictest-rs/blob/main/CHANGELOG.md Allows running external system commands directly within test files. The runner checks the command's exit code for success. This feature is useful for manipulating external resources during tests. The implementation in the runner uses `std::process::Command::status` by default, with an option to override for asynchronous runtimes. ```sql system ok echo "Hello, world!" ``` -------------------------------- ### Parse Test Files into Records Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt The parse_file function reads a sqllogictest file and returns a vector of Record types. This allows for fine-grained inspection and manual processing of test statements, queries, and control records. ```rust use sqllogictest::{parse_file, Record, DefaultColumnType}; fn main() -> Result<(), Box> { let records: Vec> = parse_file("tests/example.slt")?; for record in &records { match record { Record::Statement { sql, expected, .. } => { println!("Statement: {}", sql); println!(" Expected: {:?}", expected); } Record::Query { sql, expected, .. } => { println!("Query: {}", sql); match expected { sqllogictest::QueryExpect::Results { types, results, .. } => { println!(" Types: {:?}", types); println!(" Expected rows: {}", results.len()); } sqllogictest::QueryExpect::Error(e) => { println!(" Expected error: {}", e); } } } Record::Include { filename, .. } => { println!("Include: {}", filename); } Record::Control(ctrl) => { println!("Control: {:?}", ctrl); } _ => {} } } Ok(()) } ``` -------------------------------- ### Controlling Test Runner Behavior with Directives Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Details the use of 'control' directives to modify the behavior of the test runner. These directives affect sorting modes, result parsing, and variable substitution, allowing fine-grained control over how test results are processed and interpreted. ```sql # Set file-level sort mode (applies to all queries until changed) control sortmode rowsort query II SELECT a, b FROM pairs -- 1 2 3 4 # Change to value sort mode control sortmode valuesort query I SELECT x FROM numbers -- 1 2 3 # Reset to no sorting control sortmode nosort # Control result mode (how results are parsed) control resultmode valuewise query I SELECT * FROM matrix -- 1 2 3 4 control resultmode rowwise # Enable variable substitution control substitution on query T SELECT '$MY_VAR' -- my_value control substitution off ``` -------------------------------- ### Parse Test Scripts from Strings Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt The parse function converts a raw sqllogictest script string into a collection of Record objects. This is ideal for dynamic test generation or unit testing specific SQL logic scenarios. ```rust use sqllogictest::{parse, Record, DefaultColumnType, StatementExpect, QueryExpect}; fn main() -> Result<(), Box> { let script = r#" # Test basic functionality statement ok CREATE TABLE users(id INT, name TEXT) statement count 3 INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Eve') query IT rowsort SELECT * FROM users ---- 1 Alice 2 Bob 3 Eve statement error table.*not found DROP TABLE nonexistent "#; let records: Vec> = parse(script)?; assert_eq!(records.len(), 8); for record in records { if let Record::Query { sql, expected, .. } = record { println!("Found query: {}", sql); if let QueryExpect::Results { types, sort_mode, results, .. } = expected { println!(" Column types: {:?}", types); println!(" Sort mode: {:?}", sort_mode); println!(" Expected results: {:?}", results); } } } Ok(()) } ``` -------------------------------- ### Define Custom Column Types in Rust Source: https://context7.com/risinglightdb/sqllogictest-rs/llms.txt Implement the `ColumnType` trait to map custom characters to specific data types within sqllogictest. This allows for testing databases with unique or extended type systems. The `from_char` and `to_char` methods define the mapping. ```rust use sqllogictest::{ColumnType, Runner, DBOutput}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum CustomType { Integer, Text, Boolean, Json, Uuid, } impl ColumnType for CustomType { fn from_char(value: char) -> Option { match value { 'I' => Some(Self::Integer), 'T' => Some(Self::Text), 'B' => Some(Self::Boolean), 'J' => Some(Self::Json), 'U' => Some(Self::Uuid), _ => None, } } fn to_char(&self) -> char { match self { Self::Integer => 'I', Self::Text => 'T', Self::Boolean => 'B', Self::Json => 'J', Self::Uuid => 'U', } } } // Use in your DB implementation struct CustomDB; impl sqllogictest::DB for CustomDB { type Error = String; type ColumnType = CustomType; fn run(&mut self, sql: &str) -> Result, Self::Error> { Ok(DBOutput::Rows { types: vec![CustomType::Uuid, CustomType::Json], rows: vec![ vec![ "550e8400-e29b-41d4-a716-446655440000".to_string(), r#"{"key": "value"}"#.to_string(), ], ], }) } } // Test file can use custom types: // query UJ // SELECT id, metadata FROM documents // ---- // 550e8400-e29b-41d4-a716-446655440000 {"key": "value"} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.