Skip to content

Commit

Permalink
Add deparsing functionality that turns parse tree back into a SQL query
Browse files Browse the repository at this point in the history
This is based on the deparser that was written over multiple years for
the pg_query Ruby library, and is now accessible for all bindings through
this new API and implementation.

Note that there are still many (mostly special case) queries that are
not yet supported by the deparser.
  • Loading branch information
lfittl committed Mar 18, 2021
1 parent ed498f2 commit aa05c85
Show file tree
Hide file tree
Showing 7 changed files with 4,294 additions and 1 deletion.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,12 @@ examples/normalize_error: examples/normalize_error.c $(ARLIB)
examples/simple_plpgsql: examples/simple_plpgsql.c $(ARLIB)
$(CC) $(TEST_CFLAGS) -o $@ -g examples/simple_plpgsql.c $(ARLIB) $(TEST_LDFLAGS)

TESTS = test/complex test/concurrency test/fingerprint test/normalize test/parse test/parse_protobuf test/parse_plpgsql test/scan
TESTS = test/complex test/concurrency test/deparse test/fingerprint test/normalize test/parse test/parse_protobuf test/parse_plpgsql test/scan
test: $(TESTS)
ifeq ($(VALGRIND),1)
$(VALGRIND_MEMCHECK) test/complex || (cat test/valgrind.log && false)
$(VALGRIND_MEMCHECK) test/concurrency || (cat test/valgrind.log && false)
$(VALGRIND_MEMCHECK) test/deparse || (cat test/valgrind.log && false)
$(VALGRIND_MEMCHECK) test/fingerprint || (cat test/valgrind.log && false)
$(VALGRIND_MEMCHECK) test/normalize || (cat test/valgrind.log && false)
$(VALGRIND_MEMCHECK) test/parse || (cat test/valgrind.log && false)
Expand All @@ -197,6 +198,7 @@ ifeq ($(VALGRIND),1)
else
test/complex
test/concurrency
test/deparse
test/fingerprint
test/normalize
test/parse
Expand All @@ -214,6 +216,9 @@ test/complex: test/complex.c $(ARLIB)
test/concurrency: test/concurrency.c test/parse_tests.c $(ARLIB)
$(CC) $(TEST_CFLAGS) -o $@ test/concurrency.c $(ARLIB) $(TEST_LDFLAGS)

test/deparse: test/deparse.c test/deparse_tests.c $(ARLIB)
$(CC) $(TEST_CFLAGS) -o $@ test/deparse.c $(ARLIB) $(TEST_LDFLAGS)

test/fingerprint: test/fingerprint.c test/fingerprint_tests.c $(ARLIB)
# We have "-Isrc/" because this test uses pg_query_fingerprint_with_opts
$(CC) $(TEST_CFLAGS) -o $@ -Isrc/ test/fingerprint.c $(ARLIB) $(TEST_LDFLAGS)
Expand Down
8 changes: 8 additions & 0 deletions pg_query.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ typedef struct {
PgQueryError* error;
} PgQueryProtobufParseResult;

typedef struct {
char* query;
PgQueryError* error;
} PgQueryDeparseResult;

typedef struct {
char* plpgsql_funcs;
PgQueryError* error;
Expand Down Expand Up @@ -62,9 +67,12 @@ PgQueryPlpgsqlParseResult pg_query_parse_plpgsql(const char* input);

PgQueryFingerprintResult pg_query_fingerprint(const char* input);

PgQueryDeparseResult pg_query_deparse_protobuf(PgQueryProtobuf parse_tree);

void pg_query_free_normalize_result(PgQueryNormalizeResult result);
void pg_query_free_scan_result(PgQueryScanResult result);
void pg_query_free_parse_result(PgQueryParseResult result);
void pg_query_free_deparse_result(PgQueryDeparseResult result);
void pg_query_free_protobuf_parse_result(PgQueryProtobufParseResult result);
void pg_query_free_plpgsql_parse_result(PgQueryPlpgsqlParseResult result);
void pg_query_free_fingerprint_result(PgQueryFingerprintResult result);
Expand Down
2 changes: 2 additions & 0 deletions scripts/extract_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ def write_out
runner.deep_resolve('bms_free')
runner.deep_resolve('makeBitString')

# Needed for deparse
runner.deep_resolve('pg_toupper')

# Needed for normalize
runner.deep_resolve('pg_qsort')
Expand Down

0 comments on commit aa05c85

Please sign in to comment.