import pytest
import tempfile
import time
from pathlib import Path
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'apexbase', 'python'))
try:
from apexbase import ApexClient, ResultView
except ImportError as e:
pytest.skip(f"ApexBase not available: {e}", allow_module_level=True)
try:
import pandas as pd
PANDAS_AVAILABLE = True
except ImportError:
PANDAS_AVAILABLE = False
class TestTableManagementAPI:
def test_create_table_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("users")
assert "users" in client.list_tables()
client.close()
def test_create_multiple_tables(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
for name in ["customers", "orders", "products"]:
client.create_table(name)
tables = client.list_tables()
assert "customers" in tables
assert "orders" in tables
assert "products" in tables
client.close()
def test_drop_table_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("temp_table")
assert "temp_table" in client.list_tables()
client.drop_table("temp_table")
assert "temp_table" not in client.list_tables()
client.close()
def test_use_table_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("table_a")
client.create_table("table_b")
client.use_table("table_a")
client.store([{"id": 1, "source": "A"}])
client.use_table("table_b")
client.store([{"id": 2, "source": "B"}])
client.use_table("table_a")
result = client.execute("SELECT * FROM table_a")
assert len(result) == 1
client.use_table("table_b")
result = client.execute("SELECT * FROM table_b")
assert len(result) == 1
client.close()
class TestColumnManagementAPI:
def test_add_column_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": 1, "name": "Alice"}])
client.flush()
client.add_column("email", "string")
client.store([{"id": 2, "name": "Bob", "email": "bob@test.com"}])
result = client.execute("SELECT * FROM default ORDER BY id")
df = result.to_pandas()
assert "email" in df.columns
client.close()
def test_drop_column_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": 1, "keep": "yes", "drop_me": "no"}])
client.flush()
client.drop_column("drop_me")
client.flush()
client.close()
client = ApexClient(dirpath=temp_dir)
client.use_table("default")
result = client.execute("SELECT * FROM default")
df = result.to_pandas()
assert "keep" in df.columns
client.close()
def test_rename_column_api(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": 1, "old_name": "value"}])
client.flush()
client.rename_column("old_name", "new_name")
client.flush()
client.close()
client = ApexClient(dirpath=temp_dir)
client.use_table("default")
result = client.execute("SELECT * FROM default")
df = result.to_pandas()
assert "id" in df.columns
client.close()
class TestComplexSQLSelect:
def test_select_with_multiple_conditions(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "category": "A", "status": "active", "value": 100},
{"id": 2, "category": "A", "status": "inactive", "value": 200},
{"id": 3, "category": "B", "status": "active", "value": 150},
{"id": 4, "category": "B", "status": "inactive", "value": 300},
])
result = client.execute("""
SELECT * FROM default
WHERE category = 'A' AND status = 'active'
""")
assert len(result) == 1
result = client.execute("""
SELECT * FROM default
WHERE category = 'A' OR status = 'active'
""")
assert len(result) == 3
client.close()
def test_select_with_between(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": i, "score": i * 10} for i in range(1, 11)
])
result = client.execute("""
SELECT * FROM default
WHERE score BETWEEN 30 AND 70
""")
assert len(result) == 5
client.close()
def test_select_with_in_clause(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "city": "NYC"},
{"id": 2, "city": "LA"},
{"id": 3, "city": "Chicago"},
{"id": 4, "city": "Boston"},
])
result = client.execute("""
SELECT * FROM default
WHERE city IN ('NYC', 'LA', 'Boston')
""")
assert len(result) == 3
client.close()
def test_select_with_like(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "name": "Alice Johnson"},
{"id": 2, "name": "Bob Smith"},
{"id": 3, "name": "Alice Brown"},
{"id": 4, "name": "Charlie Johnson"},
])
result = client.execute("SELECT * FROM default WHERE name LIKE 'Alice%'")
assert len(result) == 2
result = client.execute("SELECT * FROM default WHERE name LIKE '%Johnson'")
assert len(result) == 2
result = client.execute("SELECT * FROM default WHERE name LIKE '%li%'")
assert len(result) == 3
client.close()
def test_select_with_not(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "active": True},
{"id": 2, "active": False},
{"id": 3, "active": True},
])
result = client.execute("SELECT * FROM default WHERE active = false")
assert len(result) == 1
client.close()
class TestSQLAggregations:
def test_count_star(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": i} for i in range(100)])
result = client.execute("SELECT COUNT(*) FROM default")
df = result.to_pandas()
assert df.iloc[0, 0] == 100
client.close()
def test_count_column(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 10},
{"id": 2, "value": 20},
{"id": 3}, ])
result = client.execute("SELECT COUNT(value) FROM default")
df = result.to_pandas()
assert df.iloc[0, 0] >= 2
client.close()
def test_sum_avg(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "amount": 100},
{"id": 2, "amount": 200},
{"id": 3, "amount": 300},
])
result = client.execute("SELECT SUM(amount), AVG(amount) FROM default")
df = result.to_pandas()
assert df.iloc[0, 0] == 600 assert df.iloc[0, 1] == 200
client.close()
def test_min_max(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "score": 85},
{"id": 2, "score": 92},
{"id": 3, "score": 78},
{"id": 4, "score": 95},
])
result = client.execute("SELECT MIN(score), MAX(score) FROM default")
df = result.to_pandas()
assert df.iloc[0, 0] == 78 assert df.iloc[0, 1] == 95
client.close()
def test_multiple_aggregates(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "price": 10.0},
{"id": 2, "price": 20.0},
{"id": 3, "price": 30.0},
{"id": 4, "price": 40.0},
])
result = client.execute("""
SELECT COUNT(*), SUM(price), AVG(price), MIN(price), MAX(price)
FROM default
""")
df = result.to_pandas()
assert df.iloc[0, 0] == 4 assert df.iloc[0, 1] == 100 assert df.iloc[0, 2] == 25 assert df.iloc[0, 3] == 10 assert df.iloc[0, 4] == 40
client.close()
class TestSQLGroupBy:
def test_group_by_single_column(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"category": "A", "value": 10},
{"category": "A", "value": 20},
{"category": "B", "value": 30},
{"category": "B", "value": 40},
{"category": "B", "value": 50},
])
result = client.execute("""
SELECT category, COUNT(*), SUM(value)
FROM default
GROUP BY category
ORDER BY category
""")
df = result.to_pandas()
assert len(df) == 2
assert df.iloc[0]["category"] == "A"
assert df.iloc[0]["COUNT(*)"] == 2
assert df.iloc[0]["SUM(value)"] == 30
client.close()
def test_group_by_with_having(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"dept": "Sales", "amount": 1000},
{"dept": "Sales", "amount": 2000},
{"dept": "IT", "amount": 500},
{"dept": "HR", "amount": 300},
{"dept": "HR", "amount": 400},
])
result = client.execute("""
SELECT dept, SUM(amount) as total
FROM default
GROUP BY dept
HAVING SUM(amount) > 600
ORDER BY total DESC
""")
df = result.to_pandas()
assert len(df) == 2 assert df.iloc[0]["dept"] == "Sales"
client.close()
def test_group_by_multiple_columns(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"year": 2023, "quarter": "Q1", "revenue": 100},
{"year": 2023, "quarter": "Q1", "revenue": 150},
{"year": 2023, "quarter": "Q2", "revenue": 200},
{"year": 2024, "quarter": "Q1", "revenue": 180},
])
result = client.execute("""
SELECT year, quarter, SUM(revenue) as total
FROM default
GROUP BY year, quarter
ORDER BY year, quarter
""")
df = result.to_pandas()
assert len(df) == 3
client.close()
class TestSQLOrderBy:
def test_order_by_asc(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 3, "name": "Charlie"},
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"},
])
result = client.execute("SELECT * FROM default ORDER BY id ASC")
df = result.to_pandas()
assert df.iloc[0]["id"] == 1
assert df.iloc[1]["id"] == 2
assert df.iloc[2]["id"] == 3
client.close()
def test_order_by_desc(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "score": 85},
{"id": 2, "score": 92},
{"id": 3, "score": 78},
])
result = client.execute("SELECT * FROM default ORDER BY score DESC")
df = result.to_pandas()
assert df.iloc[0]["score"] == 92
assert df.iloc[2]["score"] == 78
client.close()
def test_order_by_multiple_columns(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"category": "A", "value": 30},
{"category": "B", "value": 10},
{"category": "A", "value": 10},
{"category": "B", "value": 20},
])
result = client.execute("""
SELECT * FROM default
ORDER BY category ASC, value DESC
""")
df = result.to_pandas()
assert df.iloc[0]["category"] == "A"
assert df.iloc[0]["value"] == 30
client.close()
def test_order_by_with_nulls(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 10},
{"id": 2, "value": 0}, {"id": 3, "value": 5},
])
result = client.execute("SELECT * FROM default ORDER BY value ASC")
df = result.to_pandas()
assert df.iloc[0]["value"] == 0
client.close()
class TestSQLLimitOffset:
def test_limit_basic(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": i} for i in range(100)])
result = client.execute("SELECT * FROM default LIMIT 10")
assert len(result) == 10
client.close()
def test_limit_with_order(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": i, "score": 100 - i} for i in range(50)])
result = client.execute("""
SELECT * FROM default
ORDER BY score DESC
LIMIT 5
""")
df = result.to_pandas()
assert len(df) == 5
assert df.iloc[0]["score"] == 100
client.close()
def test_limit_offset(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": i} for i in range(20)])
result = client.execute("""
SELECT * FROM default
ORDER BY id
LIMIT 5
""")
df = result.to_pandas()
assert len(df) == 5
assert df.iloc[0]["id"] == 0
client.close()
def test_offset_without_enough_rows(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": i} for i in range(5)])
result = client.execute("""
SELECT * FROM default
ORDER BY id
LIMIT 10 OFFSET 10
""")
assert len(result) == 0
client.close()
class TestSQLDistinct:
def test_distinct_single_column(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"category": "A", "value": 1},
{"category": "A", "value": 2},
{"category": "B", "value": 3},
{"category": "A", "value": 4},
{"category": "B", "value": 5},
])
result = client.execute("SELECT DISTINCT category FROM default ORDER BY category")
df = result.to_pandas()
assert len(df) == 2
assert df.iloc[0]["category"] == "A"
assert df.iloc[1]["category"] == "B"
client.close()
def test_count_distinct(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "category": "A"},
{"id": 2, "category": "A"},
{"id": 3, "category": "B"},
{"id": 4, "category": "C"},
{"id": 5, "category": "A"},
])
result = client.execute("SELECT COUNT(DISTINCT category) FROM default")
df = result.to_pandas()
assert df.iloc[0, 0] == 3
client.close()
class TestSQLUnion:
def test_union_basic(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "source": "first"},
{"id": 2, "source": "first"},
])
result = client.execute("""
SELECT id, source FROM default WHERE id = 1
UNION
SELECT id, source FROM default WHERE id = 2
""")
assert len(result) == 2
client.close()
def test_union_all(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": "same"},
{"id": 2, "value": "same"},
])
result = client.execute("""
SELECT id, value FROM default
UNION ALL
SELECT id, value FROM default
""")
assert len(result) == 4
client.close()
class TestSQLFunctions:
def test_string_functions(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"text": "Hello World"}])
result = client.execute("""
SELECT
UPPER(text) as upper_text,
LOWER(text) as lower_text,
LENGTH(text) as text_len
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["upper_text"] == "HELLO WORLD"
assert df.iloc[0]["lower_text"] == "hello world"
assert df.iloc[0]["text_len"] == 11
client.close()
def test_coalesce_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 10},
{"id": 2}, ])
result = client.execute("""
SELECT id, COALESCE(value, 0) as safe_value
FROM default
ORDER BY id
""")
df = result.to_pandas()
assert df.iloc[0]["safe_value"] == 10
assert df.iloc[1]["safe_value"] == 0
client.close()
def test_cast_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"num": 42, "text": "100"}])
result = client.execute("""
SELECT
CAST(num AS VARCHAR) as num_str,
CAST(text AS INT) as text_num
FROM default
""")
df = result.to_pandas()
assert str(df.iloc[0]["num_str"]) == "42"
assert df.iloc[0]["text_num"] == 100
client.close()
def test_substr_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"text": "Hello World"}])
result = client.execute("""
SELECT SUBSTR(text, 1, 5) as sub FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["sub"] == "Hello"
client.close()
class TestSQLCase:
def test_case_simple(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "score": 95},
{"id": 2, "score": 75},
{"id": 3, "score": 55},
])
result = client.execute("""
SELECT id, score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 70 THEN 'B'
ELSE 'C'
END as grade
FROM default
ORDER BY id
""")
df = result.to_pandas()
assert df.iloc[0]["grade"] == "A"
assert df.iloc[1]["grade"] == "B"
assert df.iloc[2]["grade"] == "C"
client.close()
class TestSQLPerformance:
def test_large_result_set(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
batch_size = 1000
for batch in range(10):
rows = [{"id": batch * batch_size + i, "value": i % 100} for i in range(batch_size)]
client.store(rows)
start = time.time()
result = client.execute("SELECT COUNT(*) FROM default")
elapsed = time.time() - start
df = result.to_pandas()
assert df.iloc[0, 0] == 10000
assert elapsed < 1.0
client.close()
def test_aggregation_performance(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
rows = [{"id": i, "category": f"cat_{i % 10}", "value": i % 100} for i in range(5000)]
client.store(rows)
start = time.time()
result = client.execute("""
SELECT category, COUNT(*), SUM(value), AVG(value)
FROM default
GROUP BY category
ORDER BY category
""")
elapsed = time.time() - start
df = result.to_pandas()
assert len(df) == 10 assert elapsed < 2.0
client.close()
def test_filter_with_limit_performance(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
rows = [{"id": i, "status": "active" if i % 2 == 0 else "inactive"} for i in range(10000)]
client.store(rows)
start = time.time()
result = client.execute("""
SELECT * FROM default
WHERE status = 'active'
LIMIT 10
""")
elapsed = time.time() - start
assert len(result) == 10
assert elapsed < 0.5
client.close()
class TestSQLEdgeCases:
def test_empty_table_query(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("empty")
client.use_table("empty")
result = client.execute("SELECT * FROM empty")
assert len(result) == 0
result = client.execute("SELECT COUNT(*) FROM empty")
df = result.to_pandas()
assert df.iloc[0, 0] == 0
client.close()
def test_special_characters_in_values(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "text": "Hello 'World'"},
{"id": 2, "text": "Line1\nLine2"},
{"id": 3, "text": "Tab\there"},
])
result = client.execute("SELECT * FROM default ORDER BY id")
assert len(result) == 3
client.close()
def test_unicode_values(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "text": "ä½ å¥½ä¸–ç•Œ"},
{"id": 2, "text": "Ù…Ø±ØØ¨Ø§"},
{"id": 3, "text": "🎉🎊"},
])
result = client.execute("SELECT * FROM default ORDER BY id")
df = result.to_pandas()
assert df.iloc[0]["text"] == "ä½ å¥½ä¸–ç•Œ"
assert df.iloc[2]["text"] == "🎉🎊"
client.close()
def test_null_handling(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 10},
{"id": 2, "value": 0},
{"id": 3, "value": 5},
])
result = client.execute("SELECT id, COALESCE(value, 0) as safe_val FROM default ORDER BY id")
df = result.to_pandas()
assert len(df) == 3
assert df.iloc[0]["safe_val"] == 10
client.close()
def test_boolean_values(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "active": True},
{"id": 2, "active": False},
{"id": 3, "active": True},
])
result = client.execute("SELECT * FROM default WHERE active = true")
assert len(result) == 2
result = client.execute("SELECT * FROM default WHERE active = false")
assert len(result) == 1
client.close()
class TestSQLWindowFunctions:
def test_row_number_basic(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "name": "Alice", "score": 85},
{"id": 2, "name": "Bob", "score": 92},
{"id": 3, "name": "Charlie", "score": 78},
])
result = client.execute("""
SELECT name, score,
ROW_NUMBER() OVER (ORDER BY score DESC) as rank
FROM default
""")
df = result.to_pandas()
assert len(df) == 3
assert "rank" in df.columns
bob_row = df[df["name"] == "Bob"].iloc[0]
assert bob_row["rank"] == 1
client.close()
def test_row_number_partition_by(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"dept": "Sales", "name": "Alice", "salary": 5000},
{"dept": "Sales", "name": "Bob", "salary": 6000},
{"dept": "IT", "name": "Charlie", "salary": 7000},
{"dept": "IT", "name": "Diana", "salary": 8000},
{"dept": "IT", "name": "Eve", "salary": 6500},
])
result = client.execute("""
SELECT dept, name, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) as dept_rank
FROM default
""")
df = result.to_pandas()
assert len(df) == 5
it_rows = df[df["dept"] == "IT"].sort_values("dept_rank")
assert len(it_rows) == 3
assert it_rows.iloc[0]["name"] == "Diana" assert it_rows.iloc[0]["dept_rank"] == 1
client.close()
def test_row_number_with_filter(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"category": "A", "value": 10, "active": True},
{"category": "A", "value": 20, "active": True},
{"category": "A", "value": 30, "active": False},
{"category": "B", "value": 15, "active": True},
])
result = client.execute("""
SELECT category, value,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY value) as rn
FROM default
WHERE active = true
""")
df = result.to_pandas()
assert len(df) == 3
client.close()
def test_window_with_select_star(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 100},
{"id": 2, "value": 200},
{"id": 3, "value": 150},
])
result = client.execute("""
SELECT *, ROW_NUMBER() OVER (ORDER BY value DESC) as rank
FROM default
""")
df = result.to_pandas()
assert "id" in df.columns
assert "value" in df.columns
assert "rank" in df.columns
client.close()
def test_rank_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "name": "A", "score": 100},
{"id": 2, "name": "B", "score": 100}, {"id": 3, "name": "C", "score": 90},
{"id": 4, "name": "D", "score": 80},
])
result = client.execute("""
SELECT name, score, RANK() OVER (ORDER BY score DESC) as rnk
FROM default
""")
df = result.to_pandas()
assert len(df) == 4
a_rank = df[df["name"] == "A"].iloc[0]["rnk"]
b_rank = df[df["name"] == "B"].iloc[0]["rnk"]
c_rank = df[df["name"] == "C"].iloc[0]["rnk"]
assert a_rank == 1
assert b_rank == 1
assert c_rank == 3
client.close()
def test_dense_rank_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "name": "A", "score": 100},
{"id": 2, "name": "B", "score": 100}, {"id": 3, "name": "C", "score": 90},
{"id": 4, "name": "D", "score": 80},
])
result = client.execute("""
SELECT name, score, DENSE_RANK() OVER (ORDER BY score DESC) as drnk
FROM default
""")
df = result.to_pandas()
assert len(df) == 4
a_rank = df[df["name"] == "A"].iloc[0]["drnk"]
b_rank = df[df["name"] == "B"].iloc[0]["drnk"]
c_rank = df[df["name"] == "C"].iloc[0]["drnk"]
assert a_rank == 1
assert b_rank == 1
assert c_rank == 2
client.close()
def test_lag_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "month": 1, "sales": 100},
{"id": 2, "month": 2, "sales": 150},
{"id": 3, "month": 3, "sales": 120},
{"id": 4, "month": 4, "sales": 200},
])
result = client.execute("""
SELECT month, sales, LAG(sales) OVER (ORDER BY month) as prev_sales
FROM default
""")
df = result.to_pandas()
assert len(df) == 4
first_row = df[df["month"] == 1].iloc[0]
assert pd.isna(first_row["prev_sales"]) or first_row["prev_sales"] == 0
second_row = df[df["month"] == 2].iloc[0]
assert second_row["prev_sales"] == 100
client.close()
def test_lead_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "month": 1, "sales": 100},
{"id": 2, "month": 2, "sales": 150},
{"id": 3, "month": 3, "sales": 120},
{"id": 4, "month": 4, "sales": 200},
])
result = client.execute("""
SELECT month, sales, LEAD(sales) OVER (ORDER BY month) as next_sales
FROM default
""")
df = result.to_pandas()
assert len(df) == 4
first_row = df[df["month"] == 1].iloc[0]
assert first_row["next_sales"] == 150
last_row = df[df["month"] == 4].iloc[0]
assert pd.isna(last_row["next_sales"]) or last_row["next_sales"] == 0
client.close()
def test_first_value_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "dept": "Sales", "employee": 1, "salary": 5000},
{"id": 2, "dept": "Sales", "employee": 2, "salary": 6000},
{"id": 3, "dept": "IT", "employee": 3, "salary": 7000},
{"id": 4, "dept": "IT", "employee": 4, "salary": 8000},
])
result = client.execute("""
SELECT dept, salary, FIRST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary) as first_sal
FROM default
""")
df = result.to_pandas()
sales_rows = df[df["dept"] == "Sales"]
assert all(sales_rows["first_sal"] == 5000)
it_rows = df[df["dept"] == "IT"]
assert all(it_rows["first_sal"] == 7000)
client.close()
def test_last_value_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "dept": "Sales", "employee": 1, "salary": 5000},
{"id": 2, "dept": "Sales", "employee": 2, "salary": 6000},
{"id": 3, "dept": "IT", "employee": 3, "salary": 7000},
{"id": 4, "dept": "IT", "employee": 4, "salary": 8000},
])
result = client.execute("""
SELECT dept, salary, LAST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary) as last_sal
FROM default
""")
df = result.to_pandas()
sales_rows = df[df["dept"] == "Sales"]
assert all(sales_rows["last_sal"] == 6000)
it_rows = df[df["dept"] == "IT"]
assert all(it_rows["last_sal"] == 8000)
client.close()
def test_sum_over_partition(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "region": "East", "sales": 100},
{"id": 2, "region": "East", "sales": 200},
{"id": 3, "region": "West", "sales": 150},
{"id": 4, "region": "West", "sales": 250},
])
result = client.execute("""
SELECT region, sales, SUM(sales) OVER (PARTITION BY region) as total
FROM default
""")
df = result.to_pandas()
east_rows = df[df["region"] == "East"]
assert all(east_rows["total"] == 300)
west_rows = df[df["region"] == "West"]
assert all(west_rows["total"] == 400)
client.close()
def test_avg_over_partition(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "dept": "Sales", "salary": 4000},
{"id": 2, "dept": "Sales", "salary": 6000},
{"id": 3, "dept": "IT", "salary": 7000},
{"id": 4, "dept": "IT", "salary": 9000},
])
result = client.execute("""
SELECT dept, salary, AVG(salary) OVER (PARTITION BY dept) as avg_sal
FROM default
""")
df = result.to_pandas()
sales_rows = df[df["dept"] == "Sales"]
assert all(sales_rows["avg_sal"] == 5000)
it_rows = df[df["dept"] == "IT"]
assert all(it_rows["avg_sal"] == 8000)
client.close()
def test_count_over_partition(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "category": "A", "value": 10},
{"id": 2, "category": "A", "value": 20},
{"id": 3, "category": "A", "value": 30},
{"id": 4, "category": "B", "value": 40},
{"id": 5, "category": "B", "value": 50},
])
result = client.execute("""
SELECT category, value, COUNT() OVER (PARTITION BY category) as cnt
FROM default
""")
df = result.to_pandas()
a_rows = df[df["category"] == "A"]
assert all(a_rows["cnt"] == 3)
b_rows = df[df["category"] == "B"]
assert all(b_rows["cnt"] == 2)
client.close()
def test_min_max_over_partition(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "dept": "Sales", "salary": 4000},
{"id": 2, "dept": "Sales", "salary": 6000},
{"id": 3, "dept": "Sales", "salary": 5000},
{"id": 4, "dept": "IT", "salary": 7000},
{"id": 5, "dept": "IT", "salary": 9000},
])
result = client.execute("""
SELECT dept, salary, MIN(salary) OVER (PARTITION BY dept) as min_sal
FROM default
""")
df = result.to_pandas()
sales_rows = df[df["dept"] == "Sales"]
assert all(sales_rows["min_sal"] == 4000)
it_rows = df[df["dept"] == "IT"]
assert all(it_rows["min_sal"] == 7000)
result = client.execute("""
SELECT dept, salary, MAX(salary) OVER (PARTITION BY dept) as max_sal
FROM default
""")
df = result.to_pandas()
sales_rows = df[df["dept"] == "Sales"]
assert all(sales_rows["max_sal"] == 6000)
it_rows = df[df["dept"] == "IT"]
assert all(it_rows["max_sal"] == 9000)
client.close()
def test_running_sum(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "month": 1, "revenue": 100},
{"id": 2, "month": 2, "revenue": 150},
{"id": 3, "month": 3, "revenue": 200},
{"id": 4, "month": 4, "revenue": 250},
])
result = client.execute("""
SELECT month, revenue, RUNNING_SUM(revenue) OVER (ORDER BY month) as cumulative
FROM default
""")
df = result.to_pandas()
sorted_df = df.sort_values("month")
assert sorted_df.iloc[0]["cumulative"] == 100
assert sorted_df.iloc[1]["cumulative"] == 250
assert sorted_df.iloc[2]["cumulative"] == 450
assert sorted_df.iloc[3]["cumulative"] == 700
client.close()
def test_ntile_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": i, "value": i * 10} for i in range(1, 9) ])
result = client.execute("""
SELECT id, value, NTILE() OVER (ORDER BY value) as bucket
FROM default
""")
df = result.to_pandas()
assert len(df) == 8
assert "bucket" in df.columns
client.close()
def test_window_function_performance(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
import time
data = [{"id": i, "cat": i % 10, "value": i * 10} for i in range(1000)]
client.store(data)
start = time.time()
result = client.execute("""
SELECT cat, value,
ROW_NUMBER() OVER (PARTITION BY cat ORDER BY value DESC) as rn
FROM default
""")
elapsed = time.time() - start
df = result.to_pandas()
assert len(df) == 1000
for c in range(10):
cat_rows = df[df["cat"] == c]
assert len(cat_rows) == 100, f"Category {c} has {len(cat_rows)} rows"
assert cat_rows["rn"].max() == 100
assert elapsed < 1.0, f"Window function took {elapsed:.2f}s, expected < 1s"
client.close()
class TestSQLJoins:
def test_inner_join(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.create_table("users")
client.use_table("users")
client.store([
{"user_id": 1, "name": "Alice"},
{"user_id": 2, "name": "Bob"},
{"user_id": 3, "name": "Charlie"},
])
client.flush()
client.create_table("orders")
client.use_table("orders")
client.store([
{"order_id": 101, "user_id": 1, "amount": 50.0},
{"order_id": 102, "user_id": 1, "amount": 75.0},
{"order_id": 103, "user_id": 2, "amount": 100.0},
])
client.flush()
result = client.execute("""
SELECT u.name, o.order_id, o.amount
FROM users u
JOIN orders o ON u.user_id = o.user_id
ORDER BY o.order_id
""")
df = result.to_pandas()
assert len(df) == 3
assert df.iloc[0]["name"] == "Alice"
client.close()
def test_left_join(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.create_table("customers")
client.use_table("customers")
client.store([
{"cust_id": 1, "name": "Alice"},
{"cust_id": 2, "name": "Bob"},
{"cust_id": 3, "name": "Charlie"}, ])
client.flush()
client.create_table("sales")
client.use_table("sales")
client.store([
{"sale_id": 1, "cust_id": 1, "total": 100},
{"sale_id": 2, "cust_id": 2, "total": 200},
])
client.flush()
result = client.execute("""
SELECT c.name, s.total
FROM customers c
LEFT JOIN sales s ON c.cust_id = s.cust_id
ORDER BY c.cust_id
""")
df = result.to_pandas()
assert len(df) == 3
client.close()
def test_join_with_aggregation(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.create_table("employees")
client.use_table("employees")
client.store([
{"emp_id": 1, "dept": "Sales", "salary": 5000},
{"emp_id": 2, "dept": "Sales", "salary": 6000},
{"emp_id": 3, "dept": "IT", "salary": 7000},
])
client.flush()
result = client.execute("""
SELECT dept, COUNT(*) as emp_count, SUM(salary) as total_salary
FROM employees
GROUP BY dept
ORDER BY dept
""")
df = result.to_pandas()
assert len(df) == 2
client.close()
class TestSQLExpressions:
def test_arithmetic_in_where(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "price": 100, "qty": 2},
{"id": 2, "price": 50, "qty": 5},
{"id": 3, "price": 200, "qty": 1},
])
result = client.execute("SELECT * FROM default WHERE price > 75")
assert len(result) == 2
client.close()
def test_column_alias(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"long_column_name": 100}])
result = client.execute("""
SELECT long_column_name AS short
FROM default
""")
df = result.to_pandas()
assert "short" in df.columns
assert df.iloc[0]["short"] == 100
client.close()
def test_literal_values_in_select(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"id": 1}])
result = client.execute("""
SELECT id, 'constant' as str_const, 42 as num_const
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["str_const"] == "constant"
assert df.iloc[0]["num_const"] == 42
client.close()
def test_comparison_operators(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"id": 1, "value": 10},
{"id": 2, "value": 20},
{"id": 3, "value": 30},
{"id": 4, "value": 40},
{"id": 5, "value": 50},
])
result = client.execute("SELECT * FROM default WHERE value > 30")
assert len(result) == 2
result = client.execute("SELECT * FROM default WHERE value <= 20")
assert len(result) == 2
result = client.execute("SELECT * FROM default WHERE value != 30")
assert len(result) == 4
result = client.execute("SELECT * FROM default WHERE value = 30")
assert len(result) == 1
client.close()
class TestSQLStringOperations:
def test_concat_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"fname": "John", "lname": "Doe"}])
result = client.execute("""
SELECT CONCAT(fname, lname) as combined
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["combined"] == "JohnDoe"
client.close()
def test_trim_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"text": " hello "}])
result = client.execute("""
SELECT TRIM(text) as trimmed
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["trimmed"] == "hello"
client.close()
def test_replace_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"text": "hello world"}])
result = client.execute("""
SELECT REPLACE(text, 'world', 'universe') as replaced
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["replaced"] == "hello universe"
client.close()
class TestSQLMathFunctions:
def test_abs_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"value": 10}])
result = client.execute("SELECT ABS(value) as abs_val FROM default")
df = result.to_pandas()
assert df.iloc[0]["abs_val"] == 10
client.close()
def test_round_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"value": 3.14159}])
result = client.execute("SELECT ROUND(value, 2) as rounded FROM default")
df = result.to_pandas()
assert abs(df.iloc[0]["rounded"] - 3.14) < 0.01
client.close()
def test_floor_ceil_functions(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"value": 3.7}])
result = client.execute("""
SELECT
FLOOR(value) as floor_val,
CEIL(value) as ceil_val
FROM default
""")
df = result.to_pandas()
assert df.iloc[0]["floor_val"] == 3
assert df.iloc[0]["ceil_val"] == 4
client.close()
def test_sqrt_function(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([{"value": 16}])
result = client.execute("SELECT SQRT(value) as sqrt_val FROM default")
df = result.to_pandas()
assert df.iloc[0]["sqrt_val"] == 4.0
client.close()
class TestSQLComplexQueries:
def test_aggregation_by_type(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"type": "sale", "amount": 100},
{"type": "refund", "amount": 50},
{"type": "sale", "amount": 200},
{"type": "sale", "amount": 150},
])
result = client.execute("""
SELECT type, SUM(amount) as total
FROM default
GROUP BY type
ORDER BY type
""")
df = result.to_pandas()
assert len(df) == 2
refund_row = df[df["type"] == "refund"].iloc[0]
sale_row = df[df["type"] == "sale"].iloc[0]
assert refund_row["total"] == 50
assert sale_row["total"] == 450
client.close()
def test_filter_group_having_order_limit(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.store([
{"category": "A", "status": "active", "value": 10},
{"category": "A", "status": "active", "value": 20},
{"category": "A", "status": "inactive", "value": 5},
{"category": "B", "status": "active", "value": 100},
{"category": "B", "status": "active", "value": 50},
{"category": "C", "status": "active", "value": 15},
])
result = client.execute("""
SELECT category, SUM(value) as total
FROM default
WHERE status = 'active'
GROUP BY category
HAVING SUM(value) > 20
ORDER BY total DESC
LIMIT 2
""")
df = result.to_pandas()
assert len(df) == 2
assert df.iloc[0]["category"] == "B"
assert df.iloc[0]["total"] == 150
client.close()
def test_multiple_tables_complex_query(self):
with tempfile.TemporaryDirectory() as temp_dir:
client = ApexClient(dirpath=temp_dir)
client.create_table("default")
client.create_table("products")
client.use_table("products")
client.store([
{"product_id": 1, "name": "Widget", "price": 10.0},
{"product_id": 2, "name": "Gadget", "price": 25.0},
])
client.flush()
client.create_table("sales")
client.use_table("sales")
client.store([
{"sale_id": 1, "product_id": 1, "quantity": 5},
{"sale_id": 2, "product_id": 1, "quantity": 3},
{"sale_id": 3, "product_id": 2, "quantity": 2},
])
client.flush()
result = client.execute("""
SELECT p.name, SUM(s.quantity) as total_qty
FROM products p
JOIN sales s ON p.product_id = s.product_id
GROUP BY p.name
ORDER BY total_qty DESC
""")
df = result.to_pandas()
assert len(df) == 2
assert df.iloc[0]["name"] == "Widget"
assert df.iloc[0]["total_qty"] == 8
client.close()