functional index arg matching patch

Started by Mark Hollomonover 25 years ago4 messages
#1Mark Hollomon
mhh@mindspring.com
1 attachment(s)

Attached is a patch to allow
functinal indecies to use functions that
are for 'binary-compatible' types.

eg

create function foobar(text) returns text as ....

create table vc ( a varchar );

create index on vc ( foobar(a) );

should now work.

--
Mark Hollomon
mhh@mindspring.com

Attachments:

index.patchtext/plain; charset=us-asciiDownload
*** indexcmds.c.orig	Fri Aug 18 21:38:34 2000
--- indexcmds.c	Mon Aug 21 11:42:16 2000
***************
*** 21,26 ****
--- 21,27 ----
  #include "catalog/catname.h"
  #include "catalog/heap.h"
  #include "catalog/index.h"
+ #include "catalog/indexing.h"
  #include "catalog/pg_am.h"
  #include "catalog/pg_amop.h"
  #include "catalog/pg_database.h"
***************
*** 414,425 ****
  								0);
  	if (!HeapTupleIsValid(tuple))
  	{
! 		func_error("DefineIndex", funcIndex->name,
! 				   indexInfo->ii_NumKeyAttrs, argTypes, NULL);
  	}
  
  	indexInfo->ii_FuncOid = tuple->t_data->t_oid;
  	retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
  
  	/* Process opclass, using func return type as default type */
  
--- 415,527 ----
  								0);
  	if (!HeapTupleIsValid(tuple))
  	{
! 		Relation	heapRelation;
! 		Relation	idesc;
! 		ScanKeyData skey;
! 		HeapTupleData stuple;
! 		IndexScanDesc sd;
! 		RetrieveIndexResult indexRes;
! 		Form_pg_proc pgProcP;
! 		int best_arg_match;
! 		int match_count;
! 		Oid bestArgTypes[FUNC_MAX_ARGS];
! 
! 		MemSet(bestArgTypes, 0, sizeof(bestArgTypes));
! 
! 		heapRelation = heap_openr(ProcedureRelationName, AccessShareLock);
! 
! 		ScanKeyEntryInitialize(&skey,
! 						   (bits16) 0x0,
! 						   (AttrNumber) Anum_pg_proc_proname,
! 						   (RegProcedure) F_NAMEEQ,
! 						   (Datum) funcIndex->name);
! 
! 		idesc = index_openr(ProcedureNameIndex);
! 
! 		sd = index_beginscan(idesc, false, 1, &skey);
! 
! 		/* The number of exact arg matches for the best match so far */
! 		best_arg_match = -1;
! 		/* the number of functions with best_arg_match matches seen.
! 		 * If we end with this being more than one, there is an ambiguity
! 		 */
! 		match_count = 0;
! 
! 		do
! 		{
! 			indexRes = index_getnext(sd, ForwardScanDirection);
! 			if (indexRes)
! 			{
! 				Buffer		buffer;
! 
! 				stuple.t_datamcxt = NULL;
! 				stuple.t_data = NULL;
! 				stuple.t_self = indexRes->heap_iptr;
! 				heap_fetch(heapRelation, SnapshotNow, &stuple, &buffer);
! 				pfree(indexRes);
! 				if (stuple.t_data != NULL)
! 				{
! 					pgProcP = (Form_pg_proc) GETSTRUCT(&stuple);
! 					if (pgProcP->pronargs == argn)
! 					{
! 						int current_match_count;
! 						int i;
! 
! 						current_match_count = 0;
! 						for (i=0; i< argn; i++)
! 						{
! 							if (argTypes[i] == pgProcP->proargtypes[i]) {
! 								current_match_count += 1;
! 							} else if (! IS_BINARY_COMPATIBLE(argTypes[i], pgProcP->proargtypes[i]))
! 							{
! 								break;
! 							}
! 						}
! 						if (i == argn)
! 						{
! 							if (current_match_count > best_arg_match)
! 							{
! 								best_arg_match = current_match_count;
! 								match_count = 1;
! 								for (i=0; i<argn; i++)
! 								{
! 									bestArgTypes[i] =  pgProcP->proargtypes[i];
! 								}
! 							} else if (current_match_count == best_arg_match)
! 							{
! 								match_count += 1;
! 							}
! 						}
! 					}
! 				ReleaseBuffer(buffer);
! 				}
! 			}
! 		}while (indexRes);
! 
! 		index_endscan(sd);
! 		index_close(idesc);
! 		heap_close(heapRelation, AccessShareLock);
! 
! 		if (match_count != 1)
! 		{
! 			func_error("DefineIndex", funcIndex->name,
! 						indexInfo->ii_NumKeyAttrs, argTypes, NULL);
! 		}
! 		tuple = SearchSysCacheTuple(PROCNAME,
! 									PointerGetDatum(funcIndex->name),
! 									Int32GetDatum(indexInfo->ii_NumKeyAttrs),
! 									PointerGetDatum(bestArgTypes),
! 									0);
! 		if (! HeapTupleIsValid(tuple))
! 		{
! 			elog(ERROR, "Gosh, why couldn't we find the function after matching its args");
! 		}
! 
  	}
  
  	indexInfo->ii_FuncOid = tuple->t_data->t_oid;
  	retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
