diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index e271ae5..0a4ffa8 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -163,15 +163,22 @@ typedef struct					/* cast_hash table entry */
 	plpgsql_CastHashKey key;	/* hash key --- MUST BE FIRST */
 	Expr	   *cast_expr;		/* cast expression, or NULL if no-op cast */
 	CachedExpression *cast_cexpr;	/* cached expression backing the above */
+} plpgsql_SessionCastHashEntry;
+
+typedef struct
+{
+	plpgsql_CastHashKey key;	/* hash key --- MUST BE FIRST */
 	/* ExprState is valid only when cast_lxid matches current LXID */
 	ExprState  *cast_exprstate; /* expression's eval tree */
 	bool		cast_in_use;	/* true while we're executing eval tree */
 	LocalTransactionId cast_lxid;
-} plpgsql_CastHashEntry;
+} plpgsql_PrivateCastHashEntry;
 
-static MemoryContext shared_cast_context = NULL;
-static HTAB *shared_cast_hash = NULL;
+static MemoryContext shared_cast_upper_context = NULL;
+static HTAB *shared_cast_upper_hash = NULL;
 
+static MemoryContext shared_cast_lower_context = NULL;
+static HTAB *shared_cast_lower_hash = NULL;
 /*
  * LOOP_RC_PROCESSING encapsulates common logic for looping statements to
  * handle return/exit/continue result codes from the loop body statement(s).
@@ -422,9 +429,9 @@ static Datum do_cast_value(PLpgSQL_execstate *estate,
 						   Datum value, bool *isnull,
 						   Oid valtype, int32 valtypmod,
 						   Oid reqtype, int32 reqtypmod);
-static plpgsql_CastHashEntry *get_cast_hashentry(PLpgSQL_execstate *estate,
-												 Oid srctype, int32 srctypmod,
-												 Oid dsttype, int32 dsttypmod);
+static plpgsql_PrivateCastHashEntry * get_cast_hashentry(PLpgSQL_execstate *estate,
+														 Oid srctype, int32 srctypmod,
+														 Oid dsttype, int32 dsttypmod);
 static void exec_init_tuple_store(PLpgSQL_execstate *estate);
 static void exec_set_found(PLpgSQL_execstate *estate, bool state);
 static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
@@ -4031,7 +4038,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
 		estate->simple_eval_estate = simple_eval_estate;
 		/* Private cast hash just lives in function's main context */
 		ctl.keysize = sizeof(plpgsql_CastHashKey);
