Add Variant SELECT rewriter and comprehensive architecture docs#16
Add Variant SELECT rewriter and comprehensive architecture docs#16tonyalaribe wants to merge 4 commits intomasterfrom
Conversation
- Consolidate WALRUS_DATA_DIR and FOYER_CACHE_DIR into single TIMEFUSION_DATA_DIR with derived subdirs (wal/, cache/) - Add VariantConversionExec to convert string columns to Variant during INSERT - Add VariantInsertRewriter analyzer rule to rewrite string literals for Variant columns - Add is_schema_compatible_for_insert() for flexible INSERT type checking - Split optimizers.rs into optimizers/ module directory - Improve query sanitization for INSERT and long queries
- Add VariantSelectRewriter analyzer rule to wrap Variant columns with variant_to_json() in SELECT projections for PostgreSQL wire protocol - Add comprehensive documentation: - docs/ARCHITECTURE.md: Full system architecture overview - docs/VARIANT_TYPE_SYSTEM.md: Variant type implementation details - docs/WAL.md: Write-ahead log implementation and recovery - Update database.rs with unified table storage model improvements - Update DML operations with buffered layer integration - Align otel_logs_and_spans schema with monoscope - Fix test configurations for new architecture
PR Review: Add Variant SELECT rewriter and comprehensive architecture docsSummaryThis is a well-structured PR that adds critical functionality for Variant type handling and significantly improves documentation. The implementation is thoughtful and addresses PostgreSQL wire protocol compatibility correctly. ✅ StrengthsCode Quality
Best Practices
🔍 Issues & RecommendationsSecurity ConcernsHIGH: Credentials in Database Schema (database.rs:570-571) s3_access_key_id VARCHAR(500) NOT NULL,
s3_secret_access_key VARCHAR(500) NOT NULL,Storing credentials in plaintext is a security vulnerability. Consider:
MEDIUM: Potential SQL Injection in Dynamic Queries Code Quality Issues1. Missing Error Context (variant_insert_rewriter.rs:32) plan.transform_up(|node| rewrite_insert_node(node)).map(|t| t.data)Consider adding error context to help with debugging: plan.transform_up(|node| rewrite_insert_node(node))
.map(|t| t.data)
.map_err(|e| DataFusionError::Plan(format!("VariantInsertRewriter failed: {}", e)))2. Recursive Transformation Could Stack Overflow (variant_insert_rewriter.rs:94-104)
3. Magic Number (optimizers/mod.rs:29) let date_scalar = ScalarValue::Date32(Some(date.and_hms_opt(0, 0, 0).unwrap().and_utc().timestamp() as i32 / 86400));The division by 86400 (seconds per day) should be a named constant: const SECONDS_PER_DAY: i32 = 86400;4. Unused Code Warning (optimizers/mod.rs:7-10) // Remove unused imports warning - these are used by the submodules indirectly
use datafusion::logical_expr::{BinaryExpr, Expr, Operator};
use datafusion::scalar::ScalarValue;These imports ARE used directly in the time_range_partition_pruner module below. The comment is misleading - just remove it. Performance Considerations1. Cloning in Hot Path (variant_select_rewriter.rs:40) expr.clone()While necessary for the TreeNode pattern, consider documenting that this is acceptable because:
2. Batch Conversion Efficiency (database.rs:100-152) Test CoverageGOOD:
NEEDS IMPROVEMENT:
Recommendation: Add unit tests in #[cfg(test)]
mod tests {
use super::*;
use datafusion::prelude::*;
#[test]
fn test_variant_select_no_double_wrap() {
// Test that already-wrapped columns aren't wrapped again
}
#[test]
fn test_variant_insert_with_partial_columns() {
// Test INSERT with fewer columns than table schema
}
}DocumentationMinor Issues:
🎯 Action ItemsBefore Merge (Required):
Post-Merge (Recommended):
📊 Metrics
ConclusionThis is high-quality work that significantly improves the Variant type system and documentation. The security concern around credential storage should be addressed before merging, but otherwise the implementation is solid. The new documentation is comprehensive and will help onboard contributors. Recommendation: Approve with requested changes to credential storage Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com |
variant_columns_to_json() was using RecordBatch::try_new() which fails when creating batches with 0 columns (empty projections used by COUNT(*)) because Arrow requires either columns or an explicit row count. Changed to try_new_with_options() to preserve the original batch's row count, fixing queries like SELECT COUNT(*) that don't need any columns.
Transient network errors like "error sending request" were failing immediately with no retries. Added: - RetryConfig: 5 retries with exponential backoff (100ms-15s) - ClientOptions: 30s connect timeout, 5min request timeout This should resolve intermittent flush failures to R2/S3.
Summary
variant_to_json()in SELECT projections, ensuring proper serialization for PostgreSQL wire protocolDocumentation Added
docs/ARCHITECTURE.md- Full system architecture overview with diagramsdocs/VARIANT_TYPE_SYSTEM.md- Variant type implementation->and->>)docs/WAL.md- Write-ahead log implementationCode Changes
src/optimizers/variant_select_rewriter.rs- New analyzer rulesrc/database.rs- Unified table storage improvementssrc/dml.rs- Buffered layer integrationTest plan
cargo testfor unit testscargo test --test integration_testfor integration tests