+ 
  
  	/* Process opclass, using func return type as default type */
  
#2Mark Hollomon
mhh@nortelnetworks.com
In reply to: Mark Hollomon (#1)
Re: functional index arg matching patch

Tom Lane wrote:

Mark Hollomon <mhh@mindspring.com> writes:

Attached is a patch to allow
functinal indecies to use functions that
are for 'binary-compatible' types.

Um, thanks for working on this, but I already fixed that...

regards, tom lane

When? A message you sent on 8-11 indicated it wasn't.

And I didn't see any code in CVS as of ~ 8-17
when I started. But I may have missed it.

I'll be interested in seeing how you
did it.

--

Mark Hollomon
mhh@nortelnetworks.com

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Mark Hollomon (#2)
Re: functional index arg matching patch

"Mark Hollomon" <mhh@nortelnetworks.com> writes:

Tom Lane wrote:

Um, thanks for working on this, but I already fixed that...

When? A message you sent on 8-11 indicated it wasn't.

(Checks CVS) ... yesterday, actually.

I'll be interested in seeing how you did it.

I just called the ambiguous-function-name-resolution code in
parse_func.c and then checked to make sure it hadn't selected
something the executor wasn't prepared to cope with --- ie,
functions requiring runtime conversions of input data types.

It looked like you had copied out a bunch of the parse_func.c code,
which is OK in the short run but the duplicated code might be
a headache to keep in sync later on.

regards, tom lane

#4Mark Hollomon
mhh@nortelnetworks.com
In reply to: Mark Hollomon (#1)
Re: functional index arg matching patch

Tom Lane wrote:

"Mark Hollomon" <mhh@nortelnetworks.com> writes:

Tom Lane wrote:

Um, thanks for working on this, but I already fixed that...

When? A message you sent on 8-11 indicated it wasn't.

(Checks CVS) ... yesterday, actually.

Yea, I saw it when a refreshed last night.

I'll be interested in seeing how you did it.

I just called the ambiguous-function-name-resolution code in
parse_func.c and then checked to make sure it hadn't selected
something the executor wasn't prepared to cope with --- ie,
functions requiring runtime conversions of input data types.

It looked like you had copied out a bunch of the parse_func.c code,
which is OK in the short run but the duplicated code might be
a headache to keep in sync later on.

I had thought about doing it the way you did, but didn't know the
consequences of some of the other coersions that parse_func.c
tried to do. My guess that it wasn't harmless was correct judging from
your code.

--

Mark Hollomon
mhh@nortelnetworks.com
ESN 451-9008 (302)454-9008