mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Rewrite array_cmp to not depend on deconstruct_array. Should be a little
faster, but more importantly does not leak memory. Still needs more work though, per my recent note to pgsql-hackers.
This commit is contained in:
		@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.97 2003/08/08 21:42:04 momjian Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.98 2003/08/15 00:22:26 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -2510,18 +2510,21 @@ array_cmp(FunctionCallInfo fcinfo)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 | 
						ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 | 
				
			||||||
	ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
 | 
						ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
 | 
				
			||||||
 | 
						char	   *p1 = (char *) ARR_DATA_PTR(array1);
 | 
				
			||||||
 | 
						char	   *p2 = (char *) ARR_DATA_PTR(array2);
 | 
				
			||||||
 | 
						int			ndims1 = ARR_NDIM(array1);
 | 
				
			||||||
 | 
						int			ndims2 = ARR_NDIM(array2);
 | 
				
			||||||
 | 
						int		   *dims1 = ARR_DIMS(array1);
 | 
				
			||||||
 | 
						int		   *dims2 = ARR_DIMS(array2);
 | 
				
			||||||
 | 
						int			nitems1 = ArrayGetNItems(ndims1, dims1);
 | 
				
			||||||
 | 
						int			nitems2 = ArrayGetNItems(ndims2, dims2);
 | 
				
			||||||
 | 
						Oid			element_type = ARR_ELEMTYPE(array1);
 | 
				
			||||||
	FmgrInfo   *ac_fmgr_info = fcinfo->flinfo;
 | 
						FmgrInfo   *ac_fmgr_info = fcinfo->flinfo;
 | 
				
			||||||
	Datum		opresult;
 | 
					 | 
				
			||||||
	int			result = 0;
 | 
						int			result = 0;
 | 
				
			||||||
	Oid			element_type = InvalidOid;
 | 
					 | 
				
			||||||
	int			typlen;
 | 
						int			typlen;
 | 
				
			||||||
	bool		typbyval;
 | 
						bool		typbyval;
 | 
				
			||||||
	char		typalign;
 | 
						char		typalign;
 | 
				
			||||||
	Datum	   *dvalues1;
 | 
						int			min_nitems;
 | 
				
			||||||
	int			nelems1;
 | 
					 | 
				
			||||||
	Datum	   *dvalues2;
 | 
					 | 
				
			||||||
	int			nelems2;
 | 
					 | 
				
			||||||
	int			min_nelems;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	typedef struct
 | 
						typedef struct
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -2534,7 +2537,6 @@ array_cmp(FunctionCallInfo fcinfo)
 | 
				
			|||||||
	} ac_extra;
 | 
						} ac_extra;
 | 
				
			||||||
	ac_extra   *my_extra;
 | 
						ac_extra   *my_extra;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	element_type = ARR_ELEMTYPE(array1);
 | 
					 | 
				
			||||||
	if (element_type != ARR_ELEMTYPE(array2))
 | 
						if (element_type != ARR_ELEMTYPE(array2))
 | 
				
			||||||
		ereport(ERROR,
 | 
							ereport(ERROR,
 | 
				
			||||||
				(errcode(ERRCODE_DATATYPE_MISMATCH),
 | 
									(errcode(ERRCODE_DATATYPE_MISMATCH),
 | 
				
			||||||
@@ -2573,42 +2575,49 @@ array_cmp(FunctionCallInfo fcinfo)
 | 
				
			|||||||
	typbyval = my_extra->typbyval;
 | 
						typbyval = my_extra->typbyval;
 | 
				
			||||||
	typalign = my_extra->typalign;
 | 
						typalign = my_extra->typalign;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* extract a C array of arg array datums */
 | 
						/* Loop over source data */
 | 
				
			||||||
	deconstruct_array(array1, element_type, typlen, typbyval, typalign,
 | 
						min_nitems = Min(nitems1, nitems2);
 | 
				
			||||||
					  &dvalues1, &nelems1);
 | 
						for (i = 0; i < min_nitems; i++)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	deconstruct_array(array2, element_type, typlen, typbyval, typalign,
 | 
					 | 
				
			||||||
					  &dvalues2, &nelems2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	min_nelems = Min(nelems1, nelems2);
 | 
					 | 
				
			||||||
	for (i = 0; i < min_nelems; i++)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* are they equal */
 | 
							Datum		elt1;
 | 
				
			||||||
		opresult = FunctionCall2(&my_extra->eqproc,
 | 
							Datum		elt2;
 | 
				
			||||||
								 dvalues1[i], dvalues2[i]);
 | 
							Datum		opresult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!DatumGetBool(opresult))
 | 
							/* Get element pair */
 | 
				
			||||||
 | 
							elt1 = fetch_att(p1, typbyval, typlen);
 | 
				
			||||||
 | 
							elt2 = fetch_att(p2, typbyval, typlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p1 = att_addlength(p1, typlen, PointerGetDatum(p1));
 | 
				
			||||||
 | 
							p1 = (char *) att_align(p1, typalign);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p2 = att_addlength(p2, typlen, PointerGetDatum(p2));
 | 
				
			||||||
 | 
							p2 = (char *) att_align(p2, typalign);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Compare the pair of elements */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* are they equal */
 | 
				
			||||||
 | 
							opresult = FunctionCall2(&my_extra->eqproc, elt1, elt2);
 | 
				
			||||||
 | 
							if (DatumGetBool(opresult))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* nope, see if arg1 is less than arg2 */
 | 
				
			||||||
 | 
							opresult = FunctionCall2(&my_extra->ordproc, elt1, elt2);
 | 
				
			||||||
 | 
							if (DatumGetBool(opresult))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* nope, see if arg1 is less than arg2 */
 | 
								/* arg1 is less than arg2 */
 | 
				
			||||||
			opresult = FunctionCall2(&my_extra->ordproc,
 | 
								result = -1;
 | 
				
			||||||
									 dvalues1[i], dvalues2[i]);
 | 
								break;
 | 
				
			||||||
			if (DatumGetBool(opresult))
 | 
							}
 | 
				
			||||||
			{
 | 
							else
 | 
				
			||||||
				/* arg1 is less than arg2 */
 | 
							{
 | 
				
			||||||
				result = -1;
 | 
								/* arg1 is greater than arg2 */
 | 
				
			||||||
				break;
 | 
								result = 1;
 | 
				
			||||||
			}
 | 
								break;
 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				/* arg1 is greater than arg2 */
 | 
					 | 
				
			||||||
				result = 1;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((result == 0) && (nelems1 != nelems2))
 | 
						if ((result == 0) && (nitems1 != nitems2))
 | 
				
			||||||
		result = (nelems1 < nelems2) ? -1 : 1;
 | 
							result = (nitems1 < nitems2) ? -1 : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Avoid leaking memory when handed toasted input. */
 | 
						/* Avoid leaking memory when handed toasted input. */
 | 
				
			||||||
	PG_FREE_IF_COPY(array1, 0);
 | 
						PG_FREE_IF_COPY(array1, 0);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user