diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 743e7d6..81aa0b8 100644
*** a/src/backend/executor/execQual.c
--- b/src/backend/executor/execQual.c
***************
*** 44,49 ****
--- 44,50 ----
  #include "executor/execdebug.h"
  #include "executor/nodeSubplan.h"
  #include "funcapi.h"
+ #include "mb/pg_wchar.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
  #include "nodes/nodeFuncs.h"
***************
*** 51,56 ****
--- 52,58 ----
  #include "parser/parse_coerce.h"
  #include "parser/parsetree.h"
  #include "pgstat.h"
+ #include "tcop/tcopprot.h"
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/date.h"
*************** restart:
*** 1772,1777 ****
--- 1774,1782 ----
  		fcache->setArgsValid = false;
  	}
  
+ 	/* Treat function as active beginning here */
+ 	econtext->cur_expr = (ExprState *) fcache;
+ 
  	/*
  	 * Now call the function, passing the evaluated parameter values.
  	 */
*************** restart:
*** 1969,1974 ****
--- 1974,1980 ----
  				if (fcinfo->argnull[i])
  				{
  					*isNull = true;
+ 					econtext->cur_expr = NULL;
  					return (Datum) 0;
  				}
  			}
*************** restart:
*** 1983,1988 ****
--- 1989,1996 ----
  		pgstat_end_function_usage(&fcusage, true);
  	}
  
+ 	econtext->cur_expr = NULL;
+ 
  	return result;
  }
  
*************** ExecMakeFunctionResultNoSets(FuncExprSta
*** 2040,2045 ****
--- 2048,2056 ----
  		}
  	}
  
+ 	/* Treat function as active beginning here */
+ 	econtext->cur_expr = (ExprState *) fcache;
+ 
  	pgstat_init_function_usage(fcinfo, &fcusage);
  
  	fcinfo->isnull = false;
*************** ExecMakeFunctionResultNoSets(FuncExprSta
*** 2048,2053 ****
--- 2059,2066 ----
  
  	pgstat_end_function_usage(&fcusage, true);
  
+ 	econtext->cur_expr = NULL;
+ 
  	return result;
  }
  
*************** ExecPrepareExpr(Expr *node, EState *esta
*** 5309,5314 ****
--- 5322,5350 ----
   * ----------------------------------------------------------------
   */
  
+ static void
+ ExprErrorCallback(void *arg)
+ {
+ 	ExprContext *econtext = (ExprContext *) arg;
+ 
+ 	if (econtext->cur_expr)
+ 	{
+ 		int			location = exprLocation((Node *) econtext->cur_expr->expr);
+ 		int			pos;
+ 
+ 		/* No-op if location was not provided */
+ 		if (location < 0)
+ 			return;
+ 		/* Can't do anything if source text is not available */
+ 		if (debug_query_string == NULL)
+ 			return;
+ 		/* Convert offset to character number */
+ 		pos = pg_mbstrlen_with_len(debug_query_string, location) + 1;
+ 		/* And pass it to the ereport mechanism */
+ 		errposition(pos);
+ 	}
+ }
+ 
  /* ----------------------------------------------------------------
   *		ExecQual
   *
*************** bool
*** 5341,5346 ****
--- 5377,5383 ----
  ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
  {
  	bool		result;
+ 	ErrorContextCallback errcallback;
  	MemoryContext oldContext;
  	ListCell   *l;
  
*************** ExecQual(List *qual, ExprContext *econte
*** 5351,5356 ****
--- 5388,5400 ----
  	EV_nodeDisplay(qual);
  	EV_printf("\n");
  
+ 	/* Setup error traceback support for ereport() */
+ 	econtext->cur_expr = NULL;
+ 	errcallback.callback = ExprErrorCallback;
+ 	errcallback.arg = (void *) econtext;
+ 	errcallback.previous = error_context_stack;
+ 	error_context_stack = &errcallback;
+ 
  	/*
  	 * Run in short-lived per-tuple context while computing expressions.
  	 */
*************** ExecQual(List *qual, ExprContext *econte
*** 5398,5403 ****
--- 5442,5449 ----
  
  	MemoryContextSwitchTo(oldContext);
  
+ 	error_context_stack = errcallback.previous;
+ 
  	return result;
  }
  
*************** ExecTargetList(List *targetlist,
*** 5463,5472 ****
--- 5509,5526 ----
  			   ExprDoneCond *isDone)
  {
  	Form_pg_attribute *att = tupdesc->attrs;
+ 	ErrorContextCallback errcallback;
  	MemoryContext oldContext;
  	ListCell   *tl;
  	bool		haveDoneSets;
  
+ 	/* Setup error traceback support for ereport() */
+ 	econtext->cur_expr = NULL;
+ 	errcallback.callback = ExprErrorCallback;
+ 	errcallback.arg = (void *) econtext;
+ 	errcallback.previous = error_context_stack;
+ 	error_context_stack = &errcallback;
+ 
  	/*
  	 * Run in short-lived per-tuple context while computing expressions.
  	 */
*************** ExecTargetList(List *targetlist,
*** 5524,5529 ****
--- 5578,5584 ----
  			 */
  			*isDone = ExprEndResult;
  			MemoryContextSwitchTo(oldContext);
+ 			error_context_stack = errcallback.previous;
  			return false;
  		}
  		else
*************** ExecTargetList(List *targetlist,
*** 5587,5592 ****
--- 5642,5648 ----
  				}
  
  				MemoryContextSwitchTo(oldContext);
+ 				error_context_stack = errcallback.previous;
  				return false;
  			}
  		}
