mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Add text-vs-name cross-type operators, and unify name_ops with text_ops.
Now that name comparison has effectively the same behavior as text comparison, we might as well merge the name_ops opfamily into text_ops, allowing cross-type comparisons to be processed without forcing a datatype coercion first. We need do little more than add cross-type operators to make the opfamily complete, and fix one or two places in the planner that assumed text_ops was a single-datatype opfamily. I chose to unify hash name_ops into hash text_ops as well, since the types have compatible hashing semantics. This allows marking the new cross-type equality operators as oprcanhash. (Note: this doesn't remove the name_ops opclasses, so there's no breakage of index definitions. Those opclasses are just reparented into the text_ops opfamily.) Discussion: https://postgr.es/m/15938.1544377821@sss.pgh.pa.us
This commit is contained in:
		@@ -25,6 +25,7 @@
 | 
				
			|||||||
#include "catalog/pg_opfamily.h"
 | 
					#include "catalog/pg_opfamily.h"
 | 
				
			||||||
#include "catalog/pg_type.h"
 | 
					#include "catalog/pg_type.h"
 | 
				
			||||||
#include "nodes/makefuncs.h"
 | 
					#include "nodes/makefuncs.h"
 | 
				
			||||||
 | 
					#include "nodes/nodeFuncs.h"
 | 
				
			||||||
#include "optimizer/clauses.h"
 | 
					#include "optimizer/clauses.h"
 | 
				
			||||||
#include "optimizer/cost.h"
 | 
					#include "optimizer/cost.h"
 | 
				
			||||||
#include "optimizer/pathnode.h"
 | 
					#include "optimizer/pathnode.h"
 | 
				
			||||||
@@ -3518,6 +3519,10 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
 | 
				
			|||||||
		case OID_TEXT_ICLIKE_OP:
 | 
							case OID_TEXT_ICLIKE_OP:
 | 
				
			||||||
		case OID_TEXT_REGEXEQ_OP:
 | 
							case OID_TEXT_REGEXEQ_OP:
 | 
				
			||||||
		case OID_TEXT_ICREGEXEQ_OP:
 | 
							case OID_TEXT_ICREGEXEQ_OP:
 | 
				
			||||||
 | 
							case OID_NAME_LIKE_OP:
 | 
				
			||||||
 | 
							case OID_NAME_ICLIKE_OP:
 | 
				
			||||||
 | 
							case OID_NAME_REGEXEQ_OP:
 | 
				
			||||||
 | 
							case OID_NAME_ICREGEXEQ_OP:
 | 
				
			||||||
			isIndexable =
 | 
								isIndexable =
 | 
				
			||||||
				(opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
 | 
									(opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
 | 
				
			||||||
				(opfamily == TEXT_SPGIST_FAM_OID) ||
 | 
									(opfamily == TEXT_SPGIST_FAM_OID) ||
 | 
				
			||||||
@@ -3537,14 +3542,6 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
 | 
				
			|||||||
				  lc_collate_is_c(idxcollation)));
 | 
									  lc_collate_is_c(idxcollation)));
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case OID_NAME_LIKE_OP:
 | 
					 | 
				
			||||||
		case OID_NAME_ICLIKE_OP:
 | 
					 | 
				
			||||||
		case OID_NAME_REGEXEQ_OP:
 | 
					 | 
				
			||||||
		case OID_NAME_ICREGEXEQ_OP:
 | 
					 | 
				
			||||||
			/* name uses locale-insensitive sorting */
 | 
					 | 
				
			||||||
			isIndexable = (opfamily == NAME_BTREE_FAM_OID);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case OID_BYTEA_LIKE_OP:
 | 
							case OID_BYTEA_LIKE_OP:
 | 
				
			||||||
			isIndexable = (opfamily == BYTEA_BTREE_FAM_OID);
 | 
								isIndexable = (opfamily == BYTEA_BTREE_FAM_OID);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
@@ -4097,7 +4094,8 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
			 Const *prefix_const, Pattern_Prefix_Status pstatus)
 | 
								 Const *prefix_const, Pattern_Prefix_Status pstatus)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	List	   *result;
 | 
						List	   *result;
 | 
				
			||||||
	Oid			datatype;
 | 
						Oid			ldatatype = exprType(leftop);
 | 
				
			||||||
 | 
						Oid			rdatatype;
 | 
				
			||||||
	Oid			oproid;
 | 
						Oid			oproid;
 | 
				
			||||||
	Expr	   *expr;
 | 
						Expr	   *expr;
 | 
				
			||||||
	FmgrInfo	ltproc;
 | 
						FmgrInfo	ltproc;
 | 
				
			||||||
@@ -4110,20 +4108,16 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
		case TEXT_BTREE_FAM_OID:
 | 
							case TEXT_BTREE_FAM_OID:
 | 
				
			||||||
		case TEXT_PATTERN_BTREE_FAM_OID:
 | 
							case TEXT_PATTERN_BTREE_FAM_OID:
 | 
				
			||||||
		case TEXT_SPGIST_FAM_OID:
 | 
							case TEXT_SPGIST_FAM_OID:
 | 
				
			||||||
			datatype = TEXTOID;
 | 
								rdatatype = TEXTOID;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case BPCHAR_BTREE_FAM_OID:
 | 
							case BPCHAR_BTREE_FAM_OID:
 | 
				
			||||||
		case BPCHAR_PATTERN_BTREE_FAM_OID:
 | 
							case BPCHAR_PATTERN_BTREE_FAM_OID:
 | 
				
			||||||
			datatype = BPCHAROID;
 | 
								rdatatype = BPCHAROID;
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case NAME_BTREE_FAM_OID:
 | 
					 | 
				
			||||||
			datatype = NAMEOID;
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case BYTEA_BTREE_FAM_OID:
 | 
							case BYTEA_BTREE_FAM_OID:
 | 
				
			||||||
			datatype = BYTEAOID;
 | 
								rdatatype = BYTEAOID;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
