Skip to content

Commit b6c869d

Browse files
authored
Update to lib_pb_query 6.2.2 (#16)
Also adds a couple of validation steps: - guard against large queries to prevent a segfault trying to allocate more memory than is available on the stack - guard against null values in the protobuf ast passed to deparse. And adds fuzzing to the library. This found a single problem, which was caused by NULLs in the AST passed to deparse.
1 parent dd739bf commit b6c869d

648 files changed

Lines changed: 15435 additions & 5133 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,12 @@ pg_query-*.tar
2727

2828
# compiled nif
2929
priv/*.so
30+
31+
# Fuzz build outputs (compiled binaries)
32+
fuzz/_build/
33+
34+
# Generated deparse corpus - rebuild with: make fuzz-corpus
35+
fuzz/corpus/deparse/
36+
37+
# libFuzzer-discovered corpus entries (hash-named files added during fuzzing runs)
38+
fuzz/corpus/parse/[0-9a-f][0-9a-f][0-9a-f][0-9a-f]*

Makefile

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,75 @@ ifeq ($(shell uname -s),Darwin)
1111
LDFLAGS += -undefined dynamic_lookup
1212
endif
1313

14-
.PHONY: all libpg_query_ex clean update-libpg_query
14+
FUZZ_CC = clang
15+
FUZZ_CFLAGS = -g -O1 -fsanitize=fuzzer,address -I$(LIBPG_QUERY_PATH)
16+
FUZZ_LDFLAGS = -fsanitize=fuzzer,address -lpthread
17+
FUZZ_SRCS = fuzz/fuzz_parse_protobuf.c \
18+
fuzz/fuzz_scan.c \
19+
fuzz/fuzz_deparse.c \
20+
fuzz/fuzz_roundtrip.c
21+
FUZZ_BINS = $(patsubst fuzz/%.c,fuzz/_build/%,$(FUZZ_SRCS))
22+
23+
.PHONY: all libpg_query_ex clean fuzz fuzz-corpus fuzz-clean patch update-libpg_query
1524

1625
all: priv/libpg_query_ex.so
1726

18-
priv:
19-
mkdir -p priv
27+
28+
fuzz/_build:
29+
mkdir -p fuzz/_build
2030

2131
$(LIBPG_QUERY_PATH)/libpg_query.a:
2232
$(MAKE) -B -C $(LIBPG_QUERY_PATH) libpg_query.a
2333

24-
priv/libpg_query_ex.so: priv $(LIBPG_QUERY_PATH)/libpg_query.a c_src/libpg_query_ex.c
34+
priv/libpg_query_ex.so: $(LIBPG_QUERY_PATH)/libpg_query.a c_src/libpg_query_ex.c
35+
mkdir -p priv
2536
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ c_src/libpg_query_ex.c $(LIBPG_QUERY_PATH)/libpg_query.a
2637

38+
# Build all fuzz targets (requires clang with libFuzzer)
39+
fuzz: fuzz/_build $(LIBPG_QUERY_PATH)/libpg_query.a $(FUZZ_BINS)
40+
@echo ""
41+
@echo "Fuzz targets built in fuzz/_build/. Next steps:"
42+
@echo " 1. Populate the deparse corpus: make fuzz-corpus"
43+
@echo " 2. Run a fuzzer, e.g.:"
44+
@echo " fuzz/_build/fuzz_parse_protobuf -max_len=65536 fuzz/corpus/parse/"
45+
@echo " fuzz/_build/fuzz_deparse -max_len=65536 fuzz/corpus/deparse/"
46+
47+
fuzz/_build/%: fuzz/%.c $(LIBPG_QUERY_PATH)/libpg_query.a
48+
$(FUZZ_CC) $(FUZZ_CFLAGS) -o $@ $< $(LIBPG_QUERY_PATH)/libpg_query.a $(FUZZ_LDFLAGS)
49+
50+
# Also build the corpus generator (not a fuzz target, no -fsanitize=fuzzer)
51+
fuzz/_build/gen_deparse_corpus: fuzz/gen_deparse_corpus.c $(LIBPG_QUERY_PATH)/libpg_query.a
52+
$(FUZZ_CC) -g -O1 -fsanitize=address -I$(LIBPG_QUERY_PATH) -o $@ $< \
53+
$(LIBPG_QUERY_PATH)/libpg_query.a -fsanitize=address -lpthread
54+
55+
# Generate binary protobuf seeds for fuzz_deparse from the SQL corpus
56+
fuzz-corpus: fuzz/_build/gen_deparse_corpus
57+
@mkdir -p fuzz/corpus/deparse
58+
fuzz/_build/gen_deparse_corpus fuzz/corpus/deparse \
59+
"SELECT 1" \
60+
"SELECT id, name FROM users WHERE active = true" \
61+
"SELECT u.id, o.total FROM users u JOIN orders o ON u.id = o.user_id" \
62+
"INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')" \
63+
"UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '90 days'" \
64+
"DELETE FROM sessions WHERE expires_at < NOW()" \
65+
"WITH recent AS (SELECT * FROM events WHERE created_at > NOW() - INTERVAL '1 hour') SELECT count(*) FROM recent" \
66+
"SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 100)" \
67+
"SELECT department, count(*), avg(salary) FROM employees GROUP BY department HAVING count(*) > 5" \
68+
"SELECT id, salary, rank() OVER (PARTITION BY department ORDER BY salary DESC) FROM employees" \
69+
"SELECT id::text, created_at::date, price::numeric(10,2) FROM products" \
70+
"SELECT CASE WHEN status = 1 THEN 'active' WHEN status = 2 THEN 'pending' ELSE 'unknown' END FROM orders" \
71+
"SELECT ARRAY[1,2,3], unnest(tags) FROM posts" \
72+
"SELECT data->>'name', data->'address'->>'city' FROM profiles WHERE data @> '{\"active\":true}'" \
73+
"SELECT id FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)" \
74+
"SELECT * FROM events WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'" \
75+
"SELECT * FROM users WHERE email ILIKE '%@example.com' AND name NOT LIKE 'test%'" \
76+
"SELECT * FROM users WHERE deleted_at IS NULL AND parent_id IS NOT NULL" \
77+
"SELECT * FROM users WHERE id = \$$1 AND status = \$$2" \
78+
"SELECT id FROM admins UNION ALL SELECT id FROM moderators EXCEPT SELECT id FROM banned_users"
79+
80+
fuzz-clean:
81+
$(RM) -r fuzz/_build fuzz/corpus/deparse fuzz/crashes
82+
2783
protobuf:
2884
MIX_ENV=prod mix protox.generate --output-path=lib/pg_query/proto --multiple-files c_src/libpg_query/protobuf/pg_query.proto
2985

@@ -32,6 +88,15 @@ clean:
3288
$(MAKE) -C $(LIBPG_QUERY_PATH) clean
3389
$(RM) priv/libpg_query_ex.so
3490

91+
# Apply all local patches to the vendored libpg_query source
92+
patch:
93+
@for p in patches/*.patch; do \
94+
echo "Applying $$p ..."; \
95+
git apply "$$p" || { echo "FAILED: $$p"; exit 1; }; \
96+
done
97+
@echo "All patches applied."
98+
3599
update-libpg_query:
36-
git subtree pull -P "c_src/libpg_query" --squash https://github.com/pganalyze/libpg_query.git 15-latest
100+
git subtree pull -P "c_src/libpg_query" --squash https://github.com/pganalyze/libpg_query.git 17-latest
101+
$(MAKE) patch
37102

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,46 @@ def deps do
3535
end
3636
```
3737

38+
## Fuzzing
39+
40+
The `fuzz/` directory contains [libFuzzer](https://llvm.org/docs/LibFuzzer.html) harnesses that exercise the NIF boundary. You need clang with libFuzzer support (standard in most LLVM distributions).
41+
42+
Build all four targets:
43+
44+
```bash
45+
make fuzz
46+
```
47+
48+
Optionally seed the deparse corpus from known-good SQL strings:
49+
50+
```bash
51+
make fuzz-corpus
52+
```
53+
54+
Then run a target, for example:
55+
56+
```bash
57+
# Fuzz the parse → deparse round-trip (highest-value target)
58+
fuzz/_build/fuzz_roundtrip -max_len=4096 -artifact_prefix=fuzz/crashes/ fuzz/corpus/parse/
59+
60+
# Fuzz raw protobuf bytes fed directly into the deparser
61+
fuzz/_build/fuzz_deparse -max_len=65536 -artifact_prefix=fuzz/crashes/ fuzz/corpus/deparse/
62+
63+
# Fuzz the SQL parser
64+
fuzz/_build/fuzz_parse_protobuf -max_len=4096 -artifact_prefix=fuzz/crashes/ fuzz/corpus/parse/
65+
66+
# Fuzz the SQL scanner
67+
fuzz/_build/fuzz_scan -max_len=4096 -artifact_prefix=fuzz/crashes/ fuzz/corpus/parse/
68+
```
69+
70+
Crash artifacts are written to `fuzz/crashes/` (the `-artifact_prefix` flag controls this; without it libFuzzer writes to the current directory). Replay a crash by passing the file as a positional argument:
71+
72+
```bash
73+
fuzz/_build/fuzz_roundtrip fuzz/crashes/<file>
74+
```
75+
76+
Clean up build artefacts and generated corpus with `make fuzz-clean`.
77+
3878
## License
3979

4080
This Elixir interface is distributed under the terms of the [Apache 2.0 license](./LICENSE).

c_src/libpg_query/.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
*.sql binary
1+
*.sql binary
2+
*.psql binary

c_src/libpg_query/.github/workflows/ci.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11-
os: [ubuntu-20.04]
11+
os: [ubuntu-24.04]
1212
compiler: [clang, gcc]
1313
protobuf_lib: [protobuf-c, protobuf-cpp]
1414
valgrind: [valgrind,no-valgrind]
15+
exclude:
16+
# this combination hits linking errors: see https://github.com/pganalyze/libpg_query/pull/289
17+
- compiler: clang
18+
protobuf_lib: protobuf-cpp
19+
valgrind: valgrind
1520
steps:
1621
- name: Check out code
1722
uses: actions/checkout@v4
@@ -21,7 +26,7 @@ jobs:
2126
uses: actions/cache@v4
2227
with:
2328
path: protobuf-25.1
24-
key: ${{ runner.os }}-protobuf-25.1
29+
key: ${{ runner.os }}-${{ matrix.compiler }}-protobuf-25.1
2530
- name: Build protobuf library
2631
if: matrix.protobuf_lib == 'protobuf-cpp' && steps.cache-protobuf.outputs.cache-hit != 'true'
2732
run: |

c_src/libpg_query/CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,50 @@
22

33
All versions are tagged by the major Postgres version, plus an individual semver for this library itself.
44

5+
## 17-6.2.2 2026-01-26
6+
7+
* pg_query_normalize: Fix handling of special strings in DefElem [#325](https://github.com/pganalyze/libpg_query/pull/325)
8+
- This avoids a crash when running the normalize function on certain utility statements
9+
* pg_query_deparse_comments_for_query: Add missing initialization [#324](https://github.com/pganalyze/libpg_query/pull/324)
10+
- This avoids a crash for callers that read the error field of the result when there is no error
11+
12+
## 17-6.2.1 2026-01-14
13+
14+
* Add pg_query_is_utility_stmt function to determine if query text contains utility statements [#313](https://github.com/pganalyze/libpg_query/pull/313)
15+
* This is a fast check for callers that don't actually need the parse tree itself
16+
* Add missing top-level postgres_deparse.h in Makefile install step
17+
- This was an oversight from the previous 6.2.0 release
18+
* Improve pg_query_summary function:
19+
- Speed up summary truncate replacement logic
20+
- Correctly handle `GRANT .. ON ALL TABLES IN SCHEMA` statements
21+
- Correctly handle schema qualified filter columns
22+
23+
## 17-6.2.0 2025-12-10
24+
25+
* Add fast summary information function (pg_query_summary)
26+
- This allows gathering certain information, for example which tables are referenced in a
27+
statement, without requiring a Protobuf serialization step in a higher level library
28+
- Additionally this can also be used to perform "smart truncation" of a query by
29+
omitting deeply nested information (e.g. a CTE definition, or a target list) whilst
30+
preserving more essential parts like the FROM claus
31+
* Deparser:
32+
- Introduce pretty printing / formatting
33+
- Introduces a new optional pretty print mode that emits a human readable
34+
output. A detailed explanation of the mechanism can be found at the start
35+
of the deparser file.
36+
- Rework handling of expressions inside typecasts
37+
- Prefer (..)::type syntax, unless we are already in a function call.
38+
- Use lowercase keywords in xmlroot functions
39+
- This matches other XML functions as well as the Postgres documentation,
40+
since these are closer to function argument names than regular keywords.
41+
- Fix deparse of ALTER TABLE a ALTER b SET STATISTICS DEFAULT
42+
- Fix the null pointer dereference when handling identity columns
43+
* Allow alternate definitions of NAMEDATALEN identifier limit
44+
- This allows building libpg_query with an override of the built-time limit of
45+
Postgres identifiers (typically 63 characters)
46+
* Normalization: Add support for CALL statements
47+
* Bump Postgres to 17.7 and switch back to release tarballs
48+
549
## 17-6.1.0 2025-04-02
650

751
* Update to Postgres 17.4, and add recent patches scheduled for Postgres 17.5 (not yet released)

c_src/libpg_query/Makefile

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ PGDIR = $(root_dir)/tmp/postgres
77
PGDIRBZ2 = $(root_dir)/tmp/postgres.tar.bz2
88
PGDIRZIP = $(root_dir)/tmp/postgres.zip
99

10-
PG_VERSION = 17.4
10+
PG_VERSION = 17.7
1111
PG_VERSION_MAJOR = $(call word-dot,$(PG_VERSION),1)
12-
PG_VERSION_NUM = 170004
13-
PG_BRANCH = REL_17_STABLE
12+
PG_VERSION_NUM = 170007
1413
PROTOC_VERSION = 25.1
1514

16-
VERSION = 6.1.0
15+
VERSION = 6.2.2
1716
VERSION_MAJOR = $(call word-dot,$(VERSION),1)
1817
VERSION_MINOR = $(call word-dot,$(VERSION),2)
1918
VERSION_PATCH = $(call word-dot,$(VERSION),3)
@@ -39,6 +38,7 @@ override CFLAGS += -g -I. -I./vendor -I./src/include -I./src/postgres/include -W
3938

4039
ifeq ($(OS),Windows_NT)
4140
override CFLAGS += -I./src/postgres/include/port/win32
41+
override TEST_CFLAGS += -I./src/postgres/include/port/win32
4242
endif
4343

4444
override PG_CONFIGURE_FLAGS += -q --without-readline --without-zlib --without-icu
@@ -116,14 +116,9 @@ clean:
116116
.PHONY: all clean build build_shared extract_source examples test install
117117

118118
$(PGDIR):
119-
# We temporarily build off REL_17_STABLE to pull in https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=6da2ba1d8a031984eb016fed6741bb2ac945f19d
120-
# TODO: Go back to upstream tarball once 17.5 is released
121-
# tar -xjf $(PGDIRBZ2)
122-
# curl -o $(PGDIRBZ2) https://ftp.postgresql.org/pub/source/v$(PG_VERSION)/postgresql-$(PG_VERSION).tar.bz2
123-
# mv $(root_dir)/postgresql-$(PG_VERSION) $(PGDIR)
124-
curl -L -o $(PGDIRZIP) https://github.com/postgres/postgres/archive/refs/heads/$(PG_BRANCH).zip
125-
unzip $(PGDIRZIP)
126-
mv $(root_dir)/postgres-$(PG_BRANCH) $(PGDIR)
119+
curl -o $(PGDIRBZ2) https://ftp.postgresql.org/pub/source/v$(PG_VERSION)/postgresql-$(PG_VERSION).tar.bz2
120+
tar -xjf $(PGDIRBZ2)
121+
mv $(root_dir)/postgresql-$(PG_VERSION) $(PGDIR)
127122
cd $(PGDIR); patch -p1 < $(root_dir)/patches/01_parser_additional_param_ref_support.patch
128123
cd $(PGDIR); patch -p1 < $(root_dir)/patches/03_lexer_track_yyllocend.patch
129124
cd $(PGDIR); patch -p1 < $(root_dir)/patches/04_lexer_comments_as_tokens.patch
@@ -133,6 +128,7 @@ $(PGDIR):
133128
cd $(PGDIR); patch -p1 < $(root_dir)/patches/08_avoid_zero_length_delimiter_in_regression_tests.patch
134129
cd $(PGDIR); patch -p1 < $(root_dir)/patches/09_allow_param_junk.patch
135130
cd $(PGDIR); patch -p1 < $(root_dir)/patches/10_avoid_namespace_hashtab_impl_gen.patch
131+
cd $(PGDIR); patch -p1 < $(root_dir)/patches/11_ifndef_namedatalen.patch
136132
cd $(PGDIR); ./configure $(PG_CONFIGURE_FLAGS)
137133
cd $(PGDIR); make -C src/pl/plpgsql/src pl_gram.h plerrcodes.h pl_reserved_kwlist_d.h pl_unreserved_kwlist_d.h
138134
cd $(PGDIR); make -C src/port pg_config_paths.h
@@ -241,14 +237,15 @@ examples/normalize_error: examples/normalize_error.c $(ARLIB)
241237
examples/simple_plpgsql: examples/simple_plpgsql.c $(ARLIB)
242238
$(CC) $(TEST_CFLAGS) -o $@ -g examples/simple_plpgsql.c $(ARLIB) $(TEST_LDFLAGS)
243239

244-
TESTS = test/complex test/concurrency test/deparse test/fingerprint test/fingerprint_opts test/normalize test/normalize_utility test/parse test/parse_opts test/parse_protobuf test/parse_protobuf_opts test/parse_plpgsql test/scan test/split
240+
TESTS = test/complex test/concurrency test/deparse test/fingerprint test/fingerprint_opts test/is_utility_stmt test/normalize test/normalize_utility test/parse test/parse_opts test/parse_protobuf test/parse_protobuf_opts test/parse_plpgsql test/scan test/split test/summary test/summary_truncate
245241
test: $(TESTS)
246242
ifeq ($(VALGRIND),1)
247243
$(VALGRIND_MEMCHECK) test/complex || (cat test/valgrind.log && false)
248244
$(VALGRIND_MEMCHECK) test/concurrency || (cat test/valgrind.log && false)
249245
$(VALGRIND_MEMCHECK) test/deparse || (cat test/valgrind.log && false)
250246
$(VALGRIND_MEMCHECK) test/fingerprint || (cat test/valgrind.log && false)
251247
$(VALGRIND_MEMCHECK) test/fingerprint_opts || (cat test/valgrind.log && false)
248+
$(VALGRIND_MEMCHECK) test/is_utility_stmt || (cat test/valgrind.log && false)
252249
$(VALGRIND_MEMCHECK) test/normalize || (cat test/valgrind.log && false)
253250
$(VALGRIND_MEMCHECK) test/normalize_utility || (cat test/valgrind.log && false)
254251
$(VALGRIND_MEMCHECK) test/parse || (cat test/valgrind.log && false)
@@ -257,6 +254,8 @@ ifeq ($(VALGRIND),1)
257254
$(VALGRIND_MEMCHECK) test/parse_protobuf_opts || (cat test/valgrind.log && false)
258255
$(VALGRIND_MEMCHECK) test/scan || (cat test/valgrind.log && false)
259256
$(VALGRIND_MEMCHECK) test/split || (cat test/valgrind.log && false)
257+
$(VALGRIND_MEMCHECK) test/summary || (cat test/valgrind.log && false)
258+
$(VALGRIND_MEMCHECK) test/summary_truncate || (cat test/valgrind.log && false)
260259
# Output-based tests
261260
$(VALGRIND_MEMCHECK) test/parse_plpgsql || (cat test/valgrind.log && false)
262261
diff -Naur test/plpgsql_samples.expected.json test/plpgsql_samples.actual.json
@@ -266,6 +265,7 @@ else
266265
test/deparse
267266
test/fingerprint
268267
test/fingerprint_opts
268+
test/is_utility_stmt
269269
test/normalize
270270
test/normalize_utility
271271
test/parse
@@ -274,6 +274,8 @@ else
274274
test/parse_protobuf_opts
275275
test/scan
276276
test/split
277+
test/summary
278+
test/summary_truncate
277279
# Output-based tests
278280
test/parse_plpgsql
279281
diff -Naur test/plpgsql_samples.expected.json test/plpgsql_samples.actual.json
@@ -297,6 +299,10 @@ test/fingerprint_opts: test/fingerprint_opts.c test/fingerprint_opts_tests.c $(A
297299
# We have "-Isrc/" because this test uses pg_query_fingerprint_with_opts
298300
$(CC) $(TEST_CFLAGS) -o $@ -Isrc/ test/fingerprint_opts.c $(ARLIB) $(TEST_LDFLAGS)
299301

302+
test/is_utility_stmt: test/framework/main.c test/is_utility_stmt.c $(ARLIB)
303+
# We have "-Isrc/postgres/include" because this test uses pg_query_summary_direct
304+
$(CC) $(TEST_CFLAGS) -o $@ -Isrc/postgres/include test/framework/main.c test/is_utility_stmt.c $(ARLIB) $(TEST_LDFLAGS)
305+
300306
test/normalize: test/normalize.c test/normalize_tests.c $(ARLIB)
301307
$(CC) $(TEST_CFLAGS) -o $@ test/normalize.c $(ARLIB) $(TEST_LDFLAGS)
302308

@@ -306,6 +312,14 @@ test/normalize_utility: test/normalize_utility.c test/normalize_utility_tests.c
306312
test/parse: test/parse.c test/parse_tests.c $(ARLIB)
307313
$(CC) $(TEST_CFLAGS) -o $@ test/parse.c $(ARLIB) $(TEST_LDFLAGS)
308314

315+
test/summary: test/framework/main.c test/summary.c test/summary_tests.c test/summary_tests_list.c $(ARLIB)
316+
# We have "-Isrc/postgres/include" because this test uses pg_query_summary_direct
317+
$(CC) $(TEST_CFLAGS) -o $@ -Isrc/postgres/include test/framework/main.c test/summary.c $(ARLIB) $(TEST_LDFLAGS)
318+
319+
test/summary_truncate: test/framework/main.c test/summary_truncate.c $(ARLIB)
320+
# We have "-Isrc/postgres/include" because this test uses pg_query_summary_direct
321+
$(CC) $(TEST_CFLAGS) -o $@ -Isrc/postgres/include test/framework/main.c test/summary_truncate.c $(ARLIB) $(TEST_LDFLAGS)
322+
309323
test/parse_opts: test/parse_opts.c test/parse_opts_tests.c $(ARLIB)
310324
$(CC) $(TEST_CFLAGS) -o $@ test/parse_opts.c $(ARLIB) $(TEST_LDFLAGS)
311325

@@ -336,4 +350,5 @@ install: $(ARLIB) $(SOLIB)
336350
$(LN_S) $(SOLIBVER) "$(DESTDIR)"$(libdir)/$(SOLIB)
337351
$(INSTALL) -d "$(DESTDIR)"$(includedir)/$(TARGET)
338352
$(INSTALL) -m 644 pg_query.h "$(DESTDIR)"$(includedir)/pg_query.h
353+
$(INSTALL) -m 644 postgres_deparse.h "$(DESTDIR)"$(includedir)/postgres_deparse.h
339354
$(INSTALL) -m 644 protobuf/pg_query.proto "$(DESTDIR)"$(includedir)/$(TARGET)/pg_query.proto

0 commit comments

Comments
 (0)