Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into random-values-from-…
Browse files Browse the repository at this point in the history
…file
  • Loading branch information
hmeriann committed Sep 12, 2024
2 parents e08843b + 0008ffd commit f629ec1
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 87 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/TestDebug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Test Debug
on:
workflow_dispatch:
pull_request:
push:
branches:
- '**'
- '!main'

jobs:
build-duckdb:
name: Build DuckDB
runs-on: ubuntu-latest
timeout-minutes: 120
outputs:
duckdb-hash: ${{ steps.find-hash.outputs.hash }}
env:
BUILD_ICU: 1
BUILD_JSON: 1
BUILD_TPCH: 1
BUILD_TPCDS: 1
BUILD_PARQUET: 1
BUILD_JEMALLOC: 1
CRASH_ON_ASSERT: 1

steps:
- name: Dependencies
shell: bash
run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build ccache

- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive

- name: Setup Ccache
uses: hendrikmuhs/ccache-action@main

- name: Build and Test
shell: bash
run: |
make test_debug
93 changes: 18 additions & 75 deletions .github/workflows/test-fuzzer-ci-still-works.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,88 +10,31 @@ on:
jobs:
build-duckdb:
name: Build DuckDB
runs-on: ubuntu-latest
timeout-minutes: 120
outputs:
duckdb-hash: ${{ steps.find-hash.outputs.hash }}
env:
BUILD_ICU: 1
BUILD_JSON: 1
BUILD_TPCH: 1
BUILD_TPCDS: 1
BUILD_PARQUET: 1
BUILD_JEMALLOC: 1
CRASH_ON_ASSERT: 1
GEN: ninja

steps:
- name: Dependencies
shell: bash
run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build ccache

- uses: actions/checkout@v3
with:
repository: duckdb/duckdb
fetch-depth: 0

- name: Setup Ccache
uses: hendrikmuhs/ccache-action@main

- id: find-hash
run: echo "::set-output name=hash::$(git rev-parse HEAD)"

- name: create build sqlsmith extension file
shell: bash
run: |
echo "duckdb_extension_load(sqlsmith
GIT_URL https://github.com/duckdb/duckdb_sqlsmith
GIT_TAG main
)" > sqlsmith.cmake
- name: Build
shell: bash
run: |
EXTENSION_CONFIGS="sqlsmith.cmake" make debug
- uses: actions/upload-artifact@v3
with:
name: duckdb
path: build/debug/duckdb
uses: duckdblabs/duckdb-fuzzer-ci/.github/workflows/reusable_workflows/build_fuzzer.yml@main
with:
git_url: ${{ github.actor }}
git_tag: ${{ github.ref_name }}
timeout-minutes: 120

fuzzer:
name: Fuzzer
needs:
- build-duckdb
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
fuzzer: [duckfuzz, sqlsmith, duckfuzz_functions]
data: [emptyalltypes]

steps:
- uses: actions/checkout@v3
with:
path: duckdb_sqlsmith
fetch-depth: 0

- name: Download a single artifact
uses: actions/download-artifact@v3
with:
name: duckdb

