Files
upstream-seaweedfs/weed/query/engine/sql_alias_support_test.go
upstream-mirror 89f5be005d
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 03:23:42 +05:00

409 lines
15 KiB
Go

package engine
import (
"testing"
"github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
"github.com/stretchr/testify/assert"
)
// TestSQLAliasResolution tests the complete SQL alias resolution functionality
func TestSQLAliasResolution(t *testing.T) {
engine := NewTestSQLEngine()
t.Run("ResolveColumnAlias", func(t *testing.T) {
// Test the helper function for resolving aliases
// Create SELECT expressions with aliases
selectExprs := []SelectExpr{
&AliasedExpr{
Expr: &ColName{Name: stringValue("_ts_ns")},
As: aliasValue("ts"),
},
&AliasedExpr{
Expr: &ColName{Name: stringValue("id")},
As: aliasValue("record_id"),
},
}
// Test alias resolution
resolved := engine.resolveColumnAlias("ts", selectExprs)
assert.Equal(t, "_ts_ns", resolved, "Should resolve 'ts' alias to '_ts_ns'")
resolved = engine.resolveColumnAlias("record_id", selectExprs)
assert.Equal(t, "id", resolved, "Should resolve 'record_id' alias to 'id'")
// Test non-aliased column (should return as-is)
resolved = engine.resolveColumnAlias("some_other_column", selectExprs)
assert.Equal(t, "some_other_column", resolved, "Non-aliased columns should return unchanged")
})
t.Run("SingleAliasInWhere", func(t *testing.T) {
// Test using a single alias in WHERE clause
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 12345}},
},
}
// Parse SQL with alias in WHERE
sql := "SELECT _ts_ns AS ts, id FROM test WHERE ts = 1756947416566456262"
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse SQL with alias in WHERE")
selectStmt := stmt.(*SelectStatement)
// Build predicate with context (for alias resolution)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build predicate with alias resolution")
// Test the predicate
result := predicate(testRecord)
assert.True(t, result, "Predicate should match using alias 'ts' for '_ts_ns'")
// Test with non-matching value
sql2 := "SELECT _ts_ns AS ts, id FROM test WHERE ts = 999999"
stmt2, err := ParseSQL(sql2)
assert.NoError(t, err)
selectStmt2 := stmt2.(*SelectStatement)
predicate2, err := engine.buildPredicateWithContext(selectStmt2.Where.Expr, selectStmt2.SelectExprs)
assert.NoError(t, err)
result2 := predicate2(testRecord)
assert.False(t, result2, "Predicate should not match different value")
})
t.Run("MultipleAliasesInWhere", func(t *testing.T) {
// Test using multiple aliases in WHERE clause
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 82460}},
},
}
// Parse SQL with multiple aliases in WHERE
sql := "SELECT _ts_ns AS ts, id AS record_id FROM test WHERE ts = 1756947416566456262 AND record_id = 82460"
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse SQL with multiple aliases")
selectStmt := stmt.(*SelectStatement)
// Build predicate with context
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build predicate with multiple alias resolution")
// Test the predicate - should match both conditions
result := predicate(testRecord)
assert.True(t, result, "Should match both aliased conditions")
// Test with one condition not matching
testRecord2 := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 99999}}, // Different ID
},
}
result2 := predicate(testRecord2)
assert.False(t, result2, "Should not match when one alias condition fails")
})
t.Run("RangeQueryWithAliases", func(t *testing.T) {
// Test range queries using aliases
testRecords := []*schema_pb.RecordValue{
{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456260}}, // Below range
},
},
{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}}, // In range
},
},
{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456265}}, // Above range
},
},
}
// Test range query with alias
sql := "SELECT _ts_ns AS ts FROM test WHERE ts > 1756947416566456261 AND ts < 1756947416566456264"
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse range query with alias")
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build range predicate with alias")
// Test each record
assert.False(t, predicate(testRecords[0]), "Should not match record below range")
assert.True(t, predicate(testRecords[1]), "Should match record in range")
assert.False(t, predicate(testRecords[2]), "Should not match record above range")
})
t.Run("MixedAliasAndDirectColumn", func(t *testing.T) {
// Test mixing aliased and non-aliased columns in WHERE
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 82460}},
"status": {Kind: &schema_pb.Value_StringValue{StringValue: "active"}},
},
}
// Use alias for one column, direct name for another
sql := "SELECT _ts_ns AS ts, id, status FROM test WHERE ts = 1756947416566456262 AND status = 'active'"
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse mixed alias/direct query")
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build mixed predicate")
result := predicate(testRecord)
assert.True(t, result, "Should match with mixed alias and direct column usage")
})
t.Run("AliasCompatibilityWithTimestampFixes", func(t *testing.T) {
// Test that alias resolution works with the timestamp precision fixes
largeTimestamp := int64(1756947416566456262) // Large nanosecond timestamp
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: largeTimestamp}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 897795}},
},
}
// Test that large timestamp precision is maintained with aliases
sql := "SELECT _ts_ns AS ts, id FROM test WHERE ts = 1756947416566456262"
stmt, err := ParseSQL(sql)
assert.NoError(t, err)
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err)
result := predicate(testRecord)
assert.True(t, result, "Large timestamp precision should be maintained with aliases")
// Test precision with off-by-one (should not match)
sql2 := "SELECT _ts_ns AS ts, id FROM test WHERE ts = 1756947416566456263" // +1
stmt2, err := ParseSQL(sql2)
assert.NoError(t, err)
selectStmt2 := stmt2.(*SelectStatement)
predicate2, err := engine.buildPredicateWithContext(selectStmt2.Where.Expr, selectStmt2.SelectExprs)
assert.NoError(t, err)
result2 := predicate2(testRecord)
assert.False(t, result2, "Should not match timestamp differing by 1 nanosecond")
})
t.Run("EdgeCasesAndErrorHandling", func(t *testing.T) {
// Test edge cases and error conditions
// Test with nil SelectExprs
predicate, err := engine.buildPredicateWithContext(&ComparisonExpr{
Left: &ColName{Name: stringValue("test_col")},
Operator: "=",
Right: &SQLVal{Type: IntVal, Val: []byte("123")},
}, nil)
assert.NoError(t, err, "Should handle nil SelectExprs gracefully")
assert.NotNil(t, predicate, "Should return valid predicate even without aliases")
// Test alias resolution with empty SelectExprs
resolved := engine.resolveColumnAlias("test_col", []SelectExpr{})
assert.Equal(t, "test_col", resolved, "Should return original name with empty SelectExprs")
// Test alias resolution with nil SelectExprs
resolved = engine.resolveColumnAlias("test_col", nil)
assert.Equal(t, "test_col", resolved, "Should return original name with nil SelectExprs")
})
t.Run("ComparisonOperators", func(t *testing.T) {
// Test all comparison operators work with aliases
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1000}},
},
}
operators := []struct {
op string
value string
expected bool
}{
{"=", "1000", true},
{"=", "999", false},
{">", "999", true},
{">", "1000", false},
{">=", "1000", true},
{">=", "1001", false},
{"<", "1001", true},
{"<", "1000", false},
{"<=", "1000", true},
{"<=", "999", false},
}
for _, test := range operators {
t.Run(test.op+"_"+test.value, func(t *testing.T) {
sql := "SELECT _ts_ns AS ts FROM test WHERE ts " + test.op + " " + test.value
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse operator: %s", test.op)
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build predicate for operator: %s", test.op)
result := predicate(testRecord)
assert.Equal(t, test.expected, result, "Operator %s with value %s should return %v", test.op, test.value, test.expected)
})
}
})
t.Run("BackwardCompatibility", func(t *testing.T) {
// Ensure non-alias queries still work exactly as before
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 12345}},
},
}
// Test traditional query (no aliases)
sql := "SELECT _ts_ns, id FROM test WHERE _ts_ns = 1756947416566456262"
stmt, err := ParseSQL(sql)
assert.NoError(t, err)
selectStmt := stmt.(*SelectStatement)
// Should work with both old and new predicate building methods
predicateOld, err := engine.buildPredicate(selectStmt.Where.Expr)
assert.NoError(t, err, "Old buildPredicate method should still work")
predicateNew, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "New buildPredicateWithContext should work for non-alias queries")
// Both should produce the same result
resultOld := predicateOld(testRecord)
resultNew := predicateNew(testRecord)
assert.True(t, resultOld, "Old method should match")
assert.True(t, resultNew, "New method should match")
assert.Equal(t, resultOld, resultNew, "Both methods should produce identical results")
})
}
// TestAliasIntegrationWithProductionScenarios tests real-world usage patterns
func TestAliasIntegrationWithProductionScenarios(t *testing.T) {
engine := NewTestSQLEngine()
t.Run("OriginalFailingQuery", func(t *testing.T) {
// Test the exact query pattern that was originally failing
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756913789829292386}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 82460}},
},
}
// This was the original failing pattern
sql := "SELECT id, _ts_ns AS ts FROM ecommerce.user_events WHERE ts = 1756913789829292386"
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse the originally failing query pattern")
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build predicate for originally failing pattern")
result := predicate(testRecord)
assert.True(t, result, "Should now work for the originally failing query pattern")
})
t.Run("ComplexProductionQuery", func(t *testing.T) {
// Test a more complex production-like query
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 897795}},
"user_id": {Kind: &schema_pb.Value_StringValue{StringValue: "user123"}},
"event_type": {Kind: &schema_pb.Value_StringValue{StringValue: "click"}},
},
}
sql := `SELECT
id AS event_id,
_ts_ns AS event_time,
user_id AS uid,
event_type AS action
FROM ecommerce.user_events
WHERE event_time = 1756947416566456262
AND uid = 'user123'
AND action = 'click'`
stmt, err := ParseSQL(sql)
assert.NoError(t, err, "Should parse complex production query")
selectStmt := stmt.(*SelectStatement)
predicate, err := engine.buildPredicateWithContext(selectStmt.Where.Expr, selectStmt.SelectExprs)
assert.NoError(t, err, "Should build predicate for complex query")
result := predicate(testRecord)
assert.True(t, result, "Should match complex production query with multiple aliases")
// Test partial match failure
testRecord2 := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
"id": {Kind: &schema_pb.Value_Int64Value{Int64Value: 897795}},
"user_id": {Kind: &schema_pb.Value_StringValue{StringValue: "user999"}}, // Different user
"event_type": {Kind: &schema_pb.Value_StringValue{StringValue: "click"}},
},
}
result2 := predicate(testRecord2)
assert.False(t, result2, "Should not match when one aliased condition fails")
})
t.Run("PerformanceRegression", func(t *testing.T) {
// Ensure alias resolution doesn't significantly impact performance
testRecord := &schema_pb.RecordValue{
Fields: map[string]*schema_pb.Value{
"_ts_ns": {Kind: &schema_pb.Value_Int64Value{Int64Value: 1756947416566456262}},
},
}
// Build predicates for comparison
sqlWithAlias := "SELECT _ts_ns AS ts FROM test WHERE ts = 1756947416566456262"
sqlWithoutAlias := "SELECT _ts_ns FROM test WHERE _ts_ns = 1756947416566456262"
stmtWithAlias, err := ParseSQL(sqlWithAlias)
assert.NoError(t, err)
stmtWithoutAlias, err := ParseSQL(sqlWithoutAlias)
assert.NoError(t, err)
selectStmtWithAlias := stmtWithAlias.(*SelectStatement)
selectStmtWithoutAlias := stmtWithoutAlias.(*SelectStatement)
// Both should build successfully
predicateWithAlias, err := engine.buildPredicateWithContext(selectStmtWithAlias.Where.Expr, selectStmtWithAlias.SelectExprs)
assert.NoError(t, err)
predicateWithoutAlias, err := engine.buildPredicateWithContext(selectStmtWithoutAlias.Where.Expr, selectStmtWithoutAlias.SelectExprs)
assert.NoError(t, err)
// Both should produce the same logical result
resultWithAlias := predicateWithAlias(testRecord)
resultWithoutAlias := predicateWithoutAlias(testRecord)
assert.True(t, resultWithAlias, "Alias query should work")
assert.True(t, resultWithoutAlias, "Non-alias query should work")
assert.Equal(t, resultWithAlias, resultWithoutAlias, "Both should produce same result")
})
}