#!/bin/bash
# Test execute_sql "limited" flag behavior
# Usage: ./test_sql_limit.sh [db_path]
# Default: ../db/test.duckdb (ALWAYS USE TEST DATABASE!)
#
# This tests the fix for the bug where "limited" was always false
# even when results were truncated.
source "$(dirname "$0")/test_lib.sh"
# Get absolute paths before changing directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# Convert DB_PATH to absolute path (before we cd later)
DB_PATH_ARG="${1:-$PROJECT_DIR/db/test.duckdb}"
if [[ "$DB_PATH_ARG" = /* ]]; then
DB_PATH="$DB_PATH_ARG"
else
DB_PATH="$(cd "$(dirname "$DB_PATH_ARG")" && pwd)/$(basename "$DB_PATH_ARG")"
fi
if [ ! -f "$DB_PATH" ]; then
echo -e "${RED}Error: Database not found at $DB_PATH${NC}"
exit 1
fi
echo "=== Testing execute_sql 'limited' Flag ==="
echo ""
echo "Database: $DB_PATH"
echo ""
check_binary
# Navigate to the project directory where skraak binary is located
cd "$PROJECT_DIR" || exit 1
# Helper to run CLI command and capture JSON output (stderr discarded)
run_cli() {
"$PROJECT_DIR/skraak" "$@" 2>/dev/null || true
}
# Count total files in database for test planning
FILE_COUNT=$(run_cli sql --db "$DB_PATH" "SELECT COUNT(*) as cnt FROM file WHERE active = true" | jq -r '.rows[0].cnt // 0')
LOCATION_COUNT=$(run_cli sql --db "$DB_PATH" "SELECT COUNT(*) as cnt FROM location WHERE active = true" | jq -r '.rows[0].cnt // 0')
DATASET_COUNT=$(run_cli sql --db "$DB_PATH" "SELECT COUNT(*) as cnt FROM dataset WHERE active = true" | jq -r '.rows[0].cnt // 0')
echo "Database stats:"
echo " Files: $FILE_COUNT"
echo " Locations: $LOCATION_COUNT"
echo " Datasets: $DATASET_COUNT"
echo ""
# We need at least some files to test truncation
if [ "$FILE_COUNT" -lt 100 ]; then
echo -e "${YELLOW}Warning: Need at least 100 files to test truncation. Have $FILE_COUNT.${NC}"
echo "Some tests may be skipped."
echo ""
fi
TESTS_RUN=0
TESTS_PASSED=0
TESTS_FAILED=0
# Test helper: check limited flag and row count
test_limit_flag() {
local name="$1"
local expected_limited="$2"
local expected_row_count="$3"
local result="$4"
((TESTS_RUN++)) || true
# Note: jq '//' operator treats false as empty, so check for boolean explicitly
local actual_limited=$(echo "$result" | jq -r 'if has("limited") then (.limited | tostring) else "missing" end')
local actual_row_count=$(echo "$result" | jq -r '.row_count // -1')
if [ "$actual_limited" = "$expected_limited" ] && [ "$actual_row_count" -eq "$expected_row_count" ]; then
echo -e "${GREEN}✓${NC} $name"
echo " row_count=$actual_row_count, limited=$actual_limited"
((TESTS_PASSED++)) || true
return 0
else
echo -e "${RED}✗${NC} $name"
echo " Expected: row_count=$expected_row_count, limited=$expected_limited"
echo " Actual: row_count=$actual_row_count, limited=$actual_limited"
((TESTS_FAILED++)) || true
return 1
fi
}
# Test helper: check query_executed field
test_query_reported() {
local name="$1"
local expected_query_fragment="$2"
local result="$3"
((TESTS_RUN++)) || true
local query=$(echo "$result" | jq -r '.query_executed // ""')
if echo "$query" | grep -q "$expected_query_fragment"; then
echo -e "${GREEN}✓${NC} $name"
echo " query: $query"
((TESTS_PASSED++)) || true
return 0
else
echo -e "${RED}✗${NC} $name"
echo " Expected fragment: $expected_query_fragment"
echo " Actual query: $query"
((TESTS_FAILED++)) || true
return 1
fi
}
echo "=== Test 1: Auto-limit with truncation ==="
echo "Query without LIMIT on large table should trigger truncation"
if [ "$FILE_COUNT" -ge 100 ]; then
result=$(run_cli sql --db "$DB_PATH" "SELECT * FROM file WHERE active = true")
test_limit_flag "Auto-limit truncates results" "true" "1000" "$result"
test_query_reported "Query shows effective limit 1000" "LIMIT 1000" "$result"
else
echo -e "${YELLOW}⊘${NC} Skipped (need >= 100 files)"
fi
echo ""
echo "=== Test 2: Auto-limit without truncation ==="
echo "Query without LIMIT on small table should not truncate"
result=$(run_cli sql --db "$DB_PATH" "SELECT * FROM dataset WHERE active = true")
EXPECTED_ROWS=$DATASET_COUNT
test_limit_flag "Auto-limit no truncation" "false" "$EXPECTED_ROWS" "$result"
echo ""
echo "=== Test 3: User-provided LIMIT preserved ==="
echo "User's own LIMIT clause should be preserved"
result=$(run_cli sql --db "$DB_PATH" "SELECT * FROM file WHERE active = true LIMIT 5")
test_limit_flag "User LIMIT: limited=false" "false" "5" "$result"
test_query_reported "User LIMIT preserved in query" "LIMIT 5$" "$result"
echo ""
echo "=== Test 4: User LIMIT equal to default ==="
echo "User LIMIT 1000 should work (not double-limited)"
result=$(run_cli sql --db "$DB_PATH" "SELECT * FROM file WHERE active = true LIMIT 1000")
test_limit_flag "User LIMIT 1000: limited=false" "false" "1000" "$result"
test_query_reported "User LIMIT 1000 preserved" "LIMIT 1000$" "$result"
echo ""
echo "=== Test 5: Explicit --limit parameter with truncation ==="
echo "Using --limit 100 should truncate if table has > 100 rows"
if [ "$FILE_COUNT" -ge 100 ]; then
result=$(run_cli sql --db "$DB_PATH" --limit 100 "SELECT * FROM file WHERE active = true")
test_limit_flag "--limit 100 truncates" "true" "100" "$result"
test_query_reported "Query shows LIMIT 100" "LIMIT 100" "$result"
else
echo -e "${YELLOW}⊘${NC} Skipped (need >= 100 files)"
fi
echo ""
echo "=== Test 6: Explicit --limit parameter without truncation ==="
echo "Using --limit larger than table should not truncate"
result=$(run_cli sql --db "$DB_PATH" --limit 100 "SELECT * FROM dataset WHERE active = true")
EXPECTED_ROWS=$DATASET_COUNT
test_limit_flag "--limit > table size: no truncation" "false" "$EXPECTED_ROWS" "$result"
echo ""
echo "=== Test 7: Empty result set ==="
echo "Query returning no rows should have limited=false"
result=$(run_cli sql --db "$DB_PATH" "SELECT * FROM dataset WHERE id = 'NONEXISTENT_ID_12345'")
test_limit_flag "Empty result: limited=false" "false" "0" "$result"
echo ""
echo "=== Test 8: Small --limit with small table ==="
echo "--limit 1 on datasets should work correctly"
result=$(run_cli sql --db "$DB_PATH" --limit 1 "SELECT * FROM dataset WHERE active = true")
if [ "$DATASET_COUNT" -gt 1 ]; then
test_limit_flag "--limit 1 truncates (table has $DATASET_COUNT)" "true" "1" "$result"
else
test_limit_flag "--limit 1 no truncation (table has $DATASET_COUNT)" "false" "$DATASET_COUNT" "$result"
fi
echo ""
echo "=== Summary ==="
echo "Tests run: $TESTS_RUN"
echo -e "Passed: ${GREEN}$TESTS_PASSED${NC}"
if [ "$TESTS_FAILED" -gt 0 ]; then
echo -e "Failed: ${RED}$TESTS_FAILED${NC}"
exit 1
else
echo -e "Failed: $TESTS_FAILED"
fi