-		ctl.entrysize = sizeof(plpgsql_CastHashEntry);
+		ctl.entrysize = sizeof(plpgsql_PrivateCastHashEntry);
 		ctl.hcxt = CurrentMemoryContext;
 		estate->cast_hash = hash_create("PLpgSQL private cast cache",
 										16, /* start small and extend */
@@ -4042,23 +4049,42 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
 	else
 	{
 		estate->simple_eval_estate = shared_simple_eval_estate;
-		/* Create the session-wide cast-info hash table if we didn't already */
-		if (shared_cast_hash == NULL)
+		if (shared_cast_upper_hash == NULL)
 		{
-			shared_cast_context = AllocSetContextCreate(TopMemoryContext,
-														"PLpgSQL cast info",
-														ALLOCSET_DEFAULT_SIZES);
+			shared_cast_upper_context = AllocSetContextCreate(TopMemoryContext,
+															  "SPL cast upper info",
+															  ALLOCSET_DEFAULT_SIZES);
 			ctl.keysize = sizeof(plpgsql_CastHashKey);
-			ctl.entrysize = sizeof(plpgsql_CastHashEntry);
-			ctl.hcxt = shared_cast_context;
-			shared_cast_hash = hash_create("PLpgSQL cast cache",
-										   16,	/* start small and extend */
-										   &ctl,
-										   HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+			ctl.entrysize = sizeof(plpgsql_PrivateCastHashEntry);
+			ctl.hcxt = shared_cast_upper_context;
+			shared_cast_upper_hash = hash_create("PLpgSQL private cast cache",
+												 16, /* start small and extend */
+												 &ctl,
+												 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
 		}
-		estate->cast_hash = shared_cast_hash;
-		estate->cast_hash_context = shared_cast_context;
+		estate->cast_hash_context = shared_cast_upper_context;
+		estate->cast_hash = shared_cast_upper_hash;
+	}
+
+
+	/* Create the session-wide cast-info hash table if we didn't already */
+	if (shared_cast_lower_hash == NULL)
+	{
+		shared_cast_lower_context = AllocSetContextCreate(TopMemoryContext,
+														  "PLpgSQL cast info",
+														  ALLOCSET_DEFAULT_SIZES);
+		ctl.keysize = sizeof(plpgsql_CastHashKey);
+		ctl.entrysize = sizeof(plpgsql_SessionCastHashEntry);
+		ctl.hcxt = shared_cast_lower_context;
+		shared_cast_lower_hash = hash_create("PLpgSQL cast cache",
+											 16,	/* start small and extend */
+											 &ctl,
+											 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 	}
+	estate->shared_cast_hash = shared_cast_lower_hash;
+	estate->shared_cast_hash_context = shared_cast_lower_context;
+
 	/* likewise for the simple-expression resource owner */
 	if (simple_eval_resowner)
 		estate->simple_eval_resowner = simple_eval_resowner;
@@ -7723,7 +7749,7 @@ do_cast_value(PLpgSQL_execstate *estate,
 			  Oid valtype, int32 valtypmod,
 			  Oid reqtype, int32 reqtypmod)
 {
-	plpgsql_CastHashEntry *cast_entry;
+	plpgsql_PrivateCastHashEntry *cast_entry;
 
 	cast_entry = get_cast_hashentry(estate,
 									valtype, valtypmod,
@@ -7761,13 +7787,15 @@ do_cast_value(PLpgSQL_execstate *estate,
  * true while executing it.
  * ----------
  */
-static plpgsql_CastHashEntry *
+static plpgsql_PrivateCastHashEntry *
 get_cast_hashentry(PLpgSQL_execstate *estate,
 				   Oid srctype, int32 srctypmod,
 				   Oid dsttype, int32 dsttypmod)
 {
 	plpgsql_CastHashKey cast_key;
-	plpgsql_CastHashEntry *cast_entry;
+	plpgsql_PrivateCastHashEntry *private_cast_entry;
+	plpgsql_SessionCastHashEntry *cast_entry;
+
 	bool		found;
 	LocalTransactionId curlxid;
 	MemoryContext oldcontext;
@@ -7777,9 +7805,9 @@ get_cast_hashentry(PLpgSQL_execstate *estate,
 	cast_key.dsttype = dsttype;
 	cast_key.srctypmod = srctypmod;
 	cast_key.dsttypmod = dsttypmod;
-	cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
-													   &cast_key,
-													   HASH_ENTER, &found);
+	cast_entry = (plpgsql_SessionCastHashEntry *) hash_search(estate->shared_cast_hash,
+															  &cast_key,
+															  HASH_ENTER, &found);
 	if (!found)					/* initialize if new entry */
 		cast_entry->cast_cexpr = NULL;
 
@@ -7884,10 +7912,6 @@ get_cast_hashentry(PLpgSQL_execstate *estate,
 		/* Now we can fill in the hashtable entry. */
 		cast_entry->cast_cexpr = cast_cexpr;
 		cast_entry->cast_expr = (Expr *) cast_expr;
-		cast_entry->cast_exprstate = NULL;
-		cast_entry->cast_in_use = false;
-		cast_entry->cast_lxid = InvalidLocalTransactionId;
-
 		MemoryContextSwitchTo(oldcontext);
 	}
 
@@ -7895,6 +7919,18 @@ get_cast_hashentry(PLpgSQL_execstate *estate,
 	if (cast_entry->cast_expr == NULL)
 		return NULL;
 
+
+	private_cast_entry = (plpgsql_PrivateCastHashEntry *) hash_search(estate->cast_hash,
+																	  &cast_key,
+																	  HASH_ENTER, &found);
+
+	if (!found)
+	{
+		private_cast_entry->cast_exprstate = NULL;
+		private_cast_entry->cast_in_use = false;
+		private_cast_entry->cast_lxid = InvalidLocalTransactionId;
+	}
+
 	/*
 	 * Prepare the expression for execution, if it's not been done already in
 	 * the current transaction; also, if it's marked busy in the current
@@ -7908,16 +7944,16 @@ get_cast_hashentry(PLpgSQL_execstate *estate,
 	 * cast hash tables to go with them.)
 	 */
 	curlxid = MyProc->lxid;
-	if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
+	if (private_cast_entry->cast_lxid != curlxid || private_cast_entry->cast_in_use)
 	{
 		oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
-		cast_entry->cast_exprstate = ExecInitExpr(cast_entry->cast_expr, NULL);
-		cast_entry->cast_in_use = false;
-		cast_entry->cast_lxid = curlxid;
+		private_cast_entry->cast_exprstate = ExecInitExpr(cast_entry->cast_expr, NULL);
+		private_cast_entry->cast_in_use = false;
+		private_cast_entry->cast_lxid = curlxid;
 		MemoryContextSwitchTo(oldcontext);
 	}
 
-	return cast_entry;
+	return private_cast_entry;
 }
 
 
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index c40471b..765bb9e 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -1074,10 +1074,14 @@ typedef struct PLpgSQL_execstate
 	/* if running nonatomic procedure or DO block, resowner to use for CALL */
 	ResourceOwner procedure_resowner;
 
-	/* lookup table to use for executing type casts */
+	/* lookup local table to use for executing type casts */
 	HTAB	   *cast_hash;
 	MemoryContext cast_hash_context;
 
+	/* look Session table to use for executing type casts */
+	HTAB	   *shared_cast_hash;
+	MemoryContext shared_cast_hash_context;
+
 	/* memory context for statement-lifespan temporary values */
 	MemoryContext stmt_mcontext;	/* current stmt context, or NULL if none */
 	MemoryContext stmt_mcontext_parent; /* parent of current context */
