plpgsql-provide-typmod.patch

text/x-patch

Filename: plpgsql-provide-typmod.patch
Type: text/x-patch
Part: 0
Message: Re: plpgsql doesn't supply typmod for the Params it generates

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/pl/plpgsql/src/pl_comp.c 0 0
src/pl/plpgsql/src/pl_exec.c 0 0
src/pl/plpgsql/src/plpgsql.h 0 0
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 535fea9257c22e5cc54dc956ebd59a6865340a55..a80235cd2aaf76e493f125c80a15bae9bc1b11ce 100644
*** a/src/pl/plpgsql/src/pl_comp.c
--- b/src/pl/plpgsql/src/pl_comp.c
*************** make_datum_param(PLpgSQL_expr *expr, int
*** 1267,1275 ****
  	param = makeNode(Param);
  	param->paramkind = PARAM_EXTERN;
  	param->paramid = dno + 1;
! 	param->paramtype = exec_get_datum_type(estate, datum);
! 	param->paramtypmod = -1;
! 	param->paramcollid = exec_get_datum_collation(estate, datum);
  	param->location = location;
  
  	return (Node *) param;
--- 1267,1277 ----
  	param = makeNode(Param);
  	param->paramkind = PARAM_EXTERN;
  	param->paramid = dno + 1;
! 	exec_get_datum_type_info(estate,
! 							 datum,
! 							 &param->paramtype,
! 							 &param->paramtypmod,
! 							 &param->paramcollid);
  	param->location = location;
  
  	return (Node *) param;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 1da5095507468c5c5c81fd0042e69a41edcef304..2a536b688d3efbdbde54d2e010cb706bb3fcab1f 100644
*** a/src/pl/plpgsql/src/pl_exec.c
--- b/src/pl/plpgsql/src/pl_exec.c
*************** exec_get_datum_type(PLpgSQL_execstate *e
*** 4307,4335 ****
  }
  
  /*
!  * exec_get_datum_collation				Get collation of a PLpgSQL_datum
   */
! Oid
! exec_get_datum_collation(PLpgSQL_execstate *estate,
! 						 PLpgSQL_datum *datum)
  {
- 	Oid			collid;
- 
  	switch (datum->dtype)
  	{
  		case PLPGSQL_DTYPE_VAR:
  			{
  				PLpgSQL_var *var = (PLpgSQL_var *) datum;
  
! 				collid = var->datatype->collation;
  				break;
  			}
  
  		case PLPGSQL_DTYPE_ROW:
  		case PLPGSQL_DTYPE_REC:
! 			/* composite types are never collatable */
! 			collid = InvalidOid;
! 			break;
  
  		case PLPGSQL_DTYPE_RECFIELD:
  			{
--- 4307,4369 ----
  }
  
  /*
!  * exec_get_datum_type_info			Get datatype etc of a PLpgSQL_datum
!  *
!  * An extended version of exec_get_datum_type, which also retrieves the
!  * typmod and collation of the datum.
   */
! void
! exec_get_datum_type_info(PLpgSQL_execstate *estate,
! 						 PLpgSQL_datum *datum,
! 						 Oid *typeid, int32 *typmod, Oid *collation)
  {
  	switch (datum->dtype)
  	{
  		case PLPGSQL_DTYPE_VAR:
  			{
  				PLpgSQL_var *var = (PLpgSQL_var *) datum;
  
! 				*typeid = var->datatype->typoid;
! 				*typmod = var->datatype->atttypmod;
! 				*collation = var->datatype->collation;
  				break;
  			}
  
  		case PLPGSQL_DTYPE_ROW:
+ 			{
+ 				PLpgSQL_row *row = (PLpgSQL_row *) datum;
+ 
+ 				if (!row->rowtupdesc)	/* should not happen */
+ 					elog(ERROR, "row variable has no tupdesc");
+ 				/* Make sure we have a valid type/typmod setting */
+ 				BlessTupleDesc(row->rowtupdesc);
+ 				*typeid = row->rowtupdesc->tdtypeid;
+ 				/* do NOT return the mutable typmod of a RECORD variable */
+ 				*typmod = -1;
+ 				/* composite types are never collatable */
+ 				*collation = InvalidOid;
+ 				break;
+ 			}
+ 
  		case PLPGSQL_DTYPE_REC:
! 			{
! 				PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
! 
! 				if (rec->tupdesc == NULL)
! 					ereport(ERROR,
! 						  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 						   errmsg("record \"%s\" is not assigned yet",
! 								  rec->refname),
! 						   errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
! 				/* Make sure we have a valid type/typmod setting */
! 				BlessTupleDesc(rec->tupdesc);
! 				*typeid = rec->tupdesc->tdtypeid;
! 				/* do NOT return the mutable typmod of a RECORD variable */
! 				*typmod = -1;
! 				/* composite types are never collatable */
! 				*collation = InvalidOid;
! 				break;
! 			}
  
  		case PLPGSQL_DTYPE_RECFIELD:
  			{
*************** exec_get_datum_collation(PLpgSQL_execsta
*** 4350,4370 ****
  							(errcode(ERRCODE_UNDEFINED_COLUMN),
  							 errmsg("record \"%s\" has no field \"%s\"",
  									rec->refname, recfield->fieldname)));
! 				/* XXX there's no SPI_getcollid, as yet */
  				if (fno > 0)
! 					collid = rec->tupdesc->attrs[fno - 1]->attcollation;
  				else	/* no system column types have collation */
! 					collid = InvalidOid;
  				break;
  			}
  
  		default:
  			elog(ERROR, "unrecognized dtype: %d", datum->dtype);
! 			collid = InvalidOid;	/* keep compiler quiet */
  			break;
  	}
- 
- 	return collid;
  }
  
  /* ----------
--- 4384,4410 ----
  							(errcode(ERRCODE_UNDEFINED_COLUMN),
  							 errmsg("record \"%s\" has no field \"%s\"",
  									rec->refname, recfield->fieldname)));
! 				*typeid = SPI_gettypeid(rec->tupdesc, fno);
! 				/* XXX there's no SPI_gettypmod, for some reason */
  				if (fno > 0)
! 					*typmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
! 				else
! 					*typmod = -1;
! 				/* XXX there's no SPI_getcollation either */
! 				if (fno > 0)
! 					*collation = rec->tupdesc->attrs[fno - 1]->attcollation;
  				else	/* no system column types have collation */
! 					*collation = InvalidOid;
  				break;
  			}
  
  		default:
  			elog(ERROR, "unrecognized dtype: %d", datum->dtype);
! 			*typeid = InvalidOid;	/* keep compiler quiet */
! 			*typmod = -1;
! 			*collation = InvalidOid;
  			break;
  	}
  }
  
  /* ----------
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index e50d7eb45fedec49a0f675fcd19359100fcc314b..89103aea8c5d3fa967ff2ab4a23105039dfe3a8d 100644
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
*************** extern void plpgsql_subxact_cb(SubXactEv
*** 905,912 ****
  				   SubTransactionId parentSubid, void *arg);
  extern Oid exec_get_datum_type(PLpgSQL_execstate *estate,
  					PLpgSQL_datum *datum);
! extern Oid exec_get_datum_collation(PLpgSQL_execstate *estate,
! 						 PLpgSQL_datum *datum);
  
  /* ----------
   * Functions for namespace handling in pl_funcs.c
--- 905,913 ----
  				   SubTransactionId parentSubid, void *arg);
  extern Oid exec_get_datum_type(PLpgSQL_execstate *estate,
  					PLpgSQL_datum *datum);
! extern void exec_get_datum_type_info(PLpgSQL_execstate *estate,
! 						 PLpgSQL_datum *datum,
! 						 Oid *typeid, int32 *typmod, Oid *collation);
  
  /* ----------
   * Functions for namespace handling in pl_funcs.c