in src/pg_query_fingerprint.c [241:301]
PgQueryFingerprintResult pg_query_fingerprint_with_opts(const char* input, bool printTokens)
{
MemoryContext ctx = NULL;
PgQueryInternalParsetreeAndError parsetree_and_error;
PgQueryFingerprintResult result = {0};
ctx = pg_query_enter_memory_context("pg_query_fingerprint");
parsetree_and_error = pg_query_raw_parse(input);
// These are all malloc-ed and will survive exiting the memory context, the caller is responsible to free them now
result.stderr_buffer = parsetree_and_error.stderr_buffer;
result.error = parsetree_and_error.error;
if (parsetree_and_error.tree != NULL || result.error == NULL) {
FingerprintContext ctx;
int i;
uint8 sha1result[SHA1_RESULTLEN];
ctx.sha1 = palloc0(sizeof(SHA1_CTX));
SHA1Init(ctx.sha1);
if (parsetree_and_error.tree != NULL) {
_fingerprintNode(&ctx, parsetree_and_error.tree, NULL, NULL, 0);
}
SHA1Final(sha1result, ctx.sha1);
// This is intentionally malloc-ed and will survive exiting the memory context
result.hexdigest = calloc((1 + SHA1_RESULTLEN) * 2 + 1, sizeof(char));
sprintf(result.hexdigest, "%02x", PG_QUERY_FINGERPRINT_VERSION);
for (i = 0; i < SHA1_RESULTLEN; i++) {
sprintf(result.hexdigest + (1 + i) * 2, "%02x", sha1result[i]);
}
if (printTokens) {
FingerprintContext debugCtx;
dlist_iter iter;
_fingerprintInitForTokens(&debugCtx);
_fingerprintNode(&debugCtx, parsetree_and_error.tree, NULL, NULL, 0);
printf("[");
dlist_foreach(iter, &debugCtx.tokens)
{
FingerprintToken *token = dlist_container(FingerprintToken, list_node, iter.cur);
printf("%s, ", token->str);
}
printf("]\n");
}
}
pg_query_exit_memory_context(ctx);
return result;
}