2011-12-18 20:14:16 +01:00
|
|
|
/*
|
|
|
|
* src/pl/plpython/plpy_typeio.h
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PLPY_TYPEIO_H
|
|
|
|
#define PLPY_TYPEIO_H
|
|
|
|
|
|
|
|
#include "access/htup.h"
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/tupdesc.h"
|
2011-12-18 20:14:16 +01:00
|
|
|
#include "fmgr.h"
|
|
|
|
#include "storage/itemptr.h"
|
|
|
|
|
|
|
|
struct PLyDatumToOb;
|
|
|
|
typedef PyObject *(*PLyDatumToObFunc) (struct PLyDatumToOb *, Datum);
|
|
|
|
|
|
|
|
typedef struct PLyDatumToOb
|
|
|
|
{
|
|
|
|
PLyDatumToObFunc func;
|
|
|
|
FmgrInfo typfunc; /* The type's output function */
|
|
|
|
Oid typoid; /* The OID of the type */
|
|
|
|
int32 typmod; /* The typmod of the type */
|
|
|
|
Oid typioparam;
|
|
|
|
bool typbyval;
|
|
|
|
int16 typlen;
|
|
|
|
char typalign;
|
|
|
|
struct PLyDatumToOb *elm;
|
|
|
|
} PLyDatumToOb;
|
|
|
|
|
|
|
|
typedef struct PLyTupleToOb
|
|
|
|
{
|
|
|
|
PLyDatumToOb *atts;
|
|
|
|
int natts;
|
|
|
|
} PLyTupleToOb;
|
|
|
|
|
|
|
|
typedef union PLyTypeInput
|
|
|
|
{
|
|
|
|
PLyDatumToOb d;
|
|
|
|
PLyTupleToOb r;
|
|
|
|
} PLyTypeInput;
|
|
|
|
|
|
|
|
/* convert PyObject to a Postgresql Datum or tuple.
|
|
|
|
* output from Python
|
|
|
|
*/
|
|
|
|
struct PLyObToDatum;
|
|
|
|
typedef Datum (*PLyObToDatumFunc) (struct PLyObToDatum *, int32, PyObject *);
|
|
|
|
|
|
|
|
typedef struct PLyObToDatum
|
|
|
|
{
|
|
|
|
PLyObToDatumFunc func;
|
|
|
|
FmgrInfo typfunc; /* The type's input function */
|
|
|
|
Oid typoid; /* The OID of the type */
|
|
|
|
int32 typmod; /* The typmod of the type */
|
|
|
|
Oid typioparam;
|
|
|
|
bool typbyval;
|
|
|
|
int16 typlen;
|
|
|
|
char typalign;
|
|
|
|
struct PLyObToDatum *elm;
|
|
|
|
} PLyObToDatum;
|
|
|
|
|
|
|
|
typedef struct PLyObToTuple
|
|
|
|
{
|
|
|
|
PLyObToDatum *atts;
|
|
|
|
int natts;
|
|
|
|
} PLyObToTuple;
|
|
|
|
|
|
|
|
typedef union PLyTypeOutput
|
|
|
|
{
|
|
|
|
PLyObToDatum d;
|
|
|
|
PLyObToTuple r;
|
|
|
|
} PLyTypeOutput;
|
|
|
|
|
|
|
|
/* all we need to move Postgresql data to Python objects,
|
|
|
|
* and vice versa
|
|
|
|
*/
|
|
|
|
typedef struct PLyTypeInfo
|
|
|
|
{
|
|
|
|
PLyTypeInput in;
|
|
|
|
PLyTypeOutput out;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* is_rowtype can be: -1 = not known yet (initial state); 0 = scalar
|
|
|
|
* datatype; 1 = rowtype; 2 = rowtype, but I/O functions not set up yet
|
|
|
|
*/
|
|
|
|
int is_rowtype;
|
|
|
|
/* used to check if the type has been modified */
|
|
|
|
Oid typ_relid;
|
|
|
|
TransactionId typrel_xmin;
|
|
|
|
ItemPointerData typrel_tid;
|
|
|
|
} PLyTypeInfo;
|
|
|
|
|
2011-12-29 21:55:49 +01:00
|
|
|
extern void PLy_typeinfo_init(PLyTypeInfo *arg);
|
|
|
|
extern void PLy_typeinfo_dealloc(PLyTypeInfo *arg);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
2011-12-29 21:55:49 +01:00
|
|
|
extern void PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup);
|
|
|
|
extern void PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
2011-12-29 21:55:49 +01:00
|
|
|
extern void PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc);
|
|
|
|
extern void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
2011-12-29 21:55:49 +01:00
|
|
|
extern void PLy_output_record_funcs(PLyTypeInfo *arg, TupleDesc desc);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
PL/Python: Accept strings in functions returning composite types
Before 9.1, PL/Python functions returning composite types could return
a string and it would be parsed using record_in. The 9.1 changes made
PL/Python only expect dictionaries, tuples, or objects supporting
getattr as output of composite functions, resulting in a regression
and a confusing error message, as the strings were interpreted as
sequences and the code for transforming lists to database tuples was
used. Fix this by treating strings separately as before, before
checking for the other types.
The reason why it's important to support string to database tuple
conversion is that trigger functions on tables with composite columns
get the composite row passed in as a string (from record_out).
Without supporting converting this back using record_in, this makes it
impossible to implement pass-through behavior for these columns, as
PL/Python no longer accepts strings for composite values.
A better solution would be to fix the code that transforms composite
inputs into Python objects to produce dictionaries that would then be
correctly interpreted by the Python->PostgreSQL counterpart code. But
that would be too invasive to backpatch to 9.1, and it is too late in
the 9.2 cycle to attempt it. It should be revisited in the future,
though.
Reported as bug #6559 by Kirill Simonov.
Jan Urbański
2012-04-26 20:03:48 +02:00
|
|
|
/* conversion from Python objects to composite Datums */
|
|
|
|
extern Datum PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
|
|
|
/* conversion from heap tuples to Python dictionaries */
|
2011-12-29 21:55:49 +01:00
|
|
|
extern PyObject *PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc);
|
2011-12-18 20:14:16 +01:00
|
|
|
|
2012-06-10 21:20:04 +02:00
|
|
|
#endif /* PLPY_TYPEIO_H */
|