@@ -4136,7 +4130,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
	 * If necessary, coerce the prefix constant to the right type. The given
 | 
						 * If necessary, coerce the prefix constant to the right type. The given
 | 
				
			||||||
	 * prefix constant is either text or bytea type.
 | 
						 * prefix constant is either text or bytea type.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (prefix_const->consttype != datatype)
 | 
						if (prefix_const->consttype != rdatatype)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char	   *prefix;
 | 
							char	   *prefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4154,7 +4148,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
					 prefix_const->consttype);
 | 
										 prefix_const->consttype);
 | 
				
			||||||
				return NIL;
 | 
									return NIL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		prefix_const = string_to_const(prefix, datatype);
 | 
							prefix_const = string_to_const(prefix, rdatatype);
 | 
				
			||||||
		pfree(prefix);
 | 
							pfree(prefix);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4163,7 +4157,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (pstatus == Pattern_Prefix_Exact)
 | 
						if (pstatus == Pattern_Prefix_Exact)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		oproid = get_opfamily_member(opfamily, datatype, datatype,
 | 
							oproid = get_opfamily_member(opfamily, ldatatype, rdatatype,
 | 
				
			||||||
									 BTEqualStrategyNumber);
 | 
														 BTEqualStrategyNumber);
 | 
				
			||||||
		if (oproid == InvalidOid)
 | 
							if (oproid == InvalidOid)
 | 
				
			||||||
			elog(ERROR, "no = operator for opfamily %u", opfamily);
 | 
								elog(ERROR, "no = operator for opfamily %u", opfamily);
 | 
				
			||||||
@@ -4179,7 +4173,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * We can always say "x >= prefix".
 | 
						 * We can always say "x >= prefix".
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	oproid = get_opfamily_member(opfamily, datatype, datatype,
 | 
						oproid = get_opfamily_member(opfamily, ldatatype, rdatatype,
 | 
				
			||||||
								 BTGreaterEqualStrategyNumber);
 | 
													 BTGreaterEqualStrategyNumber);
 | 
				
			||||||
	if (oproid == InvalidOid)
 | 
						if (oproid == InvalidOid)
 | 
				
			||||||
		elog(ERROR, "no >= operator for opfamily %u", opfamily);
 | 
							elog(ERROR, "no >= operator for opfamily %u", opfamily);
 | 
				
			||||||
