static bool const_record_walker(Node *node, pgssConstLocations *jstate) { bool result; if (node == NULL) return false; if ((IsA(node, A_Const) && ((A_Const *) node)->location >= 0) || (IsA(node, DefElem) && ((DefElem *) node)->location >= 0)) { /* enlarge array if needed */ if (jstate->clocations_count >= jstate->clocations_buf_size) { jstate->clocations_buf_size *= 2; jstate->clocations = (pgssLocationLen *) repalloc(jstate->clocations, jstate->clocations_buf_size * sizeof(pgssLocationLen)); } jstate->clocations[jstate->clocations_count].location = IsA(node, DefElem) ? ((DefElem *) node)->location : ((A_Const *) node)->location; /* initialize lengths to -1 to simplify fill_in_constant_lengths */ jstate->clocations[jstate->clocations_count].length = -1; jstate->clocations_count++; } else if (IsA(node, VariableSetStmt)) { return const_record_walker((Node *) ((VariableSetStmt *) node)->args, jstate); } else if (IsA(node, CopyStmt)) { return const_record_walker((Node *) ((CopyStmt *) node)->query, jstate); } else if (IsA(node, ExplainStmt)) { return const_record_walker((Node *) ((ExplainStmt *) node)->query, jstate); } else if (IsA(node, AlterRoleStmt)) { return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate); } PG_TRY(); { result = raw_expression_tree_walker(node, const_record_walker, (void*) jstate); } PG_CATCH(); { FlushErrorState(); result = false; } PG_END_TRY(); return result; }
static bool const_record_walker(Node *node, pgssConstLocations *jstate) { bool result; if (node == NULL) return false; if (IsA(node, A_Const)) { RecordConstLocation(jstate, castNode(A_Const, node)->location); } else if (IsA(node, ParamRef)) { /* Track the highest ParamRef number */ if (((ParamRef *) node)->number > jstate->highest_extern_param_id) jstate->highest_extern_param_id = castNode(ParamRef, node)->number; } else if (IsA(node, DefElem)) { return const_record_walker((Node *) ((DefElem *) node)->arg, jstate); } else if (IsA(node, RawStmt)) { return const_record_walker((Node *) ((RawStmt *) node)->stmt, jstate); } else if (IsA(node, VariableSetStmt)) { return const_record_walker((Node *) ((VariableSetStmt *) node)->args, jstate); } else if (IsA(node, CopyStmt)) { return const_record_walker((Node *) ((CopyStmt *) node)->query, jstate); } else if (IsA(node, ExplainStmt)) { return const_record_walker((Node *) ((ExplainStmt *) node)->query, jstate); } else if (IsA(node, AlterRoleStmt)) { return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate); } else if (IsA(node, DeclareCursorStmt)) { return const_record_walker((Node *) ((DeclareCursorStmt *) node)->query, jstate); } PG_TRY(); { result = raw_expression_tree_walker(node, const_record_walker, (void*) jstate); } PG_CATCH(); { FlushErrorState(); result = false; } PG_END_TRY(); 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; }