OSPP 2024: Improve pg_get_functiondef#684
Conversation
WalkthroughThe recent changes introduce the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant PostgreSQL
participant pg_get_functiondef
User->>PostgreSQL: Call pg_get_functiondef()
PostgreSQL->>pg_get_functiondef: Retrieve function definition
pg_get_functiondef-->>PostgreSQL: Return function definition
PostgreSQL-->>User: Display function definition
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
Outside diff range, codebase verification and nitpick comments (3)
contrib/pg_get_functiondef/pg_get_functiondef_extend.c (1)
34-63: Correct Typo in Function Name and Comments.The function name
DescibleFunctionByNameshould be corrected toDescribeFunctionByName. Similarly, update comments to reflect the correct spelling.- char *DescibleFunctionByName(char *function_name); - char *DescibleFunctionByName(char *function_name) + char *DescribeFunctionByName(char *function_name); + char *DescribeFunctionByName(char *function_name)contrib/pg_get_functiondef/pg_get_functiondef_mul.c (2)
1-4: Improve header comments for clarity.The header comments could be more descriptive to better explain the purpose and functionality of the file.
/* pg_get_functiondef_mul.c - The achieve of pg_get_functiondef(oid, oid, ...) + Implementation of pg_get_functiondef_mul to retrieve function definitions for multiple OIDs. */
61-68: Potential Memory Leak in OID HandlingThe code in
pg_get_functiondef_mul.cdoes not appear to handle memory deallocation forinfo->oidsin all error cases. Whilepfree(info->oids)is called when the cursor exceeds the count, it is not clear if this is handled in case of errors elsewhere in the function. Consider adding explicit memory cleanup forinfo->oidsin all error paths to prevent memory leaks.
- Ensure
info->oidsis freed in all error scenarios, especially before anyereport(ERROR, ...)calls.Analysis chain
Check for potential memory leaks in OID handling.
Ensure that the memory allocated for
oidsis properly freed in case of an error before the function exits.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for memory leaks related to OID handling in the function. # Test: Ensure that memory allocated for OIDs is freed in case of errors. rg --type c -A 5 'pfree(info->oids)'Length of output: 38
Script:
#!/bin/bash # Find the function containing the specified code snippet to check for memory management practices. ast-grep --lang c --pattern $'{ /* Get user input, store to oids[] */ deconstruct_array_builtin((ArrayType *)oids_array, OIDOID, &oids, NULL, &count); info->oids = palloc((count + 1) * sizeof(Oid)); info->oids[0] = PG_GETARG_OID(0); for (int i = 1; i <= count; i++) { info->oids[i] = DatumGetObjectId(oids[i - 1]); } }' -A 20Length of output: 344
Script:
#!/bin/bash # Search for the function using deconstruct_array_builtin to identify the function handling OIDs. rg --type c -A 20 'deconstruct_array_builtin'Length of output: 78445
Script:
#!/bin/bash # Search for memory context management functions in pg_get_functiondef_mul.c to check for cleanup mechanisms. rg --type c 'MemoryContext|pfree|reset' contrib/pg_get_functiondef/pg_get_functiondef_mul.c -A 10 -B 10Length of output: 1320
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
contrib/pg_get_functiondef/expected/pg_get_functiondef.outis excluded by!**/*.out
Files selected for processing (8)
- contrib/Makefile (1 hunks)
- contrib/pg_get_functiondef/Makefile (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef--1.0.sql (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef.control (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef_no_input.c (1 hunks)
- contrib/pg_get_functiondef/sql/pg_get_functiondef.sql (1 hunks)
Files skipped from review due to trivial changes (1)
- contrib/pg_get_functiondef/pg_get_functiondef.control
Additional comments not posted (8)
contrib/pg_get_functiondef/sql/pg_get_functiondef.sql (1)
1-12: SQL commands are well-structured.The SQL commands effectively test the new functionality of handling multiple OIDs and function names. They cover various scenarios, ensuring robustness.
contrib/pg_get_functiondef/pg_get_functiondef--1.0.sql (1)
3-13: SQL function definitions are correctly implemented.The SQL functions are well-defined to interface with their respective C implementations, allowing for flexible input handling.
contrib/pg_get_functiondef/pg_get_functiondef_no_input.c (1)
13-24: C function implementation is correct.The function correctly handles the case where no arguments are provided, using
ereportto generate a detailed error message.contrib/pg_get_functiondef/Makefile (1)
1-26: Makefile Setup Looks Good.The Makefile is well-structured and follows standard practices for PostgreSQL extensions. It includes necessary variables and conditional PGXS logic for building the
pg_get_functiondefmodule.contrib/pg_get_functiondef/pg_get_functiondef_mul.c (3)
17-28: Struct and function declaration are well-defined.The
FunctionInfoDatastruct and thePG_FUNCTION_INFO_V1macro are correctly used for storing function information and declaring the PostgreSQL function.
93-97: Cleanup logic is well-implemented.The function correctly frees allocated resources and handles the end of the result set.
101-123: Verify memory management during tuple construction.Ensure that all allocated memory for
tuple_valuesand its elements is properly freed to prevent memory leaks.contrib/Makefile (1)
36-36: Addition ofpg_get_functiondefto build process.The
pg_get_functiondefdirectory has been successfully added to theSUBDIRSlist, indicating its inclusion in the build process. Ensure that the directory contains the necessary files for successful compilation and integration.
| if (SPI_OK_CONNECT != SPI_connect()) | ||
| { | ||
| ereport(ERROR, errmsg("SPI connect failed!")); | ||
| PG_RETURN_NULL(); | ||
| } |
There was a problem hiding this comment.
Ensure proper error handling for SPI connection.
The error handling for SPI_connect is minimal. Consider adding more context to the error message or handling specific error codes.
ereport(ERROR, (errmsg("SPI connect failed: %s", SPI_result_code_string(SPI_result))));| appendStringInfo(&query, "SELECT "); | ||
| appendStringInfo(&query, "pg_get_functiondef(%d)", info->oids[0]); | ||
| for (int i = 1; i < count; i++) | ||
| { | ||
| appendStringInfo(&query, ", pg_get_functiondef(%d)", info->oids[i]); | ||
| } | ||
| appendStringInfo(&query, ", pg_get_functiondef(%d);", info->oids[info->count - 1]); |
There was a problem hiding this comment.
Optimize query construction for readability.
The query construction could be simplified for better readability and maintainability.
appendStringInfo(&query, "SELECT pg_get_functiondef(%d)", info->oids[0]);
for (int i = 1; i < info->count; i++)
{
appendStringInfo(&query, ", pg_get_functiondef(%d)", info->oids[i]);
}
appendStringInfoChar(&query, ';');| Datum pg_get_functiondef_extend(PG_FUNCTION_ARGS) | ||
| { | ||
| FuncCallContext *funcctx = NULL; | ||
| FunctionInfo info = NULL; | ||
|
|
||
| if (SRF_IS_FIRSTCALL()) | ||
| { | ||
| ArrayType *arguments_raw; | ||
| int count_of_arguments; | ||
| Datum *arguments; | ||
| MemoryContext old_context; | ||
|
|
||
| funcctx = SRF_FIRSTCALL_INIT(); | ||
| old_context = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); | ||
|
|
||
| arguments_raw = PG_GETARG_ARRAYTYPE_P(0); | ||
| deconstruct_array_builtin((ArrayType *)arguments_raw, TEXTOID, &arguments, NULL, &count_of_arguments); | ||
|
|
||
| info = (FunctionInfo)palloc0(sizeof(struct FunctionInfoData)); | ||
| funcctx->user_fctx = info; | ||
|
|
||
| info->function_name = palloc0(count_of_arguments * sizeof(char *)); | ||
| for (int i = 0; i < count_of_arguments; i++) | ||
| { | ||
| info->function_name[i] = text_to_cstring((text *)arguments[i]); | ||
| } | ||
|
|
||
| info->cursor = 0; | ||
| info->count_of_arguments = count_of_arguments; | ||
|
|
||
| if (get_call_result_type(fcinfo, NULL, &info->result_desc) != TYPEFUNC_COMPOSITE) | ||
| { | ||
| ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record"))); | ||
| } | ||
| info->result_tuple_meta = TupleDescGetAttInMetadata(info->result_desc); | ||
| MemoryContextSwitchTo(old_context); | ||
| } | ||
|
|
||
| funcctx = SRF_PERCALL_SETUP(); | ||
| info = (FunctionInfo)(funcctx->user_fctx); | ||
|
|
||
| if (info->cursor == info->count_of_arguments) | ||
| { | ||
| SRF_RETURN_DONE(funcctx); | ||
| } | ||
| else | ||
| { | ||
| HeapTuple tuple; | ||
| Datum tuple_return; | ||
| char **values; | ||
| values = palloc0(sizeof(char *) * 2); | ||
| values[0] = pstrdup(info->function_name[info->cursor]); | ||
| values[1] = DescibleFunctionByName(info->function_name[info->cursor]); | ||
| info->cursor++; | ||
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, values); | ||
| tuple_return = HeapTupleGetDatum(tuple); | ||
| SRF_RETURN_NEXT(funcctx, tuple_return); | ||
| } | ||
| PG_RETURN_NULL(); |
There was a problem hiding this comment.
Correct Function Call to DescribeFunctionByName.
Update the call to the function within pg_get_functiondef_extend to use the corrected function name DescribeFunctionByName.
- values[1] = DescibleFunctionByName(info->function_name[info->cursor]);
+ values[1] = DescribeFunctionByName(info->function_name[info->cursor]);Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Datum pg_get_functiondef_extend(PG_FUNCTION_ARGS) | |
| { | |
| FuncCallContext *funcctx = NULL; | |
| FunctionInfo info = NULL; | |
| if (SRF_IS_FIRSTCALL()) | |
| { | |
| ArrayType *arguments_raw; | |
| int count_of_arguments; | |
| Datum *arguments; | |
| MemoryContext old_context; | |
| funcctx = SRF_FIRSTCALL_INIT(); | |
| old_context = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); | |
| arguments_raw = PG_GETARG_ARRAYTYPE_P(0); | |
| deconstruct_array_builtin((ArrayType *)arguments_raw, TEXTOID, &arguments, NULL, &count_of_arguments); | |
| info = (FunctionInfo)palloc0(sizeof(struct FunctionInfoData)); | |
| funcctx->user_fctx = info; | |
| info->function_name = palloc0(count_of_arguments * sizeof(char *)); | |
| for (int i = 0; i < count_of_arguments; i++) | |
| { | |
| info->function_name[i] = text_to_cstring((text *)arguments[i]); | |
| } | |
| info->cursor = 0; | |
| info->count_of_arguments = count_of_arguments; | |
| if (get_call_result_type(fcinfo, NULL, &info->result_desc) != TYPEFUNC_COMPOSITE) | |
| { | |
| ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record"))); | |
| } | |
| info->result_tuple_meta = TupleDescGetAttInMetadata(info->result_desc); | |
| MemoryContextSwitchTo(old_context); | |
| } | |
| funcctx = SRF_PERCALL_SETUP(); | |
| info = (FunctionInfo)(funcctx->user_fctx); | |
| if (info->cursor == info->count_of_arguments) | |
| { | |
| SRF_RETURN_DONE(funcctx); | |
| } | |
| else | |
| { | |
| HeapTuple tuple; | |
| Datum tuple_return; | |
| char **values; | |
| values = palloc0(sizeof(char *) * 2); | |
| values[0] = pstrdup(info->function_name[info->cursor]); | |
| values[1] = DescibleFunctionByName(info->function_name[info->cursor]); | |
| info->cursor++; | |
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, values); | |
| tuple_return = HeapTupleGetDatum(tuple); | |
| SRF_RETURN_NEXT(funcctx, tuple_return); | |
| } | |
| PG_RETURN_NULL(); | |
| Datum pg_get_functiondef_extend(PG_FUNCTION_ARGS) | |
| { | |
| FuncCallContext *funcctx = NULL; | |
| FunctionInfo info = NULL; | |
| if (SRF_IS_FIRSTCALL()) | |
| { | |
| ArrayType *arguments_raw; | |
| int count_of_arguments; | |
| Datum *arguments; | |
| MemoryContext old_context; | |
| funcctx = SRF_FIRSTCALL_INIT(); | |
| old_context = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); | |
| arguments_raw = PG_GETARG_ARRAYTYPE_P(0); | |
| deconstruct_array_builtin((ArrayType *)arguments_raw, TEXTOID, &arguments, NULL, &count_of_arguments); | |
| info = (FunctionInfo)palloc0(sizeof(struct FunctionInfoData)); | |
| funcctx->user_fctx = info; | |
| info->function_name = palloc0(count_of_arguments * sizeof(char *)); | |
| for (int i = 0; i < count_of_arguments; i++) | |
| { | |
| info->function_name[i] = text_to_cstring((text *)arguments[i]); | |
| } | |
| info->cursor = 0; | |
| info->count_of_arguments = count_of_arguments; | |
| if (get_call_result_type(fcinfo, NULL, &info->result_desc) != TYPEFUNC_COMPOSITE) | |
| { | |
| ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record"))); | |
| } | |
| info->result_tuple_meta = TupleDescGetAttInMetadata(info->result_desc); | |
| MemoryContextSwitchTo(old_context); | |
| } | |
| funcctx = SRF_PERCALL_SETUP(); | |
| info = (FunctionInfo)(funcctx->user_fctx); | |
| if (info->cursor == info->count_of_arguments) | |
| { | |
| SRF_RETURN_DONE(funcctx); | |
| } | |
| else | |
| { | |
| HeapTuple tuple; | |
| Datum tuple_return; | |
| char **values; | |
| values = palloc0(sizeof(char *) * 2); | |
| values[0] = pstrdup(info->function_name[info->cursor]); | |
| values[1] = DescribeFunctionByName(info->function_name[info->cursor]); | |
| info->cursor++; | |
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, values); | |
| tuple_return = HeapTupleGetDatum(tuple); | |
| SRF_RETURN_NEXT(funcctx, tuple_return); | |
| } | |
| PG_RETURN_NULL(); |
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
contrib/pg_get_functiondef/expected/pg_get_functiondef.outis excluded by!**/*.out
Files selected for processing (3)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c (1 hunks)
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c (1 hunks)
- contrib/pg_get_functiondef/sql/pg_get_functiondef.sql (1 hunks)
Files skipped from review due to trivial changes (1)
- contrib/pg_get_functiondef/sql/pg_get_functiondef.sql
Files skipped from review as they are similar to previous changes (2)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c
There was a problem hiding this comment.
Actionable comments posted: 3
Outside diff range, codebase verification and nitpick comments (1)
contrib/pg_get_functiondef/pg_get_functiondef_mul.c (1)
1-4: Enhance the file header for clarity.Consider adding more details about the purpose and usage of the
pg_get_functiondef_mulfunction in the file header./* pg_get_functiondef_mul.c Implementation of pg_get_functiondef_mul, which retrieves function definitions for multiple OIDs or function names simultaneously in PostgreSQL. */
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c (1 hunks)
Additional comments not posted (6)
contrib/pg_get_functiondef/pg_get_functiondef_mul.c (6)
17-26: Struct definition is well-organized.The
FunctionInfoDatastruct is clear and encapsulates the necessary data for function execution.
28-28: Function declaration is correct.The use of
PG_FUNCTION_INFO_V1forpg_get_functiondef_mulis appropriate and follows PostgreSQL conventions.
43-47: Ensure proper error handling for SPI connection.The error handling for
SPI_connectis minimal. Consider adding more context to the error message or handling specific error codes.
74-79: Optimize query construction for readability.The query construction could be simplified for better readability and maintainability.
92-99: Ensure proper cleanup on function completion.While the function correctly cleans up resources, ensure that all allocated memory and resources are freed, especially if additional allocations are added in the future.
63-70: Check for NULL in deconstruct_array_builtin.Ensure that the
deconstruct_array_builtinfunction handles NULL values appropriately foroidsand other parameters.Verification successful
NULL Handling in
deconstruct_array_builtinis AppropriateThe
deconstruct_array_builtinfunction relies ondeconstruct_arrayfor NULL handling, which appropriately manages NULL pointers for its parameters. Therefore, the current implementation is correct.
deconstruct_arraychecks for NULL array elements and handles thenullspparameter correctly.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that deconstruct_array_builtin handles NULL values correctly. # Test: Search for the function usage. Expect: Proper NULL handling in the code. rg --type c -A 5 $'deconstruct_array_builtin'Length of output: 24828
Script:
#!/bin/bash # Extract the implementation of deconstruct_array_builtin from arrayfuncs.c to verify NULL handling. ast-grep --lang c --pattern $'void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp) { $$$ }' --jsonLength of output: 3289
Script:
#!/bin/bash # Extract the implementation of deconstruct_array to verify NULL handling. ast-grep --lang c --pattern $'void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp) { $$$ }' --jsonLength of output: 3447
| /* If can't return composite type, end the work */ | ||
| if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) | ||
| { | ||
| ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record"))); | ||
| SPI_finish(); | ||
| SRF_RETURN_DONE(funcctx); | ||
| } |
There was a problem hiding this comment.
Improve error handling for composite type check.
The error message when the function cannot return a composite type is generic. Consider providing more context or suggestions for resolving the issue.
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Function returning record called in a context that cannot accept type record. Ensure the function is called in a suitable context.")));| { | ||
| ereport(ERROR, errmsg("SPI select failed!")); | ||
| SPI_finish(); | ||
| PG_RETURN_NULL(); | ||
| } |
There was a problem hiding this comment.
Enhance error handling for SPI_execute.
The error handling for SPI_execute is minimal. Consider adding more context to the error message or handling specific error codes.
ereport(ERROR, (errmsg("SPI select failed: %s", SPI_result_code_string(SPI_result))));| char **tuple_values; | ||
| HeapTuple tuple; | ||
| Datum tuple_return; | ||
| char *record = SPI_getvalue(info->spi_table->vals[0], info->spi_table->tupdesc, info->cursor); | ||
| tuple_values = palloc(2 * sizeof(char *)); | ||
| tuple_values[0] = palloc(sizeof(char) * 16); | ||
| sprintf(tuple_values[0], "%d", info->oids[info->cursor - 1]); | ||
| if (record) | ||
| { | ||
| tuple_values[1] = palloc(sizeof(char) * (strlen(record) + 1)); | ||
| sprintf(tuple_values[1], "%s", record); | ||
| } | ||
| else | ||
| { | ||
| tuple_values[1] = palloc(sizeof(char) * 1); | ||
| memset(tuple_values[1], 0, sizeof(char)); | ||
| } | ||
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, tuple_values); | ||
| info->cursor += 1; | ||
| tuple_return = HeapTupleGetDatum(tuple); | ||
| pfree(tuple_values[0]); | ||
| pfree(tuple_values[1]); | ||
| pfree(tuple_values); | ||
| SRF_RETURN_NEXT(funcctx, tuple_return); |
There was a problem hiding this comment.
Optimize memory allocation for tuple values.
Consider using palloc0 for initializing tuple_values to zero, which can prevent potential issues with uninitialized memory.
- tuple_values = palloc(2 * sizeof(char *));
+ tuple_values = palloc0(2 * sizeof(char *));Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| char **tuple_values; | |
| HeapTuple tuple; | |
| Datum tuple_return; | |
| char *record = SPI_getvalue(info->spi_table->vals[0], info->spi_table->tupdesc, info->cursor); | |
| tuple_values = palloc(2 * sizeof(char *)); | |
| tuple_values[0] = palloc(sizeof(char) * 16); | |
| sprintf(tuple_values[0], "%d", info->oids[info->cursor - 1]); | |
| if (record) | |
| { | |
| tuple_values[1] = palloc(sizeof(char) * (strlen(record) + 1)); | |
| sprintf(tuple_values[1], "%s", record); | |
| } | |
| else | |
| { | |
| tuple_values[1] = palloc(sizeof(char) * 1); | |
| memset(tuple_values[1], 0, sizeof(char)); | |
| } | |
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, tuple_values); | |
| info->cursor += 1; | |
| tuple_return = HeapTupleGetDatum(tuple); | |
| pfree(tuple_values[0]); | |
| pfree(tuple_values[1]); | |
| pfree(tuple_values); | |
| SRF_RETURN_NEXT(funcctx, tuple_return); | |
| char **tuple_values; | |
| HeapTuple tuple; | |
| Datum tuple_return; | |
| char *record = SPI_getvalue(info->spi_table->vals[0], info->spi_table->tupdesc, info->cursor); | |
| tuple_values = palloc0(2 * sizeof(char *)); | |
| tuple_values[0] = palloc(sizeof(char) * 16); | |
| sprintf(tuple_values[0], "%d", info->oids[info->cursor - 1]); | |
| if (record) | |
| { | |
| tuple_values[1] = palloc(sizeof(char) * (strlen(record) + 1)); | |
| sprintf(tuple_values[1], "%s", record); | |
| } | |
| else | |
| { | |
| tuple_values[1] = palloc(sizeof(char) * 1); | |
| memset(tuple_values[1], 0, sizeof(char)); | |
| } | |
| tuple = BuildTupleFromCStrings(info->result_tuple_meta, tuple_values); | |
| info->cursor += 1; | |
| tuple_return = HeapTupleGetDatum(tuple); | |
| pfree(tuple_values[0]); | |
| pfree(tuple_values[1]); | |
| pfree(tuple_values); | |
| SRF_RETURN_NEXT(funcctx, tuple_return); |
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
contrib/pg_get_functiondef/expected/pg_get_functiondef_1.outis excluded by!**/*.out
Files selected for processing (1)
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- contrib/pg_get_functiondef/pg_get_functiondef_mul.c
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (2)
contrib/pg_get_functiondef/expected/pg_get_functiondef.outis excluded by!**/*.outcontrib/pg_get_functiondef/expected/pg_get_functiondef_1.outis excluded by!**/*.out
Files selected for processing (2)
- contrib/pg_get_functiondef/pg_get_functiondef_no_input.c (1 hunks)
- contrib/pg_get_functiondef/sql/pg_get_functiondef.sql (1 hunks)
Files skipped from review due to trivial changes (2)
- contrib/pg_get_functiondef/pg_get_functiondef_no_input.c
- contrib/pg_get_functiondef/sql/pg_get_functiondef.sql
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- contrib/pg_get_functiondef/pg_get_functiondef_extend.c
在既有 pg_get_functiondef 函数的基础上,增强了其功能:
Summary by CodeRabbit
New Features
pg_get_functiondefextension for retrieving PostgreSQL function definitions.pg_get_functiondef(),pg_get_functiondef(OID, VARIADIC OID[]), andpg_get_functiondef(VARIADIC TEXT[])for enhanced function introspection.pg_get_functiondef_extendfunction, allowing users to retrieve function definitions based on an array of function names.pg_get_functiondef_mulfunction for retrieving definitions of multiple functions based on their OIDs.Bug Fixes
pg_get_functiondef_no_inputfunction.Documentation
pg_get_functiondefextension.