• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

examples/H28-Dec-2020-13195

patches/H28-Dec-2020-398378

scripts/H28-Dec-2020-1,196940

src/H28-Dec-2020-185,895127,252

srcdata/H28-Dec-2020-12,34712,346

test/H28-Dec-2020-11,18210,920

testdata/H28-Dec-2020-350349

tmp/H07-May-2022-

.gitignoreH A D28-Dec-2020136 1712

.travis.ymlH A D28-Dec-202053 65

CHANGELOG.mdH A D28-Dec-20204.4 KiB14382

LICENSEH A D28-Dec-20201.5 KiB2923

MakefileH A D03-May-20225.1 KiB139103

README.mdH A D28-Dec-20205.6 KiB180117

pg_query.hH A D28-Dec-20201.6 KiB6447

README.md

1# libpg_query [![Build Status](https://travis-ci.org/lfittl/libpg_query.svg?branch=master)](https://travis-ci.org/lfittl/libpg_query)
2
3C library for accessing the PostgreSQL parser outside of the server.
4
5This library uses the actual PostgreSQL server source to parse SQL queries and return the internal PostgreSQL parse tree.
6
7Note that this is mostly intended as a base library for [pg_query](https://github.com/lfittl/pg_query) (Ruby), [pg_query.go](https://github.com/lfittl/pg_query.go) (Go), [pg-query-parser](https://github.com/zhm/pg-query-parser) (Node), [psqlparse](https://github.com/alculquicondor/psqlparse) (Python) and [pglast](https://pypi.org/project/pglast/) (Python 3).
8
9You can find further background to why a query's parse tree is useful here: https://pganalyze.com/blog/parse-postgresql-queries-in-ruby.html
10
11
12## Installation
13
14```sh
15git clone -b 10-latest git://github.com/lfittl/libpg_query
16cd libpg_query
17make
18```
19
20Due to compiling parts of PostgreSQL, running `make` will take a bit. Expect up to 3 minutes.
21
22For a production build, its best to use a specific git tag (see CHANGELOG).
23
24
25## Usage: Parsing a query
26
27A [full example](https://github.com/lfittl/libpg_query/blob/master/examples/simple.c) that parses a query looks like this:
28
29```c
30#include <pg_query.h>
31#include <stdio.h>
32
33int main() {
34  PgQueryParseResult result;
35
36  result = pg_query_parse("SELECT 1");
37
38  printf("%s\n", result.parse_tree);
39
40  pg_query_free_parse_result(result);
41}
42```
43
44Compile it like this:
45
46```
47cc -Ilibpg_query -Llibpg_query example.c -lpg_query
48```
49
50This will output:
51
52```json
53[{"SelectStmt": {"targetList": [{"ResTarget": {"val": {"A_Const": {"val": {"Integer": {"ival": 1}}, "location": 7}}, "location": 7}}], "op": 0}}]
54```
55
56
57## Usage: Fingerprinting a query
58
59Fingerprinting allows you to identify similar queries that are different only because
60of the specific object that is being queried for (i.e. different object ids in the WHERE clause),
61or because of formatting.
62
63Example:
64
65```c
66#include <pg_query.h>
67#include <stdio.h>
68
69int main() {
70  PgQueryFingerprintResult result;
71
72  result = pg_query_fingerprint("SELECT 1");
73
74  printf("%s\n", result.hexdigest);
75
76  pg_query_free_fingerprint_result(result);
77}
78```
79
80This will output:
81
82```
838e1acac181c6d28f4a923392cf1c4eda49ee4cd2
84```
85
86See https://github.com/lfittl/libpg_query/wiki/Fingerprinting for the full fingerprinting rules.
87
88## Usage: Parsing a PL/pgSQL function (Experimental)
89
90A [full example](https://github.com/lfittl/libpg_query/blob/master/examples/simple_plpgsql.c) that parses a [PL/pgSQL](https://www.postgresql.org/docs/current/static/plpgsql.html) method looks like this:
91
92```c
93#include <pg_query.h>
94#include <stdio.h>
95#include <stdlib.h>
96
97int main() {
98  PgQueryPlpgsqlParseResult result;
99
100  result = pg_query_parse_plpgsql(" \
101  CREATE OR REPLACE FUNCTION cs_fmt_browser_version(v_name varchar, \
102                                                  v_version varchar) \
103RETURNS varchar AS $$ \
104BEGIN \
105    IF v_version IS NULL THEN \
106        RETURN v_name; \
107    END IF; \
108    RETURN v_name || '/' || v_version; \
109END; \
110$$ LANGUAGE plpgsql;");
111
112  if (result.error) {
113    printf("error: %s at %d\n", result.error->message, result.error->cursorpos);
114  } else {
115    printf("%s\n", result.plpgsql_funcs);
116  }
117
118  pg_query_free_plpgsql_parse_result(result);
119
120  return 0;
121}
122```
123
124This will output:
125
126```json
127[
128{"PLpgSQL_function": {"datums": [{"PLpgSQL_var": {"refname": "found", "datatype": {"PLpgSQL_type": {"typname": "UNKNOWN"}}}}], "action": {"PLpgSQL_stmt_block": {"lineno": 1, "body": [{"PLpgSQL_stmt_if": {"lineno": 1, "cond": {"PLpgSQL_expr": {"query": "SELECT v_version IS NULL"}}, "then_body": [{"PLpgSQL_stmt_return": {"lineno": 1, "expr": {"PLpgSQL_expr": {"query": "SELECT v_name"}}}}]}}, {"PLpgSQL_stmt_return": {"lineno": 1, "expr": {"PLpgSQL_expr": {"query": "SELECT v_name || '/' || v_version"}}}}]}}}}
129]
130```
131
132## Versions
133
134For stability, it is recommended you use individual tagged git versions, see CHANGELOG.
135
136`master` reflects a PostgreSQL base version of 9.4, with a legacy output format.
137
138New development is happening on `10-latest`, which reflects a base version of Postgres 10.
139
140
141## Resources
142
143pg_query wrappers in other languages:
144
145* Ruby: [pg_query](https://github.com/lfittl/pg_query)
146* Go: [pg_query_go](https://github.com/lfittl/pg_query_go)
147* Javascript (Node): [pg-query-parser](https://github.com/zhm/pg-query-parser)
148* Javascript (Browser): [pg-query-emscripten](https://github.com/lfittl/pg-query-emscripten)
149* Python: [psqlparse](https://github.com/alculquicondor/psqlparse), [pglast](https://github.com/lelit/pglast)
150* OCaml: [pg_query-ocaml](https://github.com/roddyyaga/pg_query-ocaml)
151
152Products, tools and libraries built on pg_query:
153
154* [pganalyze](https://pganalyze.com/)
155* [hsql](https://github.com/JackDanger/hsql)
156* [sqlint](https://github.com/purcell/sqlint)
157* [pghero](https://github.com/ankane/pghero)
158* [dexter](https://github.com/ankane/dexter)
159* [pgscope](https://github.com/gjalves/pgscope)
160* [pg_materialize](https://github.com/aanari/pg-materialize)
161* [DuckDB](https://github.com/cwida/duckdb) ([details](https://github.com/cwida/duckdb/tree/master/third_party/libpg_query))
162
163
164Please feel free to [open a PR](https://github.com/lfittl/libpg_query/pull/new/master) to add yours! :)
165
166
167## Authors
168
169- [Lukas Fittl](mailto:lukas@fittl.com)
170
171
172## License
173
174PostgreSQL server source code, used under the [PostgreSQL license](https://www.postgresql.org/about/licence/).<br>
175Portions Copyright (c) 1996-2017, The PostgreSQL Global Development Group<br>
176Portions Copyright (c) 1994, The Regents of the University of California
177
178All other parts are licensed under the 3-clause BSD license, see LICENSE file for details.<br>
179Copyright (c) 2017, Lukas Fittl <lukas@fittl.com>
180