This introduces a reimplementation of normalize using our primitives
instead of the implementation in libpg_query. In addition to reducing
our reliance on that library, this implementation takes advantage of the
fact that for our use case we will already have a parsed AST to pass in.
libpg_query takes a string, parses it, records the location of any
constants, then copies and manipulates that string to replace the
constants.
In contrast, this implementation just copies the AST, walks it, replaces
any constants with parameters, and changes the numbers on any parameters
it encounters. In an effort to do this change in a single iteration over
the parse tree, we don't preserve any bind parameters that were in the
original query, which you can see reflected in the test that was
updated.
On an extremely large query, the new implementation is 4.5x faster. If
you include deparse time it is about twice as fast, and including parse
+ deparse time it is roughly 10% slower. While it isn't ideal that the
full parse + normalize + deparse flow is slightly slower, in pgdog we'd
only be using the normalize + deparse flow, so this results in a
significant performance win as well as a reduction in unsafe code.
This introduces a reimplementation of normalize using our primitives instead of the implementation in libpg_query. In addition to reducing our reliance on that library, this implementation takes advantage of the fact that for our use case we will already have a parsed AST to pass in.
libpg_query takes a string, parses it, records the location of any constants, then copies and manipulates that string to replace the constants.
In contrast, this implementation just copies the AST, walks it, replaces any constants with parameters, and changes the numbers on any parameters it encounters. In an effort to do this change in a single iteration over the parse tree, we don't preserve any bind parameters that were in the original query, which you can see reflected in the test that was updated.
On an extremely large query, the new implementation is 4.5x faster. If you include deparse time it is about twice as fast, and including parse