PgQueryParseResult pg_query_parse(const char* input) { MemoryContext ctx = NULL; PgQueryInternalParsetreeAndError parsetree_and_error; PgQueryParseResult result = {0}; ctx = pg_query_enter_memory_context("pg_query_parse"); 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) { char *tree_json; tree_json = pg_query_nodes_to_json(parsetree_and_error.tree); result.parse_tree = strdup(tree_json); pfree(tree_json); } else { result.parse_tree = strdup("[]"); } pg_query_exit_memory_context(ctx); return result; }
PgQueryNormalizeResult pg_query_normalize(const char* input) { MemoryContext ctx = NULL; PgQueryNormalizeResult result = {0}; ctx = pg_query_enter_memory_context("pg_query_normalize"); PG_TRY(); { List *tree; pgssConstLocations jstate; int query_len; /* Parse query */ tree = raw_parser(input); /* Set up workspace for constant recording */ jstate.clocations_buf_size = 32; jstate.clocations = (pgssLocationLen *) palloc(jstate.clocations_buf_size * sizeof(pgssLocationLen)); jstate.clocations_count = 0; jstate.highest_extern_param_id = 0; /* Walk tree and record const locations */ const_record_walker((Node *) tree, &jstate); /* Normalize query */ query_len = (int) strlen(input); result.normalized_query = strdup(generate_normalized_query(&jstate, input, 0, &query_len, PG_UTF8)); } PG_CATCH(); { ErrorData* error_data; PgQueryError* error; MemoryContextSwitchTo(ctx); error_data = CopyErrorData(); error = malloc(sizeof(PgQueryError)); error->message = strdup(error_data->message); error->filename = strdup(error_data->filename); error->lineno = error_data->lineno; error->cursorpos = error_data->cursorpos; result.error = error; FlushErrorState(); } PG_END_TRY(); pg_query_exit_memory_context(ctx); return result; }