[GENERAL] Re: [SQL] getting the oid for a new tuple in a BEFORE trigger

2001-08-30 Thread Francesco Casadei

On Wed, Aug 29, 2001 at 11:15:08AM +0200, Markus Wagner wrote:
> Hi,
> 
> we need to control database changes within BEFORE triggers.
> There is no problem with triggers called by update, but there is
> a problem with triggers called by insert.
> 
> We strongly need to know the oid of a newly inserted tuple. In this case, we 
> use tg_newtuple of the TriggerData structure passed to thetrigger function, 
> and its t_data -> t_oid will have the value '0'.
> 
> Using BEFORE and AFTER triggers would make our lives much harder.
> 
> Is there any way (even hack) to get the oid the newly inserted tuple will 
> receive?
> 
> Thank you very much,
> 
> Markus
> 
> 
> ---(end of broadcast)---
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to [EMAIL PROTECTED] so that your
> message can get through to the mailing list cleanly
> 
> end of the original message

Read section 24.2.5.4 'Obtaining other results status' of the Programmer's
Guide. This is for the PL/pgSQL language, though.

Francesco Casadei

---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])



Re: [GENERAL] version 1 C-Language Functions

2001-08-26 Thread Francesco Casadei

On Sat, Aug 25, 2001 at 08:04:37PM -0400, Gowey, Geoffrey wrote:
> What would the correct syntax be in order to do what I want to?  I need to
> enter in a variable length email address as the parameter to my planned
> function.  The param will then become part of a select statement to get
> records (which I currently plan to accomplish by using strcat to join the
> beginning of the select plus the param plus the closing '.  Also where is
> some good documentation on V1 command usage and examples?
> 
> Geoff
> 
> -Original Message-
> From: Tom Lane [mailto:[EMAIL PROTECTED]]
> Sent: Saturday, August 25, 2001 7:29 PM
> To: Gowey, Geoffrey
> Cc: '[EMAIL PROTECTED]'
> Subject: Re: [GENERAL] version 1 C-Language Functions 
> 
> 
> "Gowey, Geoffrey" <[EMAIL PROTECTED]> writes:
> > Unfortunately, this function fails.  What am i doing wrong?
> 
> "text *" is not "char *".  The equivalent V0 code would fail just the
> same way.
> 
>   regards, tom lane
> 
> ---(end of broadcast)---
> TIP 6: Have you searched our list archives?
> 
> http://www.postgresql.org/search.mpl
> 
> end of the original message

Read the "Programmer's Guide", part II "Server Programming", section 13.4.3
"Version-1 Calling Conventions for C-Language Functions". Look at the example
functions copytext and concat_text.

Francesco Casadei

---(end of broadcast)---
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/users-lounge/docs/faq.html



[GENERAL] return value of a version-1 C function (Solved)

2001-06-05 Thread Francesco Casadei

[This message refers to my previous post '[GENERAL] return value of a version-1
C function']

Ooops, I didn't read the docs very carefully! I solved the problem, by
declaring cod as a proper structure and then returning it with
PG_RETURN_BPCHAR_P(cod):

  BpChar *cod = (BpChar *)SPI_palloc(VARHDRSZ + 8);
  char c[9];
  ...
  /* c = generated code (8 chars) + '\0' */
  ...
  cod->vl_len = VARHDRSZ + 8;
  memmove(VARDATA(cod), c, 8);

  PG_RETURN_BPCHAR_P(cod);
}

Now I have three more questions!

1) SPI_connect() and SPI_finish() mark a new memory context; since I must
return cod I need to SPI_palloc() it in the upper Executor context. The
problem is: how can I free the SPI_palloc()'ed memory? I can't SPI_pfree() it
before PG_RETURN_BPCHAR_P(cod), conversely nothing after
PG_RETURN_BPCHAR_P(cod) would be executed. As stated in section 22.3 of the
PostgreSQL Programmer's Guide 'SPI has no ability to automatically free
allocations in the upper Executor context!', hence the question: how do I cope
with this situation?

2) If I use the VARSIZE(__PTR) macro (defined in postgres.h) to set the size of
cod, the compiler will complain about an invalid lvalue. This is not valid:

VARSIZE(cod) = VARHDRSZ + 8;

Can I safely use:

cod->vl_len = VARHDRSZ + 8;

or is this incorrect?

3) The following variable is an identifier (Name):

Name tablename = PG_GETARG_NAME(0);

If I want to retrieve the string contained in the union pointed to by
tablename I should use the macro NameStr(name) defined in c.h:

(void)strlcat(query, NameStr(fieldname), sizeof(query));

but again the compiler will complain with the error "request for member `data'
in something not a structure or union". Name is a pointer to NameData
union:

typedef union nameData
{
chardata[NAMEDATALEN];
int alignmentDummy;
} NameData;
typedef NameData *Name;

NameStr is defined as:

#define NameStr(name)   ((name).data)

but name is a pointer, so shouldn't NameStr be defined as:

#define NameStr(name)   ((name)->data)

? Is it correct to use: tablename->data?

I attached the C code of the function. I'm not a C/PostgreSQL guru, so ANY
suggestion is welcome. Thanks in advance for your help.

Francesco Casadei


#include 
#include 
#include 
#include 
#include "postgres.h"
#include "fmgr.h"
#include "executor/spi.h"


char cod[8];/* codice di otto lettere */


PG_FUNCTION_INFO_V1(genera_codice);

Datum genera_codice(PG_FUNCTION_ARGS) {

  int i;
  char n;   /* numero pseudo-casuale */
  char c[9];/* codice di otto lettere + NULL */
  char query[1024]; /* testo della query per selezionare il codice */
  Name tablename = PG_GETARG_NAME(0);
  Name fieldname = PG_GETARG_NAME(1);

  elog(DEBUG, "tablename: %s", tablename->data);
  elog(DEBUG, "fieldname: %s", fieldname->data);

  /* Connette la procedura all'SPI manager */
  if (SPI_connect() != SPI_OK_CONNECT)
PG_RETURN_NULL();

  do {
/* Genera il codice di otto lettere */
for (i = 0; i < 8; i++) {
  srandomdev();
  n = (char)(random() % 62);/* Numero pseudo-casuale compreso tra 0 e 61 */
  if (n <= 25) {
/* 0 <= n <= 25: lettera tra 'A' e 'Z' (alfabeto inglese) */
cod[i] = n + 'A';
c[i] = cod[i];
  } else if (n <= 51) {
/* 26 <= n <= 51: lettera tra 'a' e 'z' (alfabeto inglese) */
cod[i] = (n - 26) + 'a';
c[i] = cod[i];
  } else {
/* 52 <= n <= 61: cifra tra '0' e '9' */
cod[i] = (n - 52) + '0';
c[i] = cod[i];
  }
}
c[i] = '\0';

elog(DEBUG, "Generated code: %s", c);

/*
 * Prepara il testo della query che verifica se nella base di dati
 * e' gia' presente il codice appena generato
 */
bzero(query, sizeof(query));
(void)strlcat(query, "SELECT ", sizeof(query));
(void)strlcat(query, fieldname->data, sizeof(query));
(void)strlcat(query, " FROM ", sizeof(query));
(void)strlcat(query, tablename->data, sizeof(query));
(void)strlcat(query, " WHERE ", sizeof(query));
(void)strlcat(query, fieldname->data, sizeof(query));
(void)strlcat(query, " = '", sizeof(query));
(void)strlcat(query, c, sizeof(query));
(void)strlcat(query, "';", sizeof(query));

elog(DEBUG, "Query text: %s", query);

/* Esegue la query per cercare il codice generato */
if (SPI