Hi,
I'm creating my first ever extension. The function that I'm trying to write takes the schema and name of a table, and
addsit in a table with all the tables the extension follows.
In that table I want the schema, name and oid of the table.
I created a C function for that. Here is the code
```
Datum add_mygreat_table(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(add_mygreat_table);
Datum add_mygreat_table(PG_FUNCTION_ARGS) {
char *tableSchema,
*tableName;
Oid tableNamespace,
relationId;
tableSchema = PG_GETARG_CSTRING(0);
tableName = PG_GETARG_CSTRING(1);
tableNamespace = get_namespace_oid(tableSchema, false);
relationId = get_relname_relid(tableName, tableNamespace);
if (relationId == NULL)
{
ereport(ERROR, (errmsg("could not create remote table: "
"relation does not exist")));
}
Datum values[3];
bool isNulls[3];
memset(isNulls, false, sizeof(isNulls));
values[0] = CStringGetTextDatum(tableSchema);
values[1] = CStringGetTextDatum(tableName);
values[2] = ObjectIdGetDatum(relationId);
Relation greatTable = table_open(MyGreatTablesRelationId(), RowExclusiveLock);
HeapTuple tuple = heap_form_tuple(RelationGetDescr(greatTable), values, isNulls);
/*
* CatalogTupleInsert() is originally for PostgreSQL's catalog. However,
* it is used at here for convenience.
*/
CatalogTupleInsert(greatTable, tuple);
table_close(greatTable, RowExclusiveLock);
heap_freetuple(tuple);
CommandCounterIncrement();
ereport(NOTICE,
(errmsg("Table %s is now a great table", tableName)));
PG_RETURN_BOOL(true);
}
```
And in the sql I have
```
CREATE OR REPLACE FUNCTION mygreat.add_mygreat_table(cstring, cstring)
RETURNS bool
LANGUAGE C STRICT IMMUTABLE
AS '$libdir/mygreat',
$$add_mygreat_table$$;
```
Here is my problem, it works as expected when the table doesn't exist.
```
mygreat_test=# create extension hydra;
CREATE EXTENSION
mygreat_test=# select mygreat.add_mygreat_table('public', 'sampledata3');
ERROR: could not create remote table: relation does not exist
```
However if the table exists it just completely crashes
```
hydra_test=# select hydra.add_remote_table('snowflake', 'public', 'sampledata2');
NOTICE: Table sampledata2 is now a mygreat table
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
```
I figured that it was because of the `IMMUTABLE` as the function does modify the database. And according to
documentation
```
IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same
argumentvalues; t
```
So I tried creating it as a `VOLATILE` function.
```
CREATE OR REPLACE FUNCTION hydra.add_remote_table(cstring, cstring)
RETURNS bool
LANGUAGE C STRICT VOLATILE
AS '$libdir/mygreat',
$$add_mygreat_table$$;
CREATE FUNCTION
```
But now it just always crashes, and what used to return the proper error message when ran against a table that doesn't
existnow returns
```
mygreat_test=# select mygreat.add_mygreat_table('public', 'sampledata3');
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
```
In the logs, for the latest, I get
```
2021-10-27 12:28:02.712 PDT [44115] LOG: statement: select mygreat.add_mygreat_table('public', 'sampledata3');
2021-10-27 12:28:02.718 PDT [43936] LOG: server process (PID 44115) was terminated by signal 11: Segmentation fault:
11
2021-10-27 12:28:02.718 PDT [43936] DETAIL: Failed process was running: select mygreat.add_mygreat_table('public',
'sampledata3');
2021-10-27 12:28:02.719 PDT [43936] LOG: terminating any other active server processes
```
What am I doing wrong? Can anyone help me with this?
Thank you!