*************** ExecTargetList(List *targetlist,
*** 5595,5600 ****
--- 5651,5658 ----
  	/* Report success */
  	MemoryContextSwitchTo(oldContext);
  
+ 	error_context_stack = errcallback.previous;
+ 
  	return true;
  }
  
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5616,5621 ****
--- 5674,5680 ----
  {
  	TupleTableSlot *slot;
  	ExprContext *econtext;
+ 	ErrorContextCallback errcallback;
  	int			numSimpleVars;
  
  	/*
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5629,5634 ****
--- 5688,5700 ----
  	slot = projInfo->pi_slot;
  	econtext = projInfo->pi_exprContext;
  
+ 	/* Setup error traceback support for ereport() */
+ 	econtext->cur_expr = NULL;
+ 	errcallback.callback = ExprErrorCallback;
+ 	errcallback.arg = (void *) econtext;
+ 	errcallback.previous = error_context_stack;
+ 	error_context_stack = &errcallback;
+ 
  	/* Assume single result row until proven otherwise */
  	if (isDone)
  		*isDone = ExprSingleResult;
*************** ExecProject(ProjectionInfo *projInfo, Ex
*** 5714,5722 ****
--- 5780,5793 ----
  							slot->tts_isnull,
  							projInfo->pi_itemIsDone,
  							isDone))
+ 		{
+ 			error_context_stack = errcallback.previous;
  			return slot;		/* no more result rows, return empty slot */
+ 		}
  	}
  
+ 	error_context_stack = errcallback.previous;
+ 
  	/*
  	 * Successfully formed a result row.  Mark the result slot as containing a
  	 * valid virtual tuple.
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 1688310..583cf43 100644
*** a/src/backend/optimizer/util/clauses.c
--- b/src/backend/optimizer/util/clauses.c
***************
*** 29,34 ****
--- 29,35 ----
  #include "executor/executor.h"
  #include "executor/functions.h"
  #include "funcapi.h"
+ #include "mb/pg_wchar.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
  #include "nodes/nodeFuncs.h"
*************** sql_inline_error_callback(void *arg)
*** 4698,4703 ****
--- 4699,4727 ----
  	errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
  }
  
+ static void
+ ExprErrorCallback(void *arg)
+ {
+ 	ExprContext *econtext = (ExprContext *) arg;
+ 
+ 	if (econtext->cur_expr)
+ 	{
+ 		int			location = exprLocation((Node *) econtext->cur_expr->expr);
+ 		int			pos;
+ 
+ 		/* No-op if location was not provided */
+ 		if (location < 0)
+ 			return;
+ 		/* Can't do anything if source text is not available */
+ 		if (debug_query_string == NULL)
+ 			return;
+ 		/* Convert offset to character number */
+ 		pos = pg_mbstrlen_with_len(debug_query_string, location) + 1;
+ 		/* And pass it to the ereport mechanism */
+ 		errposition(pos);
+ 	}
+ }
+ 
  /*
   * evaluate_expr: pre-evaluate a constant expression
   *
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4710,4715 ****
--- 4734,4741 ----
  {
  	EState	   *estate;
  	ExprState  *exprstate;
+ 	ExprContext *econtext;
+ 	ErrorContextCallback errcallback;
  	MemoryContext oldcontext;
  	Datum		const_val;
  	bool		const_is_null;
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4733,4738 ****
--- 4759,4772 ----
  	 */
  	exprstate = ExecInitExpr(expr, NULL);
  
+ 	/* Setup error traceback support for ereport() */
+ 	econtext = GetPerTupleExprContext(estate);
+ 	econtext->cur_expr = NULL;
+ 	errcallback.callback = ExprErrorCallback;
+ 	errcallback.arg = (void *) econtext;
+ 	errcallback.previous = error_context_stack;
+ 	error_context_stack = &errcallback;
+ 
  	/*
  	 * And evaluate it.
  	 *
*************** evaluate_expr(Expr *expr, Oid result_typ
*** 4742,4750 ****
  	 * not depend on context, by definition, n'est ce pas?
  	 */
  	const_val = ExecEvalExprSwitchContext(exprstate,
! 										  GetPerTupleExprContext(estate),
  										  &const_is_null, NULL);
  
  	/* Get info needed about result datatype */
  	get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
  
--- 4776,4786 ----
  	 * not depend on context, by definition, n'est ce pas?
  	 */
  	const_val = ExecEvalExprSwitchContext(exprstate,
! 										  econtext,
  										  &const_is_null, NULL);
  
+ 	error_context_stack = errcallback.previous;
+ 
  	/* Get info needed about result datatype */
  	get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
  
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f6f73f3..a390206 100644
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
*************** typedef struct ExprContext
*** 147,152 ****
--- 147,155 ----
  	Datum		domainValue_datum;
  	bool		domainValue_isNull;
  
+ 	/* Currently executing expression node state, or NULL if indeterminate */
+ 	struct ExprState *cur_expr;
+ 
  	/* Link to containing EState (NULL if a standalone ExprContext) */
  	struct EState *ecxt_estate;
  
