Welcome to the CHICKEN Scheme pasting service

postgres trigger added by mercora on Mon Jun 27 23:35:13 2011

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "postgresql/server/postgres.h"
#include "postgresql/server/fmgr.h"
#include "postgresql/server/commands/trigger.h"
#include "postgresql/server/executor/spi.h"
#include "postgresql/server/catalog/pg_type.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

#define SERVER_HOST "127.0.0.1"
#define SERVER_PORT 7676

extern Datum miner_triggerf(PG_FUNCTION_ARGS);

// TODO: make this function accept a host an port to make it to something like dump_row_as_json_to_socket()
Datum miner_triggerf(PG_FUNCTION_ARGS){
  TriggerData *trigger_data = (TriggerData *) fcinfo->context;
  TupleDesc tuple_desc;
  HeapTuple returned_tuple;

  //leave row untouched
  if (TRIGGER_FIRED_BY_UPDATE(trigger_data->tg_event))
    returned_tuple = trigger_data->tg_newtuple;
  else
    returned_tuple = trigger_data->tg_trigtuple;


  //build json from row
  char json_row[8192]; //big enough ? what could went wrong ? ;P
  char *json_buffer;

  memset(&json_row, 0, sizeof(json_row));
  json_buffer = SPI_getrelname(trigger_data->tg_relation);
  sprintf(json_row, "{ \"table\": \"%s\", \"data\": { ", json_buffer);
  pfree(json_buffer);

  int i;
  for(i = 1; (json_buffer = SPI_fname(trigger_data->tg_relation->rd_att, i)) != NULL; i++){
    if(i != 1)
      strcat(json_row, ", ");
    sprintf(json_row, "%s \"%s\": ", json_row, json_buffer);
    pfree(json_buffer);
    
    // json/js may comes with restrictions on how thoses are displayed
    // says "All numbers in Javascript are 64 bit "double" precision IEE754 floating point."
    // Numeric in postgres is an arbitrary precision number .... does arbitrary fit in IEE754 floating point ?!? ;P
    switch(SPI_gettypeid(trigger_data->tg_relation->rd_att, i)){
    case INT4OID:
    case INT8OID:
    case NUMERICOID:
      json_buffer = SPI_getvalue(returned_tuple, trigger_data->tg_relation->rd_att, i);
      sprintf(json_row, "%s%s", json_row, json_buffer);
      break;
    case TIMESTAMPTZOID:
      //format returned by SPI_getvalue() is parseable by Datum() in js
    default:
      json_buffer = SPI_getvalue(returned_tuple, trigger_data->tg_relation->rd_att, i);
      sprintf(json_row, "%s\"%s\"", json_row, json_buffer);
    }
    pfree(json_buffer);
  }
  strcat(json_row, " } }");
  elog (WARNING, json_row);

  //send json to socket
  int notify_socket;
  struct sockaddr_in notify_socket_address;

  memset(&notify_socket_address, 0, sizeof(notify_socket_address));
  notify_socket_address.sin_family = AF_INET;
  notify_socket_address.sin_port = htons(SERVER_PORT);
  notify_socket_address.sin_addr.s_addr = inet_addr(SERVER_HOST);

  if((notify_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
    elog (WARNING, "failed to create miner notififaction socket");
  }else{
    if((sendto(notify_socket, json_row, strlen(json_row), 0,
               (struct sockaddr *) &notify_socket_address, sizeof(struct sockaddr))) == -1){
      elog (WARNING, "failed to send message to miner notififaction socket");
    }
  }
  close(notify_socket);

  return (Datum) returned_tuple;
}

Your annotation:

Enter a new annotation:

Your nick:
The title of your paste:
Your paste (mandatory) :
Which backend storage does qwiki use?
Visually impaired? Let me spell it for you (wav file) download WAV