- name: Fuzz
shell: bash
run: |
chmod +x duckdb
runtime="1 minute"
endtime=$(date -ud "$runtime" +%s)
cd duckdb_sqlsmith
while [[ $(date -u +%s) -le $endtime ]]
do
echo "Time Now: `date +%H:%M:%S`"
python3 scripts/run_fuzzer.py --no_checks --${{ matrix.fuzzer }} --${{ matrix.data }} --shell=../duckdb --dry --max_queries=10
done
enable_verification: [true, false]
exclude:
- enable_verification: true
fuzzer: sqlsmith
- enable_verification: true
fuzzer: duckfuzz_functions
uses: duckdblabs/duckdb-fuzzer-ci/.github/workflows/reusable_workflows/fuzz_duckdb.yml@main
with:
fuzzer: ${{ matrix.fuzzer }}
data: ${{ matrix.data }}
timeout-minutes: 20
max_queries: 10
enable_verification: ${{ matrix.enable_verification }}
2 changes: 1 addition & 1 deletion duckdb
Submodule duckdb updated 2589 files
28 changes: 25 additions & 3 deletions scripts/reduce_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
SELECT * FROM reduce_sql_statement('${QUERY}');
'''

verbose = False

class MultiStatementManager:
delimiter = ';'
Expand All @@ -33,7 +34,8 @@ def __init__(self, multi_statement):
self.statements.append(stmt.strip() + ";")

def is_multi_statement(sql_statement):
if len(sql_statement.split(';')) > 1:
splits = [x for x in sql_statement.split(';') if len(x.strip()) > 0]
if len(splits) > 1:
return True
return False

Expand All @@ -45,10 +47,12 @@ def sanitize_error(err):
err = re.sub(r'Error: near line \d+: ', '', err)
err = err.replace(os.getcwd() + '/', '')
err = err.replace(os.getcwd(), '')
err = re.sub(r'LINE \d+:.*\n', '', err)
err = re.sub(r' *\^ *', '', err)
if 'AddressSanitizer' in err:
match = re.search(r'[ \t]+[#]0 ([A-Za-z0-9]+) ([^\n]+)', err).groups()[1]
err = 'AddressSanitizer error ' + match
return err
return err.strip()


def run_shell_command(shell, cmd):
Expand All @@ -69,7 +73,13 @@ def get_reduced_sql(shell, sql_query):
raise Exception("Failed to reduce query")
reduce_candidates = []
for line in stdout.split('\n'):
reduce_candidates.append(line.strip('"').replace('""', '"'))
if len(line) <= 2:
continue
if line[0] == '"':
line = line[1:]
if line[len(line) - 1] == '"':
line = line[:len(line) - 1]
reduce_candidates.append(line.replace('""', '"'))
return reduce_candidates[1:]


Expand All @@ -95,6 +105,15 @@ def reduce(sql_query, data_load, shell, error_msg, max_time_seconds=300):
print(sql_query)
print("=======================")
break
elif verbose:
print("Failed to reduce query")
print("=======================")
print(reduce_candidate)
print("=====Target error======")
print(error_msg)
print("=====Actual error======")
print(new_error)
print("=======================")
if not found_new_candidate:
break
return sql_query
Expand Down Expand Up @@ -271,13 +290,16 @@ def reduce_query_log(queries, shell, data_load=[], max_time_seconds=300):
parser.add_argument(
'--max-time', dest='max_time', action='store', help='Maximum time in seconds to run the reducer', default=300
)
parser.add_argument(
'--verbose', dest='verbose', action='store_true', help='Verbose output')

args = parser.parse_args()
print("Starting reduce process")

shell = args.shell
data_load = open(args.load).read()
sql_query = open(args.exec).read()
verbose = args.verbose
(stdout, stderr, returncode) = run_shell_command(shell, data_load + sql_query)
expected_error = sanitize_error(stderr).strip()
if len(expected_error) == 0:
Expand Down
19 changes: 12 additions & 7 deletions scripts/run_fuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
db = None
shell = None
perform_checks = True
dry = False
no-git-checks = False
max_queries = 1000
verification = False

for param in sys.argv:
if param == '--sqlsmith':
fuzzer = 'sqlsmith'
Expand All @@ -31,16 +32,16 @@
db = 'emptyalltypes'
elif param == '--no_checks':
perform_checks = False
elif param == '--enable_verification':
verification = True
elif param.startswith('--enable_verification'):
verification = param.replace('--enable_verification=', '').lower() == 'true'
elif param.startswith('--shell='):
shell = param.replace('--shell=', '')
elif param.startswith('--seed='):
seed = int(param.replace('--seed=', ''))
elif param.startswith('--max_queries='):
max_queries = int(param.replace('--max_queries=', ''))
elif param.startswith('--dry'):
dry = True
elif param.startswith('--no-git-checks'):
no-git-checks = param.replace('--no-git-checks=', '').lower() == 'true'

if fuzzer is None:
print("Unrecognized fuzzer to run, expected e.g. --sqlsmith or --duckfuzz")
Expand Down Expand Up @@ -103,11 +104,14 @@ def run_shell_command(cmd):

# first get a list of all github issues, and check if we can still reproduce them

if dry:
if no-git-checks:
current_errors = []
else:
current_errors = fuzzer_helper.extract_github_issues(shell, perform_checks)

# Don't go on and fuzz if perform checks = true
if perform_checks:
exit(0)

last_query_log_file = 'sqlsmith.log'
complete_log_file = 'sqlsmith.complete.log'
Expand All @@ -118,6 +122,7 @@ def run_shell_command(cmd):
=========================================='''
)


