PgQueryFingerprintResult pg_query_fingerprint_with_opts()

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;
}