Problem with substitution of parameters on SPI_execute_plan function in Postgresql

Viewed 16

I'm trying to execute an SQL statement on a C core-function on Postgres. I'm using the SPI (Server Programming Interface) to do this.

The code is partially shown below.

However, when I execute the SPI_execute_plan, the argument $1 should be substituted by the parameter received on the function, but it is not being done correctly. The result is always the SPI_ERROR_ARGUMENT case.

I would like to know if I can print the SQL statement with the argument $1 substituted by the command and what is the problem with my code.

I'm using Postgres version 13.2 on CentOS 7.

Thanks in advance!

   PG_FUNCTION_INFO_V1(print_statistics);                                                                                                                
    Datum print_statistics(PG_FUNCTION_ARGS) {                                                                                                            
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1)|| PG_ARGISNULL(2) || PG_ARGISNULL(3)) {                                                  
            ereport(ERROR, (errmsg("Null parameters are not accepted.")));                                                                                  
        }                                                                                                                                                  
        text *arg1 = (text *)PG_GETARG_TEXT_P(0);                                                                                                          

        char * str1 = (char *)palloc(VARSIZE_ANY_EXHDR(arg1) + VARHDRSZ);
        
        SET_VARSIZE(str1, VARSIZE_ANY_EXHDR(arg1) + VARHDRSZ);
        
        memcpy(str1, VARDATA_ANY(arg1), VARSIZE_ANY_EXHDR(arg1));
       
        Oid argtypes[1] = {25};
        char nulls[1] = {' '};
        Datum values[1];
        values[0] = CStringGetDatum(str1);
       
        char* query = "SELECT * FROM table1 WHERE name = '$1'";
        SPIPlanPtr plan = SPI_prepare(query, 1, argtypes);

        elog(INFO, "arg1 (%s): %s", str1, DatumGetCString(values[0]));
       
        SPI_connect();

        int result = SPI_execute_plan(plan, values, nulls, false, 0);
        
        switch(result){
            case SPI_OK_SELECT: {elog(INFO, "SPI_OK_SELECT! Result: %d\n", result); break;}
            case SPI_ERROR_ARGUMENT: {elog(INFO, "SPI_ERROR_ARGUMENT. Result: %d\n", result); break;}
            case SPI_ERROR_COPY: {elog(INFO, "SPI_ERROR_COPY. Result: %d\n", result); break;}
            case SPI_ERROR_OPUNKNOWN: {elog(INFO, "SPI_ERROR_OPUNKNOWN. Result: %d\n", result); break;}
            case SPI_ERROR_UNCONNECTED: {elog(INFO, "SPI_ERROR_UNCONNECTED. Result: %d\n", result); break;}

        }
       
        SPI_finish(); 
1 Answers

The problem happened because I put the command to prepare the query before openning the connection with SPI.

The correct here is put the SPI_prepare(query, 1, argtypes); after the SPI_connect() command.

Related