load_script = create_db_script(db)
fuzzer_name = get_fuzzer_name(fuzzer)
fuzzer = (
Expand Down Expand Up @@ -212,5 +217,5 @@ def run_shell_command(cmd):
print(f"{error_msg}")
print(f"================MARKER====================")

if not dry:
if not no-git-checks:
fuzzer_helper.file_issue(cmd, error_msg, fuzzer_name, seed, git_hash)
2 changes: 2 additions & 0 deletions src/include/statement_simplifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class SQLStatement;
class SelectStatement;
class InsertStatement;
class UpdateStatement;
class PrepareStatement;
class DeleteStatement;
class TableRef;
class SelectNode;
Expand All @@ -41,6 +42,7 @@ class StatementSimplifier {
void Simplify(SelectStatement &stmt);
void Simplify(InsertStatement &stmt);
void Simplify(UpdateStatement &stmt);
void Simplify(PrepareStatement &stmt);
void Simplify(DeleteStatement &stmt);

void Simplification();
Expand Down
9 changes: 9 additions & 0 deletions src/statement_simplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "duckdb/parser/expression/list.hpp"
#include "duckdb/parser/statement/delete_statement.hpp"
#include "duckdb/parser/statement/insert_statement.hpp"
#include "duckdb/parser/statement/prepare_statement.hpp"
#include "duckdb/parser/statement/update_statement.hpp"
#include "duckdb/parser/statement/select_statement.hpp"
#endif
Expand Down Expand Up @@ -308,6 +309,7 @@ void StatementSimplifier::SimplifyExpression(duckdb::unique_ptr<ParsedExpression
SimplifyChildExpression(expr, case_check.then_expr);
SimplifyChildExpression(expr, case_check.when_expr);
}
SimplifyList(op.case_checks, false);
break;
}
case ExpressionClass::CAST: {
Expand Down Expand Up @@ -423,6 +425,10 @@ void StatementSimplifier::Simplify(UpdateSetInfo &info) {
}
}

void StatementSimplifier::Simplify(PrepareStatement &stmt) {
Simplify(*stmt.statement);
}

void StatementSimplifier::Simplify(UpdateStatement &stmt) {
Simplify(stmt.cte_map);
SimplifyOptional(stmt.from_table);
Expand All @@ -445,6 +451,9 @@ void StatementSimplifier::Simplify(SQLStatement &stmt) {
case StatementType::DELETE_STATEMENT:
Simplify(stmt.Cast<DeleteStatement>());
break;
case StatementType::PREPARE_STATEMENT:
Simplify(stmt.Cast<PrepareStatement>());
break;
default:
throw InvalidInputException("Expected a single SELECT, INSERT or UPDATE statement");
}
Expand Down
11 changes: 11 additions & 0 deletions test/sql/call_fuzzyduck.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# name: test/sql/call_fuzzyduck.test
# description: Test fuzzyduck
# group: [fuzzyduck]

require sqlsmith

statement ok
call fuzzyduck(max_queries=2, verbose_output=1, log='sqlsmith.log', complete_log='sqlsmith.complete.log', enable_verification=True);

statement ok
call fuzzyduck(max_queries=2, verbose_output=1, log='__TEST_DIR__/logs.txt', complete_log='__TEST_DIR__/clog.txt', enable_verification=false);
15 changes: 14 additions & 1 deletion test/sql/sql_reduce.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# name: test/sql_reduce.test
# name: test/sql/sql_reduce.test
# description: Test reduce SQL statement
# group: [sqlsmith]

Expand Down Expand Up @@ -77,3 +77,16 @@ DELETE FROM a WHERE (i < 5000)
DELETE FROM a WHERE (i >= 2000)
DELETE FROM a WHERE (i AND (i < 5000))
DELETE FROM a WHERE NULL

query I
SELECT * FROM reduce_sql_statement('PREPARE v1 AS SELECT a, b FROM tbl') ORDER BY 1
----
PREPARE v1 AS SELECT NULL, b FROM tbl
PREPARE v1 AS SELECT NULL, b FROM tbl
PREPARE v1 AS SELECT a FROM tbl
PREPARE v1 AS SELECT a, NULL FROM tbl
PREPARE v1 AS SELECT a, NULL FROM tbl
PREPARE v1 AS SELECT a, b
PREPARE v1 AS SELECT a, b FROM tbl
PREPARE v1 AS SELECT a, b FROM tbl
PREPARE v1 AS SELECT b FROM tbl

0 comments on commit f629ec1

Please sign in to comment.