@@ -4196,7 +4190,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 | 
				
			|||||||
	 * using a C-locale index collation.
 | 
						 * using a C-locale index collation.
 | 
				
			||||||
	 *-------
 | 
						 *-------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	oproid = get_opfamily_member(opfamily, datatype, datatype,
 | 
						oproid = get_opfamily_member(opfamily, ldatatype, rdatatype,
 | 
				
			||||||
								 BTLessStrategyNumber);
 | 
													 BTLessStrategyNumber);
 | 
				
			||||||
	if (oproid == InvalidOid)
 | 
						if (oproid == InvalidOid)
 | 
				
			||||||
		elog(ERROR, "no < operator for opfamily %u", opfamily);
 | 
							elog(ERROR, "no < operator for opfamily %u", opfamily);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1292,14 +1292,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 | 
				
			|||||||
	switch (vartype)
 | 
						switch (vartype)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case TEXTOID:
 | 
							case TEXTOID:
 | 
				
			||||||
 | 
							case NAMEOID:
 | 
				
			||||||
			opfamily = TEXT_BTREE_FAM_OID;
 | 
								opfamily = TEXT_BTREE_FAM_OID;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case BPCHAROID:
 | 
							case BPCHAROID:
 | 
				
			||||||
			opfamily = BPCHAR_BTREE_FAM_OID;
 | 
								opfamily = BPCHAR_BTREE_FAM_OID;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NAMEOID:
 | 
					 | 
				
			||||||
			opfamily = NAME_BTREE_FAM_OID;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case BYTEAOID:
 | 
							case BYTEAOID:
 | 
				
			||||||
			opfamily = BYTEA_BTREE_FAM_OID;
 | 
								opfamily = BYTEA_BTREE_FAM_OID;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2693,6 +2693,167 @@ text_smaller(PG_FUNCTION_ARGS)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Cross-type comparison functions for types text and name.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					nameeqtext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Name		arg1 = PG_GETARG_NAME(0);
 | 
				
			||||||
 | 
						text	   *arg2 = PG_GETARG_TEXT_PP(1);
 | 
				
			||||||
 | 
						size_t		len1 = strlen(NameStr(*arg1));
 | 
				
			||||||
 | 
						size_t		len2 = VARSIZE_ANY_EXHDR(arg2);
 | 
				
			||||||
 | 
						bool		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = (len1 == len2 &&
 | 
				
			||||||
 | 
								  memcmp(NameStr(*arg1), VARDATA_ANY(arg2), len1) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg2, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					texteqname(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						text	   *arg1 = PG_GETARG_TEXT_PP(0);
 | 
				
			||||||
 | 
						Name		arg2 = PG_GETARG_NAME(1);
 | 
				
			||||||
 | 
						size_t		len1 = VARSIZE_ANY_EXHDR(arg1);
 | 
				
			||||||
 | 
						size_t		len2 = strlen(NameStr(*arg2));
 | 
				
			||||||
 | 
						bool		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = (len1 == len2 &&
 | 
				
			||||||
 | 
								  memcmp(VARDATA_ANY(arg1), NameStr(*arg2), len1) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					namenetext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Name		arg1 = PG_GETARG_NAME(0);
 | 
				
			||||||
 | 
						text	   *arg2 = PG_GETARG_TEXT_PP(1);
 | 
				
			||||||
 | 
						size_t		len1 = strlen(NameStr(*arg1));
 | 
				
			||||||
 | 
						size_t		len2 = VARSIZE_ANY_EXHDR(arg2);
 | 
				
			||||||
 | 
						bool		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = !(len1 == len2 &&
 | 
				
			||||||
 | 
								   memcmp(NameStr(*arg1), VARDATA_ANY(arg2), len1) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg2, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					textnename(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						text	   *arg1 = PG_GETARG_TEXT_PP(0);
 | 
				
			||||||
 | 
						Name		arg2 = PG_GETARG_NAME(1);
 | 
				
			||||||
 | 
						size_t		len1 = VARSIZE_ANY_EXHDR(arg1);
 | 
				
			||||||
 | 
						size_t		len2 = strlen(NameStr(*arg2));
 | 
				
			||||||
 | 
						bool		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = !(len1 == len2 &&
 | 
				
			||||||
 | 
								   memcmp(VARDATA_ANY(arg1), NameStr(*arg2), len1) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					btnametextcmp(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Name		arg1 = PG_GETARG_NAME(0);
 | 
				
			||||||
 | 
						text	   *arg2 = PG_GETARG_TEXT_PP(1);
 | 
				
			||||||
 | 
						int32		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
 | 
				
			||||||
 | 
											VARDATA_ANY(arg2), VARSIZE_ANY_EXHDR(arg2),
 | 
				
			||||||
 | 
											PG_GET_COLLATION());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg2, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_INT32(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					bttextnamecmp(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						text	   *arg1 = PG_GETARG_TEXT_PP(0);
 | 
				
			||||||
 | 
						Name		arg2 = PG_GETARG_NAME(1);
 | 
				
			||||||
 | 
						int32		result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result = varstr_cmp(VARDATA_ANY(arg1), VARSIZE_ANY_EXHDR(arg1),
 | 
				
			||||||
 | 
											NameStr(*arg2), strlen(NameStr(*arg2)),
 | 
				
			||||||
 | 
											PG_GET_COLLATION());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_FREE_IF_COPY(arg1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PG_RETURN_INT32(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CmpCall(cmpfunc) \
 | 
				
			||||||
 | 
						DatumGetInt32(DirectFunctionCall2Coll(cmpfunc, \
 | 
				
			||||||
 | 
															  PG_GET_COLLATION(), \
 | 
				
			||||||
 | 
															  PG_GETARG_DATUM(0), \
 | 
				
			||||||
 | 
															  PG_GETARG_DATUM(1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					namelttext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(btnametextcmp) < 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					nameletext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(btnametextcmp) <= 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					namegttext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(btnametextcmp) > 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					namegetext(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(btnametextcmp) >= 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					textltname(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(bttextnamecmp) < 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					textlename(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(bttextnamecmp) <= 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					textgtname(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(bttextnamecmp) > 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Datum
 | 
				
			||||||
 | 
					textgename(PG_FUNCTION_ARGS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PG_RETURN_BOOL(CmpCall(bttextnamecmp) >= 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef CmpCall
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The following operators support character-by-character comparison
 | 
					 * The following operators support character-by-character comparison
 | 
				
			||||||
 * of text datums, to allow building indexes suitable for LIKE clauses.
 | 
					 * of text datums, to allow building indexes suitable for LIKE clauses.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,6 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*							yyyymmddN */
 | 
					/*							yyyymmddN */
 | 
				
			||||||
#define CATALOG_VERSION_NO	201812191
 | 
					#define CATALOG_VERSION_NO	201812192
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -299,24 +299,6 @@
 | 
				
			|||||||
  amoprighttype => 'char', amopstrategy => '5', amopopr => '>(char,char)',
 | 
					  amoprighttype => 'char', amopstrategy => '5', amopopr => '>(char,char)',
 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# btree name_ops
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{ amopfamily => 'btree/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '1', amopopr => '<(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					 | 
				
			||||||
{ amopfamily => 'btree/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					 | 
				
			||||||
{ amopfamily => 'btree/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '3', amopopr => '=(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					 | 
				
			||||||
{ amopfamily => 'btree/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					 | 
				
			||||||
{ amopfamily => 'btree/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '5', amopopr => '>(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# btree text_ops
 | 
					# btree text_ops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
@@ -334,6 +316,51 @@
 | 
				
			|||||||
{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
  amoprighttype => 'text', amopstrategy => '5', amopopr => '>(text,text)',
 | 
					  amoprighttype => 'text', amopstrategy => '5', amopopr => '>(text,text)',
 | 
				
			||||||
  amopmethod => 'btree' },
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '1', amopopr => '<(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '3', amopopr => '=(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '5', amopopr => '>(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '1', amopopr => '<(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '2', amopopr => '<=(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '3', amopopr => '=(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '4', amopopr => '>=(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '5', amopopr => '>(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '1', amopopr => '<(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '3', amopopr => '=(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '5', amopopr => '>(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'btree' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# btree bpchar_ops
 | 
					# btree bpchar_ops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -925,11 +952,6 @@
 | 
				
			|||||||
  amoprighttype => 'macaddr8', amopstrategy => '1',
 | 
					  amoprighttype => 'macaddr8', amopstrategy => '1',
 | 
				
			||||||
  amopopr => '=(macaddr8,macaddr8)', amopmethod => 'hash' },
 | 
					  amopopr => '=(macaddr8,macaddr8)', amopmethod => 'hash' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# name_ops
 | 
					 | 
				
			||||||
{ amopfamily => 'hash/name_ops', amoplefttype => 'name',
 | 
					 | 
				
			||||||
  amoprighttype => 'name', amopstrategy => '1', amopopr => '=(name,name)',
 | 
					 | 
				
			||||||
  amopmethod => 'hash' },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# oid_ops
 | 
					# oid_ops
 | 
				
			||||||
{ amopfamily => 'hash/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
 | 
					{ amopfamily => 'hash/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
 | 
				
			||||||
  amopstrategy => '1', amopopr => '=(oid,oid)', amopmethod => 'hash' },
 | 
					  amopstrategy => '1', amopopr => '=(oid,oid)', amopmethod => 'hash' },
 | 
				
			||||||
@@ -943,6 +965,15 @@
 | 
				
			|||||||
{ amopfamily => 'hash/text_ops', amoplefttype => 'text',
 | 
					{ amopfamily => 'hash/text_ops', amoplefttype => 'text',
 | 
				
			||||||
  amoprighttype => 'text', amopstrategy => '1', amopopr => '=(text,text)',
 | 
					  amoprighttype => 'text', amopstrategy => '1', amopopr => '=(text,text)',
 | 
				
			||||||
  amopmethod => 'hash' },
 | 
					  amopmethod => 'hash' },
 | 
				
			||||||
 | 
					{ amopfamily => 'hash/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '1', amopopr => '=(name,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'hash' },
 | 
				
			||||||
 | 
					{ amopfamily => 'hash/text_ops', amoplefttype => 'name',
 | 
				
			||||||
 | 
					  amoprighttype => 'text', amopstrategy => '1', amopopr => '=(name,text)',
 | 
				
			||||||
 | 
					  amopmethod => 'hash' },
 | 
				
			||||||
 | 
					{ amopfamily => 'hash/text_ops', amoplefttype => 'text',
 | 
				
			||||||
 | 
					  amoprighttype => 'name', amopstrategy => '1', amopopr => '=(text,name)',
 | 
				
			||||||
 | 
					  amopmethod => 'hash' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# time_ops
 | 
					# time_ops
 | 
				
			||||||
{ amopfamily => 'hash/time_ops', amoplefttype => 'time',
 | 
					{ amopfamily => 'hash/time_ops', amoplefttype => 'time',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,10 +148,6 @@
 | 
				
			|||||||
{ amprocfamily => 'btree/macaddr_ops', amproclefttype => 'macaddr',
 | 
					{ amprocfamily => 'btree/macaddr_ops', amproclefttype => 'macaddr',
 | 
				
			||||||
  amprocrighttype => 'macaddr', amprocnum => '2',
 | 
					  amprocrighttype => 'macaddr', amprocnum => '2',
 | 
				
			||||||
  amproc => 'macaddr_sortsupport' },
 | 
					  amproc => 'macaddr_sortsupport' },
 | 
				
			||||||
{ amprocfamily => 'btree/name_ops', amproclefttype => 'name',
 | 
					 | 
				
			||||||
  amprocrighttype => 'name', amprocnum => '1', amproc => 'btnamecmp' },
 | 
					 | 
				
			||||||
{ amprocfamily => 'btree/name_ops', amproclefttype => 'name',
 | 
					 | 
				
			||||||
  amprocrighttype => 'name', amprocnum => '2', amproc => 'btnamesortsupport' },
 | 
					 | 
				
			||||||
{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
 | 
					{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
 | 
				
			||||||
  amprocrighttype => 'numeric', amprocnum => '1', amproc => 'numeric_cmp' },
 | 
					  amprocrighttype => 'numeric', amprocnum => '1', amproc => 'numeric_cmp' },
 | 
				
			||||||
{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
 | 
					{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
 | 
				
			||||||
@@ -171,6 +167,14 @@
 | 
				
			|||||||
  amprocrighttype => 'text', amprocnum => '1', amproc => 'bttextcmp' },
 | 
					  amprocrighttype => 'text', amprocnum => '1', amproc => 'bttextcmp' },
 | 
				
			||||||
{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
 | 
					{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
 | 
				
			||||||
  amprocrighttype => 'text', amprocnum => '2', amproc => 'bttextsortsupport' },
 | 
					  amprocrighttype => 'text', amprocnum => '2', amproc => 'bttextsortsupport' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
 | 
				
			||||||
 | 
					  amprocrighttype => 'name', amprocnum => '1', amproc => 'btnamecmp' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
 | 
				
			||||||
 | 
					  amprocrighttype => 'name', amprocnum => '2', amproc => 'btnamesortsupport' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
 | 
				
			||||||
 | 
					  amprocrighttype => 'text', amprocnum => '1', amproc => 'btnametextcmp' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
 | 
				
			||||||
 | 
					  amprocrighttype => 'name', amprocnum => '1', amproc => 'bttextnamecmp' },
 | 
				
			||||||
{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
 | 
					{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
 | 
				
			||||||
  amprocrighttype => 'time', amprocnum => '1', amproc => 'time_cmp' },
 | 
					  amprocrighttype => 'time', amprocnum => '1', amproc => 'time_cmp' },
 | 
				
			||||||
{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
 | 
					{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
 | 
				
			||||||
@@ -276,10 +280,6 @@
 | 
				
			|||||||
{ amprocfamily => 'hash/macaddr_ops', amproclefttype => 'macaddr',
 | 
					{ amprocfamily => 'hash/macaddr_ops', amproclefttype => 'macaddr',
 | 
				
			||||||
  amprocrighttype => 'macaddr', amprocnum => '2',
 | 
					  amprocrighttype => 'macaddr', amprocnum => '2',
 | 
				
			||||||
  amproc => 'hashmacaddrextended' },
 | 
					  amproc => 'hashmacaddrextended' },
 | 
				
			||||||
{ amprocfamily => 'hash/name_ops', amproclefttype => 'name',
 | 
					 | 
				
			||||||
  amprocrighttype => 'name', amprocnum => '1', amproc => 'hashname' },
 | 
					 | 
				
			||||||
{ amprocfamily => 'hash/name_ops', amproclefttype => 'name',
 | 
					 | 
				
			||||||
  amprocrighttype => 'name', amprocnum => '2', amproc => 'hashnameextended' },
 | 
					 | 
				
			||||||
{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
 | 
					{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
 | 
				
			||||||
  amprocrighttype => 'oid', amprocnum => '1', amproc => 'hashoid' },
 | 
					  amprocrighttype => 'oid', amprocnum => '1', amproc => 'hashoid' },
 | 
				
			||||||
{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
 | 
					{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
 | 
				
			||||||
@@ -293,6 +293,10 @@
 | 
				
			|||||||
  amprocrighttype => 'text', amprocnum => '1', amproc => 'hashtext' },
 | 
					  amprocrighttype => 'text', amprocnum => '1', amproc => 'hashtext' },
 | 
				
			||||||
{ amprocfamily => 'hash/text_ops', amproclefttype => 'text',
 | 
					{ amprocfamily => 'hash/text_ops', amproclefttype => 'text',
 | 
				
			||||||
  amprocrighttype => 'text', amprocnum => '2', amproc => 'hashtextextended' },
 | 
					  amprocrighttype => 'text', amprocnum => '2', amproc => 'hashtextextended' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'hash/text_ops', amproclefttype => 'name',
 | 
				
			||||||
 | 
					  amprocrighttype => 'name', amprocnum => '1', amproc => 'hashname' },
 | 
				
			||||||
 | 
					{ amprocfamily => 'hash/text_ops', amproclefttype => 'name',
 | 
				
			||||||
 | 
					  amprocrighttype => 'name', amprocnum => '2', amproc => 'hashnameextended' },
 | 
				
			||||||
{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
 | 
					{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
 | 
				
			||||||
  amprocrighttype => 'time', amprocnum => '1', amproc => 'time_hash' },
 | 
					  amprocrighttype => 'time', amprocnum => '1', amproc => 'time_hash' },
 | 
				
			||||||
{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
 | 
					{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,10 +93,10 @@
 | 
				
			|||||||
# but cstring and name are the same thing except for trailing padding,
 | 
					# but cstring and name are the same thing except for trailing padding,
 | 
				
			||||||
# and we can safely omit that within an index entry.  So we declare the
 | 
					# and we can safely omit that within an index entry.  So we declare the
 | 
				
			||||||
# btree opclass for name as using cstring storage type.
 | 
					# btree opclass for name as using cstring storage type.
 | 
				
			||||||
{ opcmethod => 'btree', opcname => 'name_ops', opcfamily => 'btree/name_ops',
 | 
					{ opcmethod => 'btree', opcname => 'name_ops', opcfamily => 'btree/text_ops',
 | 
				
			||||||
  opcintype => 'name', opckeytype => 'cstring' },
 | 
					  opcintype => 'name', opckeytype => 'cstring' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{ opcmethod => 'hash', opcname => 'name_ops', opcfamily => 'hash/name_ops',
 | 
					{ opcmethod => 'hash', opcname => 'name_ops', opcfamily => 'hash/text_ops',
 | 
				
			||||||
  opcintype => 'name' },
 | 
					  opcintype => 'name' },
 | 
				
			||||||
{ oid => '3125', oid_symbol => 'NUMERIC_BTREE_OPS_OID',
 | 
					{ oid => '3125', oid_symbol => 'NUMERIC_BTREE_OPS_OID',
 | 
				
			||||||
  opcmethod => 'btree', opcname => 'numeric_ops',
 | 
					  opcmethod => 'btree', opcname => 'numeric_ops',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,6 +107,65 @@
 | 
				
			|||||||
  oprcode => 'starts_with', oprrest => 'prefixsel',
 | 
					  oprcode => 'starts_with', oprrest => 'prefixsel',
 | 
				
			||||||
  oprjoin => 'prefixjoinsel' },
 | 
					  oprjoin => 'prefixjoinsel' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ oid => '254', descr => 'equal',
 | 
				
			||||||
 | 
					  oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'name',
 | 
				
			||||||
 | 
					  oprright => 'text', oprresult => 'bool', oprcom => '=(text,name)',
 | 
				
			||||||
 | 
					  oprnegate => '<>(name,text)', oprcode => 'nameeqtext', oprrest => 'eqsel',
 | 
				
			||||||
 | 
					  oprjoin => 'eqjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '255', descr => 'less than',
 | 
				
			||||||
 | 
					  oprname => '<', oprleft => 'name', oprright => 'text', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '>(text,name)', oprnegate => '>=(name,text)',
 | 
				
			||||||
 | 
					  oprcode => 'namelttext', oprrest => 'scalarltsel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalarltjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '256', descr => 'less than or equal',
 | 
				
			||||||
 | 
					  oprname => '<=', oprleft => 'name', oprright => 'text', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '>=(text,name)', oprnegate => '>(name,text)',
 | 
				
			||||||
 | 
					  oprcode => 'nameletext', oprrest => 'scalarlesel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalarlejoinsel' },
 | 
				
			||||||
 | 
					{ oid => '257', descr => 'greater than or equal',
 | 
				
			||||||
 | 
					  oprname => '>=', oprleft => 'name', oprright => 'text', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<=(text,name)', oprnegate => '<(name,text)',
 | 
				
			||||||
 | 
					  oprcode => 'namegetext', oprrest => 'scalargesel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalargejoinsel' },
 | 
				
			||||||
 | 
					{ oid => '258', descr => 'greater than',
 | 
				
			||||||
 | 
					  oprname => '>', oprleft => 'name', oprright => 'text', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<(text,name)', oprnegate => '<=(name,text)',
 | 
				
			||||||
 | 
					  oprcode => 'namegttext', oprrest => 'scalargtsel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalargtjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '259', descr => 'not equal',
 | 
				
			||||||
 | 
					  oprname => '<>', oprleft => 'name', oprright => 'text', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<>(text,name)', oprnegate => '=(name,text)',
 | 
				
			||||||
 | 
					  oprcode => 'namenetext', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '260', descr => 'equal',
 | 
				
			||||||
 | 
					  oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'text',
 | 
				
			||||||
 | 
					  oprright => 'name', oprresult => 'bool', oprcom => '=(name,text)',
 | 
				
			||||||
 | 
					  oprnegate => '<>(text,name)', oprcode => 'texteqname', oprrest => 'eqsel',
 | 
				
			||||||
 | 
					  oprjoin => 'eqjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '261', descr => 'less than',
 | 
				
			||||||
 | 
					  oprname => '<', oprleft => 'text', oprright => 'name', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '>(name,text)', oprnegate => '>=(text,name)',
 | 
				
			||||||
 | 
					  oprcode => 'textltname', oprrest => 'scalarltsel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalarltjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '262', descr => 'less than or equal',
 | 
				
			||||||
 | 
					  oprname => '<=', oprleft => 'text', oprright => 'name', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '>=(name,text)', oprnegate => '>(text,name)',
 | 
				
			||||||
 | 
					  oprcode => 'textlename', oprrest => 'scalarlesel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalarlejoinsel' },
 | 
				
			||||||
 | 
					{ oid => '263', descr => 'greater than or equal',
 | 
				
			||||||
 | 
					  oprname => '>=', oprleft => 'text', oprright => 'name', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<=(name,text)', oprnegate => '<(text,name)',
 | 
				
			||||||
 | 
					  oprcode => 'textgename', oprrest => 'scalargesel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalargejoinsel' },
 | 
				
			||||||
 | 
					{ oid => '264', descr => 'greater than',
 | 
				
			||||||
 | 
					  oprname => '>', oprleft => 'text', oprright => 'name', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<(name,text)', oprnegate => '<=(text,name)',
 | 
				
			||||||
 | 
					  oprcode => 'textgtname', oprrest => 'scalargtsel',
 | 
				
			||||||
 | 
					  oprjoin => 'scalargtjoinsel' },
 | 
				
			||||||
 | 
					{ oid => '265', descr => 'not equal',
 | 
				
			||||||
 | 
					  oprname => '<>', oprleft => 'text', oprright => 'name', oprresult => 'bool',
 | 
				
			||||||
 | 
					  oprcom => '<>(name,text)', oprnegate => '=(text,name)',
 | 
				
			||||||
 | 
					  oprcode => 'textnename', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{ oid => '349', descr => 'append element onto end of array',
 | 
					{ oid => '349', descr => 'append element onto end of array',
 | 
				
			||||||
  oprname => '||', oprleft => 'anyarray', oprright => 'anyelement',
 | 
					  oprname => '||', oprleft => 'anyarray', oprright => 'anyelement',
 | 
				
			||||||
  oprresult => 'anyarray', oprcode => 'array_append' },
 | 
					  oprresult => 'anyarray', oprcode => 'array_append' },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,10 +62,6 @@
 | 
				
			|||||||
  opfmethod => 'btree', opfname => 'macaddr8_ops' },
 | 
					  opfmethod => 'btree', opfname => 'macaddr8_ops' },
 | 
				
			||||||
{ oid => '3372',
 | 
					{ oid => '3372',
 | 
				
			||||||
  opfmethod => 'hash', opfname => 'macaddr8_ops' },
 | 
					  opfmethod => 'hash', opfname => 'macaddr8_ops' },
 | 
				
			||||||
{ oid => '1986', oid_symbol => 'NAME_BTREE_FAM_OID',
 | 
					 | 
				
			||||||
  opfmethod => 'btree', opfname => 'name_ops' },
 | 
					 | 
				
			||||||
{ oid => '1987',
 | 
					 | 
				
			||||||
  opfmethod => 'hash', opfname => 'name_ops' },
 | 
					 | 
				
			||||||
{ oid => '1988',
 | 
					{ oid => '1988',
 | 
				
			||||||
  opfmethod => 'btree', opfname => 'numeric_ops' },
 | 
					  opfmethod => 'btree', opfname => 'numeric_ops' },
 | 
				
			||||||
{ oid => '1998',
 | 
					{ oid => '1998',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -673,6 +673,49 @@
 | 
				
			|||||||
  proname => 'line_distance', prorettype => 'float8',
 | 
					  proname => 'line_distance', prorettype => 'float8',
 | 
				
			||||||
  proargtypes => 'line line', prosrc => 'line_distance' },
 | 
					  proargtypes => 'line line', prosrc => 'line_distance' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ oid => '240',
 | 
				
			||||||
 | 
					  proname => 'nameeqtext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'nameeqtext' },
 | 
				
			||||||
 | 
					{ oid => '241',
 | 
				
			||||||
 | 
					  proname => 'namelttext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'namelttext' },
 | 
				
			||||||
 | 
					{ oid => '242',
 | 
				
			||||||
 | 
					  proname => 'nameletext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'nameletext' },
 | 
				
			||||||
 | 
					{ oid => '243',
 | 
				
			||||||
 | 
					  proname => 'namegetext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'namegetext' },
 | 
				
			||||||
 | 
					{ oid => '244',
 | 
				
			||||||
 | 
					  proname => 'namegttext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'namegttext' },
 | 
				
			||||||
 | 
					{ oid => '245',
 | 
				
			||||||
 | 
					  proname => 'namenetext', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'namenetext' },
 | 
				
			||||||
 | 
					{ oid => '246', descr => 'less-equal-greater',
 | 
				
			||||||
 | 
					  proname => 'btnametextcmp', proleakproof => 't', prorettype => 'int4',
 | 
				
			||||||
 | 
					  proargtypes => 'name text', prosrc => 'btnametextcmp' },
 | 
				
			||||||
 | 
					{ oid => '247',
 | 
				
			||||||
 | 
					  proname => 'texteqname', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'texteqname' },
 | 
				
			||||||
 | 
					{ oid => '248',
 | 
				
			||||||
 | 
					  proname => 'textltname', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'textltname' },
 | 
				
			||||||
 | 
					{ oid => '249',
 | 
				
			||||||
 | 
					  proname => 'textlename', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'textlename' },
 | 
				
			||||||
 | 
					{ oid => '250',
 | 
				
			||||||
 | 
					  proname => 'textgename', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'textgename' },
 | 
				
			||||||
 | 
					{ oid => '251',
 | 
				
			||||||
 | 
					  proname => 'textgtname', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'textgtname' },
 | 
				
			||||||
 | 
					{ oid => '252',
 | 
				
			||||||
 | 
					  proname => 'textnename', proleakproof => 't', prorettype => 'bool',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'textnename' },
 | 
				
			||||||
 | 
					{ oid => '253', descr => 'less-equal-greater',
 | 
				
			||||||
 | 
					  proname => 'bttextnamecmp', proleakproof => 't', prorettype => 'int4',
 | 
				
			||||||
 | 
					  proargtypes => 'text name', prosrc => 'bttextnamecmp' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{ oid => '274',
 | 
					{ oid => '274',
 | 
				
			||||||
  descr => 'current date and time - increments during transactions',
 | 
					  descr => 'current date and time - increments during transactions',
 | 
				
			||||||
  proname => 'timeofday', provolatile => 'v', prorettype => 'text',
 | 
					  proname => 'timeofday', provolatile => 'v', prorettype => 'text',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -525,6 +525,20 @@ int24ge(smallint,integer)
 | 
				
			|||||||
int42ge(integer,smallint)
 | 
					int42ge(integer,smallint)
 | 
				
			||||||
oideq(oid,oid)
 | 
					oideq(oid,oid)
 | 
				
			||||||
oidne(oid,oid)
 | 
					oidne(oid,oid)
 | 
				
			||||||
 | 
					nameeqtext(name,text)
 | 
				
			||||||
 | 
					namelttext(name,text)
 | 
				
			||||||
 | 
					nameletext(name,text)
 | 
				
			||||||
 | 
					namegetext(name,text)
 | 
				
			||||||
 | 
					namegttext(name,text)
 | 
				
			||||||
 | 
					namenetext(name,text)
 | 
				
			||||||
 | 
					btnametextcmp(name,text)
 | 
				
			||||||
 | 
					texteqname(text,name)
 | 
				
			||||||
 | 
					textltname(text,name)
 | 
				
			||||||
 | 
					textlename(text,name)
 | 
				
			||||||
 | 
					textgename(text,name)
 | 
				
			||||||
 | 
					textgtname(text,name)
 | 
				
			||||||
 | 
					textnename(text,name)
 | 
				
			||||||
 | 
					bttextnamecmp(text,name)
 | 
				
			||||||
float4eq(real,real)
 | 
					float4eq(real,real)
 | 
				
			||||||
float4ne(real,real)
 | 
					float4ne(real,real)
 | 
				
			||||||
float4lt(real,real)
 | 
					float4lt(real,real)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -299,7 +299,7 @@ explain (costs off) select * from pg_proc where proname ~ '^abc';
 | 
				
			|||||||
                              QUERY PLAN                              
 | 
					                              QUERY PLAN                              
 | 
				
			||||||
----------------------------------------------------------------------
 | 
					----------------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: ((proname >= 'abc'::name) AND (proname < 'abd'::name))
 | 
					   Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
 | 
				
			||||||
   Filter: (proname ~ '^abc'::text)
 | 
					   Filter: (proname ~ '^abc'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -307,7 +307,7 @@ explain (costs off) select * from pg_proc where proname ~ '^abc$';
 | 
				
			|||||||
                         QUERY PLAN                         
 | 
					                         QUERY PLAN                         
 | 
				
			||||||
------------------------------------------------------------
 | 
					------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: (proname = 'abc'::name)
 | 
					   Index Cond: (proname = 'abc'::text)
 | 
				
			||||||
   Filter: (proname ~ '^abc$'::text)
 | 
					   Filter: (proname ~ '^abc$'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -315,7 +315,7 @@ explain (costs off) select * from pg_proc where proname ~ '^abcd*e';
 | 
				
			|||||||
                              QUERY PLAN                              
 | 
					                              QUERY PLAN                              
 | 
				
			||||||
----------------------------------------------------------------------
 | 
					----------------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: ((proname >= 'abc'::name) AND (proname < 'abd'::name))
 | 
					   Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
 | 
				
			||||||
   Filter: (proname ~ '^abcd*e'::text)
 | 
					   Filter: (proname ~ '^abcd*e'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -323,7 +323,7 @@ explain (costs off) select * from pg_proc where proname ~ '^abc+d';
 | 
				
			|||||||
                              QUERY PLAN                              
 | 
					                              QUERY PLAN                              
 | 
				
			||||||
----------------------------------------------------------------------
 | 
					----------------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: ((proname >= 'abc'::name) AND (proname < 'abd'::name))
 | 
					   Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
 | 
				
			||||||
   Filter: (proname ~ '^abc+d'::text)
 | 
					   Filter: (proname ~ '^abc+d'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -331,7 +331,7 @@ explain (costs off) select * from pg_proc where proname ~ '^(abc)(def)';
 | 
				
			|||||||
                                 QUERY PLAN                                 
 | 
					                                 QUERY PLAN                                 
 | 
				
			||||||
----------------------------------------------------------------------------
 | 
					----------------------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: ((proname >= 'abcdef'::name) AND (proname < 'abcdeg'::name))
 | 
					   Index Cond: ((proname >= 'abcdef'::text) AND (proname < 'abcdeg'::text))
 | 
				
			||||||
   Filter: (proname ~ '^(abc)(def)'::text)
 | 
					   Filter: (proname ~ '^(abc)(def)'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -339,7 +339,7 @@ explain (costs off) select * from pg_proc where proname ~ '^(abc)$';
 | 
				
			|||||||
                         QUERY PLAN                         
 | 
					                         QUERY PLAN                         
 | 
				
			||||||
------------------------------------------------------------
 | 
					------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: (proname = 'abc'::name)
 | 
					   Index Cond: (proname = 'abc'::text)
 | 
				
			||||||
   Filter: (proname ~ '^(abc)$'::text)
 | 
					   Filter: (proname ~ '^(abc)$'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -354,7 +354,7 @@ explain (costs off) select * from pg_proc where proname ~ '^abcd(x|(?=\w\w)q)';
 | 
				
			|||||||
                               QUERY PLAN                               
 | 
					                               QUERY PLAN                               
 | 
				
			||||||
------------------------------------------------------------------------
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
					 Index Scan using pg_proc_proname_args_nsp_index on pg_proc
 | 
				
			||||||
   Index Cond: ((proname >= 'abcd'::name) AND (proname < 'abce'::name))
 | 
					   Index Cond: ((proname >= 'abcd'::text) AND (proname < 'abce'::text))
 | 
				
			||||||
   Filter: (proname ~ '^abcd(x|(?=\w\w)q)'::text)
 | 
					   Filter: (proname ~ '^abcd(x|(?=\w\w)q)'::text)
 | 
				
			||||||
(3 rows)
 | 
					(3 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1326,10 +1326,10 @@ NOTICE:  f_leak => hamburger
 | 
				
			|||||||
(1 row)
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_property_normal WHERE f_leak(passwd);
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_property_normal WHERE f_leak(passwd);
 | 
				
			||||||
                          QUERY PLAN                          
 | 
					                      QUERY PLAN                      
 | 
				
			||||||
--------------------------------------------------------------
 | 
					------------------------------------------------------
 | 
				
			||||||
 Seq Scan on customer
 | 
					 Seq Scan on customer
 | 
				
			||||||
   Filter: (f_leak(passwd) AND (name = (CURRENT_USER)::text))
 | 
					   Filter: (f_leak(passwd) AND (name = CURRENT_USER))
 | 
				
			||||||
(2 rows)
 | 
					(2 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELECT * FROM my_property_secure WHERE f_leak(passwd);
 | 
					SELECT * FROM my_property_secure WHERE f_leak(passwd);
 | 
				
			||||||
@@ -1340,12 +1340,12 @@ NOTICE:  f_leak => passwd123
 | 
				
			|||||||
(1 row)
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_property_secure WHERE f_leak(passwd);
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_property_secure WHERE f_leak(passwd);
 | 
				
			||||||
                  QUERY PLAN                   
 | 
					                 QUERY PLAN                  
 | 
				
			||||||
-----------------------------------------------
 | 
					---------------------------------------------
 | 
				
			||||||
 Subquery Scan on my_property_secure
 | 
					 Subquery Scan on my_property_secure
 | 
				
			||||||
   Filter: f_leak(my_property_secure.passwd)
 | 
					   Filter: f_leak(my_property_secure.passwd)
 | 
				
			||||||
   ->  Seq Scan on customer
 | 
					   ->  Seq Scan on customer
 | 
				
			||||||
         Filter: (name = (CURRENT_USER)::text)
 | 
					         Filter: (name = CURRENT_USER)
 | 
				
			||||||
(4 rows)
 | 
					(4 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--
 | 
					--
 | 
				
			||||||
@@ -1367,10 +1367,10 @@ NOTICE:  f_leak => hamburger
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_property_normal v
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_property_normal v
 | 
				
			||||||
		WHERE f_leak('passwd') AND f_leak(passwd);
 | 
							WHERE f_leak('passwd') AND f_leak(passwd);
 | 
				
			||||||
                                       QUERY PLAN                                        
 | 
					                                   QUERY PLAN                                    
 | 
				
			||||||
-----------------------------------------------------------------------------------------
 | 
					---------------------------------------------------------------------------------
 | 
				
			||||||
 Seq Scan on customer
 | 
					 Seq Scan on customer
 | 
				
			||||||
   Filter: (f_leak('passwd'::text) AND f_leak(passwd) AND (name = (CURRENT_USER)::text))
 | 
					   Filter: (f_leak('passwd'::text) AND f_leak(passwd) AND (name = CURRENT_USER))
 | 
				
			||||||
(2 rows)
 | 
					(2 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELECT * FROM my_property_secure v
 | 
					SELECT * FROM my_property_secure v
 | 
				
			||||||
@@ -1386,12 +1386,12 @@ NOTICE:  f_leak => passwd
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_property_secure v
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_property_secure v
 | 
				
			||||||
		WHERE f_leak('passwd') AND f_leak(passwd);
 | 
							WHERE f_leak('passwd') AND f_leak(passwd);
 | 
				
			||||||
                                 QUERY PLAN                                 
 | 
					                             QUERY PLAN                             
 | 
				
			||||||
----------------------------------------------------------------------------
 | 
					--------------------------------------------------------------------
 | 
				
			||||||
 Subquery Scan on v
 | 
					 Subquery Scan on v
 | 
				
			||||||
   Filter: f_leak(v.passwd)
 | 
					   Filter: f_leak(v.passwd)
 | 
				
			||||||
   ->  Seq Scan on customer
 | 
					   ->  Seq Scan on customer
 | 
				
			||||||
         Filter: (f_leak('passwd'::text) AND (name = (CURRENT_USER)::text))
 | 
					         Filter: (f_leak('passwd'::text) AND (name = CURRENT_USER))
 | 
				
			||||||
(4 rows)
 | 
					(4 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--
 | 
					--
 | 
				
			||||||
@@ -1409,15 +1409,15 @@ NOTICE:  f_leak => 9801-2345-6789-0123
 | 
				
			|||||||
(1 row)
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_normal WHERE f_leak(cnum);
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_normal WHERE f_leak(cnum);
 | 
				
			||||||
                     QUERY PLAN                      
 | 
					                 QUERY PLAN                  
 | 
				
			||||||
-----------------------------------------------------
 | 
					---------------------------------------------
 | 
				
			||||||
 Hash Join
 | 
					 Hash Join
 | 
				
			||||||
   Hash Cond: (r.cid = l.cid)
 | 
					   Hash Cond: (r.cid = l.cid)
 | 
				
			||||||
   ->  Seq Scan on credit_card r
 | 
					   ->  Seq Scan on credit_card r
 | 
				
			||||||
         Filter: f_leak(cnum)
 | 
					         Filter: f_leak(cnum)
 | 
				
			||||||
   ->  Hash
 | 
					   ->  Hash
 | 
				
			||||||
         ->  Seq Scan on customer l
 | 
					         ->  Seq Scan on customer l
 | 
				
			||||||
               Filter: (name = (CURRENT_USER)::text)
 | 
					               Filter: (name = CURRENT_USER)
 | 
				
			||||||
(7 rows)
 | 
					(7 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELECT * FROM my_credit_card_secure WHERE f_leak(cnum);
 | 
					SELECT * FROM my_credit_card_secure WHERE f_leak(cnum);
 | 
				
			||||||
@@ -1428,8 +1428,8 @@ NOTICE:  f_leak => 1111-2222-3333-4444
 | 
				
			|||||||
(1 row)
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_secure WHERE f_leak(cnum);
 | 
					EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_secure WHERE f_leak(cnum);
 | 
				
			||||||
                        QUERY PLAN                         
 | 
					                    QUERY PLAN                     
 | 
				
			||||||
-----------------------------------------------------------
 | 
					---------------------------------------------------
 | 
				
			||||||
 Subquery Scan on my_credit_card_secure
 | 
					 Subquery Scan on my_credit_card_secure
 | 
				
			||||||
   Filter: f_leak(my_credit_card_secure.cnum)
 | 
					   Filter: f_leak(my_credit_card_secure.cnum)
 | 
				
			||||||
   ->  Hash Join
 | 
					   ->  Hash Join
 | 
				
			||||||
@@ -1437,7 +1437,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_secure WHERE f_leak(cnum);
 | 
				
			|||||||
         ->  Seq Scan on credit_card r
 | 
					         ->  Seq Scan on credit_card r
 | 
				
			||||||
         ->  Hash
 | 
					         ->  Hash
 | 
				
			||||||
               ->  Seq Scan on customer l
 | 
					               ->  Seq Scan on customer l
 | 
				
			||||||
                     Filter: (name = (CURRENT_USER)::text)
 | 
					                     Filter: (name = CURRENT_USER)
 | 
				
			||||||
(8 rows)
 | 
					(8 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--
 | 
					--
 | 
				
			||||||
@@ -1471,7 +1471,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_usage_normal
 | 
				
			|||||||
                     ->  Seq Scan on credit_card r_1
 | 
					                     ->  Seq Scan on credit_card r_1
 | 
				
			||||||
                     ->  Hash
 | 
					                     ->  Hash
 | 
				
			||||||
                           ->  Seq Scan on customer l_1
 | 
					                           ->  Seq Scan on customer l_1
 | 
				
			||||||
                                 Filter: (name = (CURRENT_USER)::text)
 | 
					                                 Filter: (name = CURRENT_USER)
 | 
				
			||||||
(13 rows)
 | 
					(13 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELECT * FROM my_credit_card_usage_secure
 | 
					SELECT * FROM my_credit_card_usage_secure
 | 
				
			||||||
@@ -1502,7 +1502,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM my_credit_card_usage_secure
 | 
				
			|||||||
                     ->  Seq Scan on credit_card r_1
 | 
					                     ->  Seq Scan on credit_card r_1
 | 
				
			||||||
                     ->  Hash
 | 
					                     ->  Hash
 | 
				
			||||||
                           ->  Seq Scan on customer l
 | 
					                           ->  Seq Scan on customer l
 | 
				
			||||||
                                 Filter: (name = (CURRENT_USER)::text)
 | 
					                                 Filter: (name = CURRENT_USER)
 | 
				
			||||||
(13 rows)
 | 
					(13 rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--
 | 
					--
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user