2

I'm currently implementing a user-defined data type - a linked list that mimics a set of integers in a file called intList.c, and hopefully used with intList.source to install it onto my Postgres server.

So my questions are the following:

  1. Can I write C functions such as (link newNode) and (link InsertEnd) in my code wherein they're not postgres functions to be declared & created in the source file?

  2. Can I use palloc in a function called from my input function? (in this case link newNode)? Or should I do it in my input function?

My code for intList.c is as follows: P.S. These functions all work in C, but I haven't installed them in my PostgreSQL server so I don't know how it'll turn out:

 // Defining struct for linked list
 typedef struct intSet *link;

 typedef struct intList {
    int num;
    link next;
 } intList;

 //  Create a new node
 link newNode(int item) {
     link n = (link) palloc(sizeof(*n));
     n->num = item;
     n->next = NULL;
     return n;
 }

 link insertEnd(link list, link n){
     link curr;
     // Empty list
     if(list == NULL){
         list = n;
         n->next = NULL;
     // If list not empty, iterate to end of list, then append
     } else {
         for(curr = list; curr->next != NULL; curr = curr->next) {
         }
         curr->next = n;
         n->next = NULL;
     }
     return list;
 }    

 PG_FUNCTION_INFO_V1(intList_in);

 Datum
 intList_in(PG_FUNCTION_ARGS)
 {
     char       *str = PG_GETARG_CSTRING(0);
     char       *token;

     // Create an empty linked list
     link newList;
     newList = NULL;

     // Get individual ints from a set e.g. {1, 2, 3, 4}
     token = strtok(str, ",{} ");

     // For each int, create a new node then
     // append to list
     while (token != NULL) {
         link a = NULL;
         a = newNode(atoi(token));
         newList = insertEnd(newList, a);
         token = strtok(NULL, ",{} ");
     }

     PG_RETURN_POINTER(newList);
 }

 Datum
 intList_out(PG_FUNCTION_ARGS)
 {
     // Start our string
     char* out = "{";
     char* num;
     // Retrieve our list from arg(0)
     link List = PG_GETARG_POINTER(0);
     link curr;
     // Traverse list till last node, add commas after each node
     for (curr = List; curr->next != NULL; curr = curr->next) {
         num = itoa(curr->num);
         strcat(num, ", "); 
         strcat(out, num);
     }
     // At last node, add closing bracket to close list
     num = itoa(curr->num);
     strcat(num, "}");
     strcat(out, num);

     // Psprintf to result then return it
     char *result;
     result = psprintf("%s", out);
     PG_RETURN_CSTRING(result);

 }

This is only a part of my entire code, I'll be implementing operators and other functions so any tips and pointers would be greatly appreciated.

user10284022
  • 65
  • 1
  • 7
  • 1) `token = strtok(str, ",{} ");` strtok() willdamage the str (which couldbe read-only,or partof a buffer or struct) 2) `num = itoa(curr->num); strcat(num, ", "); strcat(out, num);` will certainly segfault. – wildplasser Aug 29 '18 at 13:22
  • In the case of 1), I could make another string with strcpy, but what could you recommend I do in place of 2)? The only thing I could think of was defining the size of "out" to be BUFSIZ or something large. – user10284022 Aug 29 '18 at 13:57
  • I would not use strtok() at all: there is also a 0) `strtok()` relies on static data, using your code in multiple places within the same query (not impossible) could cause strange results, at least. – wildplasser Aug 29 '18 at 14:14
  • Well in that case stcpy will do the job and thanks for pointing out the segfault, itoa was certainly not a standard function so sprintf did the job, then I just used a static string that'll be reset for each call. – user10284022 Aug 30 '18 at 03:45

1 Answers1

1

Can I write C functions such as (link newNode) and (link InsertEnd) in my code wherein they're not postgres functions to be declared & created in the source file?

I assume you mean can you write them without palloc. Sure, you can. Though it's not advised. PostgreSQL wraps malloc for both performance reasons and for integrity reasons (making sure memory is freed at the end of txn). You'll have to take care of that without palloc, and I'm not sure what kind of challenges you'll encounter.

Can I use palloc in a function called from my input function? (in this case link newNode)? Or should I do it in my input function?

Sure, if you're running on the server That's what you're supposed to do. Just #include <postres.h>

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468