pg_stat_statements_norm_v5.patch
text/x-patch
Filename: pg_stat_statements_norm_v5.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v5
| File | + | − |
|---|---|---|
| contrib/pg_stat_statements/pg_stat_statements.c | 0 | 0 |
| src/backend/catalog/heap.c | 0 | 0 |
| src/backend/commands/prepare.c | 0 | 0 |
| src/backend/commands/tablecmds.c | 0 | 0 |
| src/backend/nodes/copyfuncs.c | 0 | 0 |
| src/backend/parser/gram.y | 0 | 0 |
| src/backend/parser/parse_clause.c | 0 | 0 |
| src/backend/parser/parse_coerce.c | 0 | 0 |
| src/backend/parser/parse_expr.c | 0 | 0 |
| src/backend/parser/parse_func.c | 0 | 0 |
| src/backend/parser/parse_node.c | 0 | 0 |
| src/backend/parser/parse_target.c | 0 | 0 |
| src/backend/parser/scan.l | 0 | 0 |
| src/backend/rewrite/rewriteHandler.c | 0 | 0 |
| src/include/nodes/parsenodes.h | 0 | 0 |
| src/include/nodes/primnodes.h | 0 | 0 |
| src/include/parser/parse_coerce.h | 0 | 0 |
| src/include/parser/parse_node.h | 0 | 0 |
| src/include/parser/scanner.h | 0 | 0 |
| src/pl/plpgsql/src/gram.y | 0 | 0 |
| src/pl/plpgsql/src/pl_scanner.c | 0 | 0 |
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 8dc3054..72a030f 100644
*** a/contrib/pg_stat_statements/pg_stat_statements.c
--- b/contrib/pg_stat_statements/pg_stat_statements.c
***************
*** 10,15 ****
--- 10,25 ----
* an entry, one must hold the lock shared or exclusive (so the entry doesn't
* disappear!) and also take the entry's mutex spinlock.
*
+ * Statements go through a normalization process before being stored.
+ * Normalization is ignoring components of the query that don't normally
+ * differentiate it for the purposes of isolating poorly performing queries.
+ * For example, the statements 'SELECT * FROM t WHERE f=1' and
+ * 'SELECT * FROM t WHERE f=2' would both be considered equivalent after
+ * normalization. This is implemented by generating a series of integers
+ * from the query tree after the re-write stage, into a "query jumble". A
+ * query jumble is distinct from a straight serialization of the query tree in
+ * that Constants are canonicalized, and various extraneous information is
+ * ignored, such as the collation of Vars.
*
* Copyright (c) 2008-2011, PostgreSQL Global Development Group
*
***************
*** 27,38 ****
--- 37,51 ----
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
+ #include "optimizer/planner.h"
+ #include "parser/parsetree.h"
#include "pgstat.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/spin.h"
#include "tcop/utility.h"
#include "utils/builtins.h"
+ #include "utils/memutils.h"
PG_MODULE_MAGIC;
*************** static const uint32 PGSS_FILE_HEADER = 0
*** 48,53 ****
--- 61,70 ----
#define USAGE_INIT (1.0) /* including initial planning */
#define USAGE_DECREASE_FACTOR (0.99) /* decreased every entry_dealloc */
#define USAGE_DEALLOC_PERCENT 5 /* free this % of entries at once */
+ #define JUMBLE_SIZE 1024 /* query serialization buffer size */
+ /* Magic values */
+ #define HASH_BUF (0xFA) /* buffer is a hash of query tree */
+ #define STR_BUF (0xEB) /* buffer is query string itself */
/*
* Hashtable key that defines the identity of a hashtable entry. The
*************** typedef struct pgssHashKey
*** 63,70 ****
Oid userid; /* user OID */
Oid dbid; /* database OID */
int encoding; /* query encoding */
! int query_len; /* # of valid bytes in query string */
! const char *query_ptr; /* query string proper */
} pgssHashKey;
/*
--- 80,86 ----
Oid userid; /* user OID */
Oid dbid; /* database OID */
int encoding; /* query encoding */
! char jumble[JUMBLE_SIZE]; /* Integers from a query tree */
} pgssHashKey;
/*
*************** typedef struct pgssEntry
*** 95,100 ****
--- 111,117 ----
{
pgssHashKey key; /* hash key of entry - MUST BE FIRST */
Counters counters; /* the statistics for this query */
+ int query_len; /* # of valid bytes in query string */
slock_t mutex; /* protects the counters only */
char query[1]; /* VARIABLE LENGTH ARRAY - MUST BE LAST */
/* Note: the allocated length of query[] is actually pgss->query_size */
*************** typedef struct pgssSharedState
*** 109,116 ****
int query_size; /* max query length in bytes */
} pgssSharedState;
! /*---- Local variables ----*/
/* Current nesting depth of ExecutorRun calls */
static int nested_level = 0;
--- 126,146 ----
int query_size; /* max query length in bytes */
} pgssSharedState;
! typedef struct pgssTokenOffset
! {
! int offset; /* token offset in query string in bytes */
! int len; /* length of token in bytes */
! } pgssTokenOffset;
+ /*---- Local variables ----*/
+ /* Jumble of last query tree seen by pgss_PlannerRun */
+ static char *last_jumble = NULL;
+ /* Ptr to buffer that represents position of normalized characters */
+ static pgssTokenOffset *last_offsets = NULL;
+ /* Current Length of last_offsets buffer */
+ static size_t last_offset_buf_size = 10;
+ /* Current number of actual offsets stored in last_offsets */
+ static size_t last_offset_num = 0;
/* Current nesting depth of ExecutorRun calls */
static int nested_level = 0;
*************** static ExecutorRun_hook_type prev_Execut
*** 121,126 ****
--- 151,157 ----
static ExecutorFinish_hook_type prev_ExecutorFinish = NULL;
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
static ProcessUtility_hook_type prev_ProcessUtility = NULL;
+ static planner_hook_type prev_Planner = NULL;
/* Links to shared memory state */
static pgssSharedState *pgss = NULL;
*************** static int pgss_max; /* max # statemen
*** 147,153 ****
static int pgss_track; /* tracking level */
static bool pgss_track_utility; /* whether to track utility commands */
static bool pgss_save; /* whether to save stats across shutdown */
!
#define pgss_enabled() \
(pgss_track == PGSS_TRACK_ALL || \
--- 178,184 ----
static int pgss_track; /* tracking level */
static bool pgss_track_utility; /* whether to track utility commands */
static bool pgss_save; /* whether to save stats across shutdown */
! static bool pgss_string_key; /* whether to always only hash query str */
#define pgss_enabled() \
(pgss_track == PGSS_TRACK_ALL || \
*************** PG_FUNCTION_INFO_V1(pg_stat_statements);
*** 166,171 ****
--- 197,212 ----
static void pgss_shmem_startup(void);
static void pgss_shmem_shutdown(int code, Datum arg);
+ static PlannedStmt *pgss_PlannerRun(Query *parse, int cursorOptions, ParamListInfo boundParams);
+ static int comp_offset(const void *a, const void *b);
+ static void JumbleQuery(Query *parse);
+ static bool AppendJumb(char* item, char jumble[], size_t size, size_t *i);
+ static bool PerformJumble(const Query *parse, size_t size, size_t *i);
+ static bool QualsNode(const OpExpr *node, size_t size, size_t *i, List *rtable);
+ static bool LeafNodes(const Node *arg, size_t size, size_t *i, List *rtable);
+ static bool LimitOffsetNode(const Node *node, size_t size, size_t *i, List *rtable);
+ static bool JoinExprNode(JoinExpr *node, size_t size, size_t *i, List *rtable);
+ static bool JoinExprNodeChild(const Node *node, size_t size, size_t *i, List *rtable);
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void pgss_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
*************** static void pgss_ProcessUtility(Node *pa
*** 177,186 ****
DestReceiver *dest, char *completionTag);
static uint32 pgss_hash_fn(const void *key, Size keysize);
static int pgss_match_fn(const void *key1, const void *key2, Size keysize);
! static void pgss_store(const char *query, double total_time, uint64 rows,
! const BufferUsage *bufusage);
static Size pgss_memsize(void);
! static pgssEntry *entry_alloc(pgssHashKey *key);
static void entry_dealloc(void);
static void entry_reset(void);
--- 218,229 ----
DestReceiver *dest, char *completionTag);
static uint32 pgss_hash_fn(const void *key, Size keysize);
static int pgss_match_fn(const void *key1, const void *key2, Size keysize);
! static void pgss_store(const char *query, char jumble[],
! pgssTokenOffset offs[], int off_n,
! double total_time, uint64 rows,
! const BufferUsage *bufusage);
static Size pgss_memsize(void);
! static pgssEntry *entry_alloc(pgssHashKey *key, const char* query, int new_query_len);
static void entry_dealloc(void);
static void entry_reset(void);
*************** _PG_init(void)
*** 252,257 ****
--- 295,315 ----
NULL,
NULL);
+ /*
+ * Support legacy pg_stat_statements behavior, for compatibility with
+ * versions shipped with Postgres 8.4, 9.0 and 9.1
+ */
+ DefineCustomBoolVariable("pg_stat_statements.string_key",
+ "Differentiate queries based on query string alone.",
+ NULL,
+ &pgss_string_key,
+ false,
+ PGC_POSTMASTER,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+
EmitWarningsOnPlaceholders("pg_stat_statements");
/*
*************** _PG_init(void)
*** 262,267 ****
--- 320,332 ----
RequestAddinShmemSpace(pgss_memsize());
RequestAddinLWLocks(1);
+ /* Allocate a buffer to store selective serialization of the query tree
+ * for the purposes of query normalization.
+ */
+ last_jumble = MemoryContextAlloc(TopMemoryContext, JUMBLE_SIZE);
+ /* Allocate space for bookkeeping information for query str normalization */
+ last_offsets = MemoryContextAlloc(TopMemoryContext, last_offset_buf_size * sizeof(pgssTokenOffset));
+
/*
* Install hooks.
*/
*************** _PG_init(void)
*** 277,282 ****
--- 342,352 ----
ExecutorEnd_hook = pgss_ExecutorEnd;
prev_ProcessUtility = ProcessUtility_hook;
ProcessUtility_hook = pgss_ProcessUtility;
+ /*
+ * Install hooks for query normalization
+ */
+ prev_Planner = planner_hook;
+ planner_hook = pgss_PlannerRun;
}
/*
*************** _PG_fini(void)
*** 292,297 ****
--- 362,371 ----
ExecutorFinish_hook = prev_ExecutorFinish;
ExecutorEnd_hook = prev_ExecutorEnd;
ProcessUtility_hook = prev_ProcessUtility;
+ prev_Planner = planner_hook;
+
+ pfree(last_jumble);
+ pfree(last_offsets);
}
/*
*************** _PG_fini(void)
*** 300,306 ****
*/
static void
pgss_shmem_startup(void)
! {
bool found;
HASHCTL info;
FILE *file;
--- 374,380 ----
*/
static void
pgss_shmem_startup(void)
! {
bool found;
HASHCTL info;
FILE *file;
*************** pgss_shmem_startup(void)
*** 395,421 ****
if (!PG_VALID_BE_ENCODING(temp.key.encoding))
goto error;
/* Previous incarnation might have had a larger query_size */
! if (temp.key.query_len >= buffer_size)
{
! buffer = (char *) repalloc(buffer, temp.key.query_len + 1);
! buffer_size = temp.key.query_len + 1;
}
! if (fread(buffer, 1, temp.key.query_len, file) != temp.key.query_len)
goto error;
! buffer[temp.key.query_len] = '\0';
/* Clip to available length if needed */
! if (temp.key.query_len >= query_size)
! temp.key.query_len = pg_encoding_mbcliplen(temp.key.encoding,
buffer,
! temp.key.query_len,
query_size - 1);
- temp.key.query_ptr = buffer;
/* make the hashtable entry (discards old entries if too many) */
! entry = entry_alloc(&temp.key);
/* copy in the actual stats */
entry->counters = temp.counters;
--- 469,496 ----
if (!PG_VALID_BE_ENCODING(temp.key.encoding))
goto error;
+
/* Previous incarnation might have had a larger query_size */
! if (temp.query_len >= buffer_size)
{
! buffer = (char *) repalloc(buffer, temp.query_len + 1);
! buffer_size = temp.query_len + 1;
}
! if (fread(buffer, 1, temp.query_len, file) != temp.query_len)
goto error;
! buffer[temp.query_len] = '\0';
!
/* Clip to available length if needed */
! if (temp.query_len >= query_size)
! temp.query_len = pg_encoding_mbcliplen(temp.key.encoding,
buffer,
! temp.query_len,
query_size - 1);
/* make the hashtable entry (discards old entries if too many) */
! entry = entry_alloc(&temp.key, buffer, temp.query_len);
/* copy in the actual stats */
entry->counters = temp.counters;
*************** pgss_shmem_shutdown(int code, Datum arg)
*** 477,483 ****
hash_seq_init(&hash_seq, pgss_hash);
while ((entry = hash_seq_search(&hash_seq)) != NULL)
{
! int len = entry->key.query_len;
if (fwrite(entry, offsetof(pgssEntry, mutex), 1, file) != 1 ||
fwrite(entry->query, 1, len, file) != len)
--- 552,558 ----
hash_seq_init(&hash_seq, pgss_hash);
while ((entry = hash_seq_search(&hash_seq)) != NULL)
{
! int len = entry->query_len;
if (fwrite(entry, offsetof(pgssEntry, mutex), 1, file) != 1 ||
fwrite(entry->query, 1, len, file) != len)
*************** error:
*** 500,505 ****
--- 575,1391 ----
if (file)
FreeFile(file);
unlink(PGSS_DUMP_FILE);
+
+ }
+
+ /*
+ * pgss_PlannerRun: Planner plugin. Will selectively serialize the query tree
+ * for the purposes of query normalization if that's appropriate.
+ */
+ PlannedStmt *
+ pgss_PlannerRun(Query *parse, int cursorOptions, ParamListInfo boundParams)
+ {
+ if (!parse->utilityStmt && !pgss_string_key)
+ {
+ /*
+ * Only generate a jumble if we have no reason to hash the query string
+ * directly instead
+ */
+ JumbleQuery(parse);
+ }
+ /* Invoke the planner */
+ if (prev_Planner)
+ return prev_Planner(parse, cursorOptions, boundParams);
+ else
+ return standard_planner(parse, cursorOptions, boundParams);
+ }
+
+ /*
+ * comp_offset: Comparator for qsorting pgssTokenOffset values by their
+ * position in the original query string. Often when walking the query tree,
+ * Const tokens will be found in the same order as in the original query string,
+ * but this is certainly not guaranteed.
+ */
+ static int comp_offset(const void *a, const void *b)
+ {
+ int l = ((pgssTokenOffset*) a)->offset;
+ int r = ((pgssTokenOffset*) b)->offset;
+ if (l < r)
+ return -1;
+ else if (l > r)
+ return +1;
+ else
+ return 0;
+ }
+
+ /*
+ * JumbleQuery: Selectively serialize query tree, and store it until
+ * needed to hash the query "parse".
+ */
+ static void JumbleQuery(Query *parse)
+ {
+ /* State for this run of PerformJumble */
+ size_t i = 0;
+ last_offset_num = 0;
+ memset(last_jumble, 0, JUMBLE_SIZE);
+ last_jumble[++i] = HASH_BUF;
+ PerformJumble(parse, JUMBLE_SIZE, &i);
+ /* Sort offsets for query string normalization */
+ qsort(last_offsets, last_offset_num, sizeof(pgssTokenOffset), comp_offset);
+ }
+
+ /*
+ * AppendJumb: Append a value that is substantive to a given query to jumble,
+ * while incrementing the iterator.
+ */
+ static bool AppendJumb(char* item, char jumble[], size_t size, size_t *i)
+ {
+ Assert(item != NULL);
+ Assert(jumble != NULL);
+ Assert(i != NULL);
+
+ /*
+ * Copy the entire item to the buffer, or as much of it as possible to fill
+ * the buffer to capacity.
+ */
+ memcpy(jumble + *i, item, Min(*i >= JUMBLE_SIZE? 0:JUMBLE_SIZE - *i, size));
+
+ if (size + *i >= JUMBLE_SIZE)
+ {
+ /*
+ * While byte-for-byte, the jumble representation will often be a lot more
+ * compact than the query string, it's possible JUMBLE_SIZE has been set to
+ * a very small value. Besides, it's always possible to contrive a query
+ * where it won't be as compact, such as
+ * "select * from table_with_many_columns". Control is not expected to
+ * reach here most of the time, as this is considered an edge-case.
+ */
+ if (size + *i >= JUMBLE_SIZE * 5)
+ /* Give up completely, to avoid a possible stack overflow */
+ return false;
+ /*
+ * Don't give up yet...don't append any more, but keep walking the tree
+ * to find Const nodes to canonicalize. Having done all we can with the
+ * jumble, we must still concern ourselves with the normalized query
+ * str.
+ */
+ }
+ *i += size;
+ return true;
+ }
+
+ /*
+ * Wrapper around AppendJumb to encapsulate details of serialization
+ * of individual elements.
+ */
+ #define APP_JUMB(item) \
+ if (!AppendJumb((char*)&item, last_jumble, sizeof(item), i))\
+ return false;
+
+ /*
+ * Simple wrappers around functions so that they return upon reaching
+ * end of buffer
+ */
+ #define PERFORM_JUMBLE(item, size, i) \
+ if (!PerformJumble(item, size, i))\
+ return false;
+
+ #define QUALS_NODE(item, size, i, rtable) \
+ if (!QualsNode(item, size, i, rtable)) \
+ return false;
+
+ #define LEAF_NODES(item, size, i, rtable) \
+ if (!LeafNodes(item, size, i, rtable)) \
+ return false;
+
+ #define LIMIT_OFFSET_NODE(item, size, i, rtable) \
+ if (!LimitOffsetNode(item, size, i, rtable)) \
+ return false;
+
+ #define JOIN_EXPR_NODE(item, size, i, rtable) \
+ if (!JoinExprNode(item, size, i, rtable)) \
+ return false;
+
+ #define JOIN_EXPR_NODE_CHILD(item, size, i, rtable) \
+ if (!JoinExprNodeChild(item, size, i, rtable)) \
+ return false;
+
+ /*
+ * PerformJumble: Serialize the query tree "parse" and canonicalize
+ * constants, while simply skipping over others that are not essential to the
+ * query, such that it is usefully normalized, excluding things from the tree
+ * that are not essential to the query itself.
+ *
+ * A guiding principal as to whether two queries should be considered
+ * equivalent is whether whatever difference exists between the two queries
+ * could be expected to result in two different plans, assuming that all
+ * constants have the same selectivity estimate and excluding factors that are
+ * not essential to the query and the relations on which it operates. A
+ * non-obvious example of such a differentiator is a change in the definition
+ * of a view referenced by a query. We pointedly serialize the query tree
+ * *after* the rewriting stage, so entries in pg_stat_statements accurately
+ * represent discrete operations, while not having artifacts from external
+ * factors that are not essential to what the query actually does. Directly
+ * hashing plans would have the undesirable side-effect of potentially having
+ * totally external factors like planner cost constants differentiate a query,
+ * so that particular implementation was not chosen. Directly hashing the raw
+ * parse tree would prevent us from benefiting from the parser's own
+ * normalization of queries in later stages, such as removing differences
+ * between equivalent syntax, so that implementation was avoided too.
+ *
+ * The last_jumble buffer, that this function scribbles on, can be hashed to
+ * uniquely identify a query that may use different constants in successive
+ * calls.
+ */
+ static bool PerformJumble(const Query *parse, size_t size, size_t *i)
+ {
+ ListCell *l;
+ /* table join tree (FROM and WHERE clauses) */
+ FromExpr *jt = (FromExpr *) parse->jointree;
+ /* # of result tuples to skip (int8 expr) */
+ FuncExpr *off = (FuncExpr *) parse->limitOffset;
+ /* # of result tuples to skip (int8 expr) */
+ FuncExpr *limcount = (FuncExpr *) parse->limitCount;
+
+ APP_JUMB(parse->resultRelation);
+
+ if (parse->intoClause)
+ {
+ IntoClause *ic = parse->intoClause;
+ RangeVar *rel = ic->rel;
+ APP_JUMB(ic->onCommit);
+ APP_JUMB(ic->skipData);
+ if (rel)
+ {
+ APP_JUMB(rel->relpersistence);
+ /* Bypass macro abstraction to supply size directly.
+ *
+ * Serialize schemaname, relname themselves - this is to be
+ * somewhat consistent with the behavior of utility statements like "create
+ * table".
+ */
+ if ( (rel->schemaname && !AppendJumb(rel->schemaname, last_jumble, strlen(rel->schemaname), i)) ||
+ (rel->relname && !AppendJumb(rel->relname, last_jumble, strlen(rel->relname), i) )
+ )
+ return false;
+ }
+ }
+
+ /* WITH list (of CommonTableExpr's) */
+ foreach(l, parse->cteList)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
+ Query *cteq = (Query*) cte->ctequery;
+ if (cteq)
+ PERFORM_JUMBLE(cteq, size, i);
+ }
+ if (jt)
+ {
+ if (jt->quals)
+ {
+ if (IsA(jt->quals, OpExpr))
+ {
+ QUALS_NODE((OpExpr*) jt->quals, size, i, parse->rtable);
+ }
+ else
+ {
+ LEAF_NODES((Node*) jt->quals, size, i, parse->rtable);
+ }
+ }
+ /* table join tree */
+ foreach(l, jt->fromlist)
+ {
+ Node* fr = lfirst(l);
+ if (IsA(fr, JoinExpr))
+ {
+ JOIN_EXPR_NODE((JoinExpr*) fr, size, i, parse->rtable);
+ }
+ else if (IsA(fr, RangeTblRef))
+ {
+ RangeTblRef *rtf = (RangeTblRef *) fr;
+ RangeTblEntry *rte = rt_fetch(rtf->rtindex, parse->rtable);
+ APP_JUMB(rte->relid);
+ APP_JUMB(rte->rtekind);
+ /* Subselection in where clause */
+ if (rte->subquery)
+ PERFORM_JUMBLE(rte->subquery, size, i);
+
+ /* Function call in where clause */
+ if (rte->funcexpr)
+ LEAF_NODES((Node*) rte->funcexpr, size, i, parse->rtable);
+ }
+ else
+ {
+ elog(ERROR, "unrecognized fromlist node type: %d",
+ (int) nodeTag(fr));
+ }
+ }
+ }
+ /*
+ * target list (of TargetEntry)
+ * columns returned by query
+ */
+ foreach(l, parse->targetList)
+ {
+ TargetEntry *tg = (TargetEntry *) lfirst(l);
+ Node *e = (Node*) tg->expr;
+ if (tg->ressortgroupref)
+ APP_JUMB(tg->ressortgroupref); /* nonzero if referenced by a sort/group - for ORDER BY */
+ APP_JUMB(tg->resno); /* column number for select */
+ /* Handle the various types of nodes in
+ * the select list of this query
+ */
+ LEAF_NODES(e, size, i, parse->rtable);
+ }
+ /* return-values list (of TargetEntry) */
+ foreach(l, parse->returningList)
+ {
+ TargetEntry *rt = (TargetEntry *) lfirst(l);
+ Expr *e = (Expr*) rt->expr;
+ /*
+ * Handle the various types of nodes in
+ * the select list of this query
+ */
+ if (IsA(e, Var)) /* table column */
+ {
+ Var *v = (Var*) e;
+ RangeTblEntry *rte = rt_fetch(v->varno, parse->rtable);
+ APP_JUMB(rte->relid);
+ APP_JUMB(v->varattno);
+ }
+ else
+ {
+ elog(ERROR, "unrecognized node type for returnlist node: %d",
+ (int) nodeTag(e));
+ }
+ }
+ /* a list of SortGroupClause's */
+ foreach(l, parse->groupClause)
+ {
+ SortGroupClause *gc = (SortGroupClause *) lfirst(l);
+ APP_JUMB(gc->tleSortGroupRef);
+ APP_JUMB(gc->nulls_first);
+ }
+
+ if (parse->havingQual)
+ {
+ if (IsA(parse->havingQual, OpExpr))
+ {
+ OpExpr *na = (OpExpr *) parse->havingQual;
+ QUALS_NODE(na, size, i, parse->rtable);
+ }
+ else
+ {
+ elog(ERROR, "unrecognized node type for havingclause node: %d",
+ (int) nodeTag(parse->havingQual));
+ }
+ }
+ foreach(l, parse->windowClause)
+ {
+ WindowClause *wc = (WindowClause *) lfirst(l);
+ ListCell *il;
+ APP_JUMB(wc->frameOptions);
+ foreach(il, wc->partitionClause) /* PARTITION BY list */
+ {
+ Node *n = (Node *) lfirst(il);
+ LEAF_NODES(n, size, i, parse->rtable);
+ }
+ foreach(il, wc->orderClause) /* ORDER BY list */
+ {
+ Node *n = (Node *) lfirst(il);
+ LEAF_NODES(n, size, i, parse->rtable);
+ }
+ }
+
+ foreach(l, parse->distinctClause)
+ {
+ SortGroupClause *dc = (SortGroupClause *) lfirst(l);
+ APP_JUMB(dc->tleSortGroupRef);
+ APP_JUMB(dc->nulls_first);
+ }
+
+ /* Don't look at parse->sortClause,
+ * because the value ressortgroupref is already
+ * serialized when we iterate through targetList
+ */
+
+ if (off)
+ LIMIT_OFFSET_NODE((Node*) off, size, i, parse->rtable);
+
+ if (limcount)
+ LIMIT_OFFSET_NODE((Node*) limcount, size, i, parse->rtable);
+
+ foreach(l, parse->rowMarks)
+ {
+ RowMarkClause *rc = (RowMarkClause *) lfirst(l);
+ APP_JUMB(rc->rti); /* range table index of target relation */
+ APP_JUMB(rc->forUpdate); /* true = FOR UPDATE, false = FOR SHARE */
+ APP_JUMB(rc->noWait); /* NOWAIT option */
+ APP_JUMB(rc->pushedDown); /* pushed down from higher query level? */
+ }
+
+ if (parse->setOperations)
+ {
+ /*
+ * set-operation tree if this is top
+ * level of a UNION/INTERSECT/EXCEPT query
+ */
+ SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
+ APP_JUMB(topop->op);
+ APP_JUMB(topop->all);
+
+ /* leaf selects are RTE subselections */
+ foreach(l, parse->rtable)
+ {
+ RangeTblEntry *r = (RangeTblEntry *) lfirst(l);
+ if (r->subquery)
+ PERFORM_JUMBLE(r->subquery, size, i);
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Perform selective serialization of "Quals" nodes when
+ * they're IsA(*, OpExpr)
+ */
+ static bool QualsNode(const OpExpr *node, size_t size, size_t *i, List *rtable)
+ {
+ ListCell *l;
+ APP_JUMB(node->opno);
+ foreach(l, node->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ return true;
+ }
+
+ /*
+ * LeafNodes: Selectively serialize a selection of parser/prim nodes that are
+ * frequently, though certainly not necesssarily leaf nodes, such as Vars
+ * (columns), constants and function calls
+ */
+ static bool LeafNodes(const Node *arg, size_t size, size_t *i, List *rtable)
+ {
+ ListCell *l;
+ if (IsA(arg, Const))
+ {
+ /*
+ * Serialize generic magic value to
+ * normalize constants
+ */
+ char magic = 0xC0;
+ Const *c = (Const *) arg;
+ APP_JUMB(magic);
+ /* Datatype of the constant is a
+ * differentiator
+ */
+ APP_JUMB(c->consttype);
+ /*
+ * Some Const nodes naturally don't have a location.
+ *
+ * Views that have constants in their
+ * definitions will have a tok_len of 0
+ */
+ if (c->location > 0 && c->tok_len > 0)
+ {
+ if (last_offset_num >= last_offset_buf_size)
+ {
+ last_offset_buf_size *= 2;
+ last_offsets = repalloc(last_offsets, last_offset_buf_size * sizeof(pgssTokenOffset));
+ }
+ last_offsets[last_offset_num].offset = c->location;
+ last_offsets[last_offset_num].len = c->tok_len;
+ last_offset_num++;
+ }
+ }
+ else if (IsA(arg, Var))
+ {
+ char magic = 0xFA;
+ Var *v = (Var *) arg;
+ RangeTblEntry *rte = rt_fetch(v->varno, rtable);
+ APP_JUMB(magic);
+ APP_JUMB(rte->relid);
+ APP_JUMB(v->varattno); /* column number of table */
+ }
+ else if (IsA(arg, Param))
+ {
+ Param *p = ((Param *) arg);
+ APP_JUMB(p->paramkind);
+ APP_JUMB(p->paramid);
+ }
+ else if (IsA(arg, RelabelType))
+ {
+ APP_JUMB(((RelabelType *) arg)->resulttype);
+ }
+ else if (IsA(arg, WindowFunc))
+ {
+ WindowFunc *wf = (WindowFunc *) arg;
+ APP_JUMB(wf->winfnoid);
+ foreach(l, wf->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, FuncExpr))
+ {
+ FuncExpr *f = (FuncExpr *) arg;
+ APP_JUMB(f->funcid);
+ foreach(l, f->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, OpExpr))
+ {
+ QUALS_NODE((OpExpr*) arg, size, i, rtable);
+ }
+ else if (IsA(arg, CoerceViaIO))
+ {
+ APP_JUMB(((CoerceViaIO*) arg)->coerceformat);
+ APP_JUMB(((CoerceViaIO*) arg)->resulttype);
+ }
+ else if (IsA(arg, Aggref))
+ {
+ Aggref *a = (Aggref *) arg;
+ APP_JUMB(a->aggfnoid);
+ foreach(l, a->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, SubLink))
+ {
+ SubLink *s = (SubLink*) arg;
+ APP_JUMB(s->subLinkType);
+ /* Serialize select-list subselect recursively */
+ if (s->subselect)
+ PERFORM_JUMBLE((Query*) s->subselect, size, i);
+ }
+ else if (IsA(arg, TargetEntry))
+ {
+ TargetEntry *rt = (TargetEntry *) arg;
+ Node *e = (Node*) rt->expr;
+ APP_JUMB(rt->resorigtbl); /* OID of column's source table */
+ APP_JUMB(rt->ressortgroupref); /* nonzero if referenced by a sort/group - for ORDER BY */
+ LEAF_NODES(e, size, i, rtable);
+ }
+ else if (IsA(arg, BoolExpr))
+ {
+ BoolExpr *be = (BoolExpr *) arg;
+ APP_JUMB(be->boolop);
+ foreach(l, be->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, NullTest))
+ {
+ NullTest *nt = (NullTest *) arg;
+ Node *arg = (Node *) nt->arg;
+ APP_JUMB(nt->nulltesttype); /* IS NULL, IS NOT NULL */
+ APP_JUMB(nt->argisrow); /* is input a composite type ? */
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ else if (IsA(arg, ArrayExpr))
+ {
+ ArrayExpr *ae = (ArrayExpr *) arg;
+ APP_JUMB(ae->array_typeid); /* type of expression result */
+ APP_JUMB(ae->element_typeid); /* common type of array elements */
+ foreach(l, ae->elements)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, CaseExpr))
+ {
+ CaseExpr *ce = (CaseExpr*) arg;
+ Assert(ce->casetype != InvalidOid);
+ APP_JUMB(ce->casetype);
+ foreach(l, ce->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ if (ce->arg)
+ LEAF_NODES((Node*) ce->arg, size, i, rtable);
+
+ if (ce->defresult)
+ {
+ /* Default result (ELSE clause)
+ * The ptr may be NULL, because no else clause
+ * was actually specified, and thus the value is
+ * equivalent to SQL ELSE NULL
+ */
+ LEAF_NODES((Node*) ce->defresult, size, i, rtable); /* the default result (ELSE clause) */
+ }
+ }
+ else if (IsA(arg, CaseTestExpr))
+ {
+ CaseTestExpr *ct = (CaseTestExpr*) arg;
+ APP_JUMB(ct->typeId);
+ }
+ else if (IsA(arg, CaseWhen))
+ {
+ CaseWhen *cw = (CaseWhen*) arg;
+ Node *res = (Node*) cw->result;
+ Node *exp = (Node*) cw->expr;
+ if (res)
+ LEAF_NODES(res, size, i, rtable);
+ if (exp)
+ LEAF_NODES(exp, size, i, rtable);
+ }
+ else if (IsA(arg, MinMaxExpr))
+ {
+ MinMaxExpr *cw = (MinMaxExpr*) arg;
+ APP_JUMB(cw->minmaxtype);
+ APP_JUMB(cw->op);
+ foreach(l, cw->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, ScalarArrayOpExpr))
+ {
+ ScalarArrayOpExpr *sa = (ScalarArrayOpExpr*) arg;
+ APP_JUMB(sa->opfuncid);
+ APP_JUMB(sa->useOr);
+ foreach(l, sa->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, CoalesceExpr))
+ {
+ CoalesceExpr *ca = (CoalesceExpr*) arg;
+ foreach(l, ca->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, ArrayCoerceExpr))
+ {
+ ArrayCoerceExpr *ac = (ArrayCoerceExpr *) arg;
+ LEAF_NODES((Node*) ac->arg, size, i, rtable);
+ }
+ else if (IsA(arg, WindowClause))
+ {
+ WindowClause *wc = (WindowClause*) arg;
+ foreach(l, wc->partitionClause)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ foreach(l, wc->orderClause)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, SortGroupClause))
+ {
+ SortGroupClause *sgc = (SortGroupClause*) arg;
+ APP_JUMB(sgc->tleSortGroupRef);
+ APP_JUMB(sgc->nulls_first);
+ }
+ else if (IsA(arg, Integer) ||
+ IsA(arg, Float) ||
+ IsA(arg, String) ||
+ IsA(arg, BitString) ||
+ IsA(arg, Null)
+ )
+ {
+ /* It is not necessary to
+ * serialize integral values
+ */
+ }
+ else if (IsA(arg, BooleanTest))
+ {
+ BooleanTest *bt = (BooleanTest *) arg;
+ APP_JUMB(bt->booltesttype);
+ LEAF_NODES((Node*) bt->arg, size, i, rtable);
+ }
+ else if (IsA(arg, ArrayRef))
+ {
+ ArrayRef *ar = (ArrayRef*) arg;
+ APP_JUMB(ar->refarraytype);
+ foreach(l, ar->refupperindexpr)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ foreach(l, ar->reflowerindexpr)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, NullIfExpr))
+ {
+ /* NullIfExpr is just a typedef for OpExpr */
+ QUALS_NODE((OpExpr*) arg, size, i, rtable);
+ }
+ else if (IsA(arg, RowExpr))
+ {
+ RowExpr *re = (RowExpr*) arg;
+ APP_JUMB(re->row_format);
+ foreach(l, re->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+
+ }
+ else if (IsA(arg, XmlExpr))
+ {
+ XmlExpr *xml = (XmlExpr*) arg;
+ APP_JUMB(xml->op);
+ foreach(l, xml->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ foreach(l, xml->named_args) /* non-XML expressions for xml_attributes */
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ foreach(l, xml->arg_names) /* parallel list of Value strings */
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(arg, RowCompareExpr))
+ {
+ RowCompareExpr *rc = (RowCompareExpr*) arg;
+ foreach(l, rc->largs)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ foreach(l, rc->rargs)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else
+ {
+ elog(ERROR, "unrecognized node type for LeafNodes node: %d",
+ (int) nodeTag(arg));
+ }
+ return true;
+ }
+
+ /*
+ * Perform selective serialization of limit or offset nodes
+ */
+ static bool LimitOffsetNode(const Node *node, size_t size, size_t *i, List *rtable)
+ {
+ ListCell *l;
+ if (IsA(node, FuncExpr))
+ {
+ foreach(l, ((FuncExpr*) node)->args)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(node, Const))
+ {
+ /* This should be a differentiator, as it results in the addition of a limit node */
+ char magic = 0xEA;
+ APP_JUMB(magic);
+ }
+ else
+ {
+ /* Fall back on leaf node representation */
+ LEAF_NODES(node, size, i, rtable);
+ }
+ return true;
+ }
+
+ /*
+ * JoinExprNode: Perform selective serialization of JoinExpr nodes
+ */
+ static bool JoinExprNode(JoinExpr *node, size_t size, size_t *i, List *rtable)
+ {
+ Node *larg = node->larg; /* left subtree */
+ Node *rarg = node->rarg; /* right subtree */
+ ListCell *l;
+
+ Assert( IsA(node, JoinExpr));
+
+ APP_JUMB(node->jointype);
+ APP_JUMB(node->isNatural);
+
+ if (node->quals)
+ {
+ if ( IsA(node, OpExpr))
+ {
+ QUALS_NODE((OpExpr*) node->quals, size, i, rtable);
+ }
+ else
+ {
+ LEAF_NODES((Node*) node->quals, size, i, rtable);
+ }
+
+ }
+ foreach(l, node->usingClause) /* USING clause, if any (list of String) */
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ if (larg)
+ JOIN_EXPR_NODE_CHILD(larg, size, i, rtable);
+ if (rarg)
+ JOIN_EXPR_NODE_CHILD(rarg, size, i, rtable);
+
+ return true;
+ }
+
+ /*
+ * JoinExprNodeChild: Serialize children of the JoinExpr node
+ */
+ static bool JoinExprNodeChild(const Node *node, size_t size, size_t *i, List *rtable)
+ {
+ if (IsA(node, RangeTblRef))
+ {
+ RangeTblRef *rt = (RangeTblRef*) node;
+ RangeTblEntry *rte = rt_fetch(rt->rtindex, rtable);
+ ListCell *l;
+
+ APP_JUMB(rte->relid);
+ APP_JUMB(rte->jointype);
+
+ if (rte->subquery)
+ PERFORM_JUMBLE((Query*) rte->subquery, size, i);
+
+ foreach(l, rte->joinaliasvars)
+ {
+ Node *arg = (Node *) lfirst(l);
+ LEAF_NODES(arg, size, i, rtable);
+ }
+ }
+ else if (IsA(node, JoinExpr))
+ {
+ JOIN_EXPR_NODE((JoinExpr*) node, size, i, rtable);
+ }
+ else
+ {
+ LEAF_NODES(node, size, i, rtable);
+ }
+ return true;
}
/*
*************** pgss_ExecutorEnd(QueryDesc *queryDesc)
*** 591,600 ****
--- 1477,1527 ----
*/
InstrEndLoop(queryDesc->totaltime);
+ if (queryDesc->params || queryDesc->utilitystmt || pgss_string_key)
+ {
+ /*
+ * This query was paramaterized or is a utility statement, or
+ * pg_stat_statements is in legacy pgss_string_key mode - hash the
+ * query string, as the last call to pgss_PlannerRun won't have
+ * hashed the tree of this particular query - it may have skipped
+ * hashing, or there may not have even been a call corresponding to
+ * a call to this call of pgss_ExecutorEnd.
+ *
+ * If we're dealing with a parameterized query, the query string
+ * is the original query string anyway, so there is no need to
+ * worry about its stability.
+ *
+ * The fact that constants in the prepared query won't be
+ * canonicalized is clearly a feature rather than a bug, as the
+ * user evidently considers such constant essential to the query, or
+ * they'd have paramaterized them.
+ */
+ memset(last_jumble, 0, JUMBLE_SIZE);
+ last_jumble[0] = STR_BUF;
+ memcpy(last_jumble + 1, queryDesc->sourceText,
+ Min(JUMBLE_SIZE - 1, strlen(queryDesc->sourceText) )
+ );
+ }
+ /*
+ * There is an assumption that last_* variables were set by a prior,
+ * corresponding call to pgss_PlannerRun within this backend (provided
+ * that we jumbled the query tree with the intention of hashing it - that
+ * won't be the case if the jumble is actually just a STR_BUF copy of
+ * the query string).
+ */
pgss_store(queryDesc->sourceText,
+ last_jumble,
+ last_offsets,
+ last_offset_num,
queryDesc->totaltime->total,
queryDesc->estate->es_processed,
&queryDesc->totaltime->bufusage);
+
+ if (last_offset_buf_size > 10)
+ {
+ last_offset_buf_size = 10;
+ last_offsets = repalloc(last_offsets, last_offset_buf_size * sizeof(pgssTokenOffset));
+ }
}
if (prev_ExecutorEnd)
*************** pgss_ProcessUtility(Node *parsetree, con
*** 665,671 ****
bufusage.temp_blks_written =
pgBufferUsage.temp_blks_written - bufusage.temp_blks_written;
! pgss_store(queryString, INSTR_TIME_GET_DOUBLE(duration), rows,
&bufusage);
}
else
--- 1592,1605 ----
bufusage.temp_blks_written =
pgBufferUsage.temp_blks_written - bufusage.temp_blks_written;
! /* In the case of utility statements, hash the query string directly */
! memset(last_jumble, 0, JUMBLE_SIZE);
! last_jumble[0] = STR_BUF;
! memcpy(last_jumble + 1, queryString,
! Min(JUMBLE_SIZE - 1, strlen(queryString) )
! );
!
! pgss_store(queryString, last_jumble, NULL, 0, INSTR_TIME_GET_DOUBLE(duration), rows,
&bufusage);
}
else
*************** pgss_hash_fn(const void *key, Size keysi
*** 690,697 ****
/* we don't bother to include encoding in the hash */
return hash_uint32((uint32) k->userid) ^
hash_uint32((uint32) k->dbid) ^
! DatumGetUInt32(hash_any((const unsigned char *) k->query_ptr,
! k->query_len));
}
/*
--- 1624,1630 ----
/* we don't bother to include encoding in the hash */
return hash_uint32((uint32) k->userid) ^
hash_uint32((uint32) k->dbid) ^
! DatumGetUInt32(hash_any((const unsigned char* ) k->jumble, JUMBLE_SIZE) );
}
/*
*************** pgss_match_fn(const void *key1, const vo
*** 706,713 ****
if (k1->userid == k2->userid &&
k1->dbid == k2->dbid &&
k1->encoding == k2->encoding &&
! k1->query_len == k2->query_len &&
! memcmp(k1->query_ptr, k2->query_ptr, k1->query_len) == 0)
return 0;
else
return 1;
--- 1639,1645 ----
if (k1->userid == k2->userid &&
k1->dbid == k2->dbid &&
k1->encoding == k2->encoding &&
! memcmp(k1->jumble, k2->jumble, JUMBLE_SIZE) == 0)
return 0;
else
return 1;
*************** pgss_match_fn(const void *key1, const vo
*** 717,727 ****
* Store some statistics for a statement.
*/
static void
! pgss_store(const char *query, double total_time, uint64 rows,
! const BufferUsage *bufusage)
{
pgssHashKey key;
double usage;
pgssEntry *entry;
Assert(query != NULL);
--- 1649,1663 ----
* Store some statistics for a statement.
*/
static void
! pgss_store(const char *query, char jumble[],
! pgssTokenOffset offs[], int off_n,
! double total_time, uint64 rows,
! const BufferUsage *bufusage)
{
pgssHashKey key;
double usage;
+ int new_query_len = strlen(query);
+ char *norm_query = NULL;
pgssEntry *entry;
Assert(query != NULL);
*************** pgss_store(const char *query, double tot
*** 734,747 ****
key.userid = GetUserId();
key.dbid = MyDatabaseId;
key.encoding = GetDatabaseEncoding();
! key.query_len = strlen(query);
! if (key.query_len >= pgss->query_size)
! key.query_len = pg_encoding_mbcliplen(key.encoding,
query,
! key.query_len,
pgss->query_size - 1);
- key.query_ptr = query;
-
usage = USAGE_EXEC(duration);
/* Lookup the hash table entry with shared lock. */
--- 1670,1682 ----
key.userid = GetUserId();
key.dbid = MyDatabaseId;
key.encoding = GetDatabaseEncoding();
! memcpy(key.jumble, jumble, JUMBLE_SIZE);
!
! if (new_query_len >= pgss->query_size)
! new_query_len = pg_encoding_mbcliplen(key.encoding,
query,
! new_query_len,
pgss->query_size - 1);
usage = USAGE_EXEC(duration);
/* Lookup the hash table entry with shared lock. */
*************** pgss_store(const char *query, double tot
*** 750,759 ****
entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_FIND, NULL);
if (!entry)
{
! /* Must acquire exclusive lock to add a new entry. */
! LWLockRelease(pgss->lock);
! LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
! entry = entry_alloc(&key);
}
/* Grab the spinlock while updating the counters. */
--- 1685,1755 ----
entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_FIND, NULL);
if (!entry)
{
! /*
! * It is necessary to generate a normalized version of the query
! * string that will be used to represent it. It's important that
! * the user be presented with a stable representation of the query.
! *
! * Note that the representation seen by the user will only have
! * non-differentiating Const tokens swapped with '?' characters, and
! * this does not for example take account of the fact that alias names
! * could vary between successive calls of what is regarded as the same
! * query.
! */
! if (off_n > 0)
! {
! int i,
! last_off = 0,
! quer_it = 0,
! n_quer_it = 0,
! off = 0,
! tok_len = 0,
! len_to_wrt = 0,
! last_tok_len = 0;
!
! norm_query = palloc0(new_query_len + 1);
! for(i = 0; i < off_n; i++)
! {
! off = offs[i].offset;
! tok_len = offs[i].len;
! len_to_wrt = off - last_off;
! len_to_wrt -= last_tok_len;
! /*
! * Each iteration copies everything prior to the current
! * offset/token to be replaced, except bytes copied in
! * previous iterations
! */
! if (off + tok_len > new_query_len)
! break;
! memcpy(norm_query + n_quer_it, query + quer_it, len_to_wrt);
!
! n_quer_it += len_to_wrt;
! norm_query[n_quer_it++] = '?';
! quer_it += len_to_wrt + tok_len;
! last_off = off;
! last_tok_len = tok_len;
! }
! /* Finish off last piece of query string */
! memcpy(norm_query + n_quer_it, query + (off + tok_len),
! Min( strlen(query) - (off + tok_len),
! new_query_len - n_quer_it ) );
! /*
! * Must acquire exclusive lock to add a new entry.
! * Leave that until as late as possible.
! */
! LWLockRelease(pgss->lock);
! LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
!
! entry = entry_alloc(&key, norm_query, strlen(norm_query));
! }
! else
! {
! /* Acquire exclusive lock as required by entry_alloc() */
! LWLockRelease(pgss->lock);
! LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
!
! entry = entry_alloc(&key, query, new_query_len);
! }
}
/* Grab the spinlock while updating the counters. */
*************** pgss_store(const char *query, double tot
*** 775,782 ****
e->counters.usage += usage;
SpinLockRelease(&e->mutex);
}
-
LWLockRelease(pgss->lock);
}
/*
--- 1771,1779 ----
e->counters.usage += usage;
SpinLockRelease(&e->mutex);
}
LWLockRelease(pgss->lock);
+ if (norm_query)
+ pfree(norm_query);
}
/*
*************** pg_stat_statements(PG_FUNCTION_ARGS)
*** 857,869 ****
values[i++] = ObjectIdGetDatum(entry->key.userid);
values[i++] = ObjectIdGetDatum(entry->key.dbid);
if (is_superuser || entry->key.userid == userid)
{
char *qstr;
qstr = (char *)
pg_do_encoding_conversion((unsigned char *) entry->query,
! entry->key.query_len,
entry->key.encoding,
GetDatabaseEncoding());
values[i++] = CStringGetTextDatum(qstr);
--- 1854,1875 ----
values[i++] = ObjectIdGetDatum(entry->key.userid);
values[i++] = ObjectIdGetDatum(entry->key.dbid);
+ /* copy counters to a local variable to keep locking time short */
+ {
+ volatile pgssEntry *e = (volatile pgssEntry *) entry;
+
+ SpinLockAcquire(&e->mutex);
+ tmp = e->counters;
+ SpinLockRelease(&e->mutex);
+ }
+
if (is_superuser || entry->key.userid == userid)
{
char *qstr;
qstr = (char *)
pg_do_encoding_conversion((unsigned char *) entry->query,
! entry->query_len,
entry->key.encoding,
GetDatabaseEncoding());
values[i++] = CStringGetTextDatum(qstr);
*************** pg_stat_statements(PG_FUNCTION_ARGS)
*** 873,887 ****
else
values[i++] = CStringGetTextDatum("<insufficient privilege>");
- /* copy counters to a local variable to keep locking time short */
- {
- volatile pgssEntry *e = (volatile pgssEntry *) entry;
-
- SpinLockAcquire(&e->mutex);
- tmp = e->counters;
- SpinLockRelease(&e->mutex);
- }
-
values[i++] = Int64GetDatumFast(tmp.calls);
values[i++] = Float8GetDatumFast(tmp.total_time);
values[i++] = Int64GetDatumFast(tmp.rows);
--- 1879,1884 ----
*************** pgss_memsize(void)
*** 933,946 ****
* have made the entry while we waited to get exclusive lock.
*/
static pgssEntry *
! entry_alloc(pgssHashKey *key)
{
pgssEntry *entry;
bool found;
- /* Caller must have clipped query properly */
- Assert(key->query_len < pgss->query_size);
-
/* Make space if needed */
while (hash_get_num_entries(pgss_hash) >= pgss_max)
entry_dealloc();
--- 1930,1940 ----
* have made the entry while we waited to get exclusive lock.
*/
static pgssEntry *
! entry_alloc(pgssHashKey *key, const char* query, int new_query_len)
{
pgssEntry *entry;
bool found;
/* Make space if needed */
while (hash_get_num_entries(pgss_hash) >= pgss_max)
entry_dealloc();
*************** entry_alloc(pgssHashKey *key)
*** 950,968 ****
if (!found)
{
/* New entry, initialize it */
- /* dynahash tried to copy the key for us, but must fix query_ptr */
- entry->key.query_ptr = entry->query;
/* reset the statistics */
memset(&entry->counters, 0, sizeof(Counters));
entry->counters.usage = USAGE_INIT;
/* re-initialize the mutex each time ... we assume no one using it */
SpinLockInit(&entry->mutex);
/* ... and don't forget the query text */
! memcpy(entry->query, key->query_ptr, key->query_len);
! entry->query[key->query_len] = '\0';
}
return entry;
}
--- 1944,1964 ----
if (!found)
{
+ entry->query_len = new_query_len;
+ Assert(entry->query_len > 0);
/* New entry, initialize it */
/* reset the statistics */
memset(&entry->counters, 0, sizeof(Counters));
entry->counters.usage = USAGE_INIT;
/* re-initialize the mutex each time ... we assume no one using it */
SpinLockInit(&entry->mutex);
/* ... and don't forget the query text */
! memcpy(entry->query, query, entry->query_len);
! entry->query[entry->query_len] = '\0';
}
+ /* Caller must have clipped query properly */
+ Assert(entry->query_len < pgss->query_size);
return entry;
}
*************** entry_alloc(pgssHashKey *key)
*** 971,977 ****
* qsort comparator for sorting into increasing usage order
*/
static int
! entry_cmp(const void *lhs, const void *rhs)
{
double l_usage = (*(pgssEntry * const *) lhs)->counters.usage;
double r_usage = (*(pgssEntry * const *) rhs)->counters.usage;
--- 1967,1973 ----
* qsort comparator for sorting into increasing usage order
*/
static int
! entry_cmp_usage(const void *lhs, const void *rhs)
{
double l_usage = (*(pgssEntry * const *) lhs)->counters.usage;
double r_usage = (*(pgssEntry * const *) rhs)->counters.usage;
*************** entry_dealloc(void)
*** 1009,1015 ****
entry->counters.usage *= USAGE_DECREASE_FACTOR;
}
! qsort(entries, i, sizeof(pgssEntry *), entry_cmp);
nvictims = Max(10, i * USAGE_DEALLOC_PERCENT / 100);
nvictims = Min(nvictims, i);
--- 2005,2011 ----
entry->counters.usage *= USAGE_DECREASE_FACTOR;
}
! qsort(entries, i, sizeof(pgssEntry *), entry_cmp_usage);
nvictims = Max(10, i * USAGE_DEALLOC_PERCENT / 100);
nvictims = Min(nvictims, i);
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index e11d896..ccd92d3 100644
*** a/src/backend/catalog/heap.c
--- b/src/backend/catalog/heap.c
*************** cookDefault(ParseState *pstate,
*** 2441,2447 ****
atttypid, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 2441,2447 ----
atttypid, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index a949215..e80d57f 100644
*** a/src/backend/commands/prepare.c
--- b/src/backend/commands/prepare.c
*************** EvaluateParams(PreparedStatement *pstmt,
*** 365,371 ****
expected_type_id, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (expr == NULL)
ereport(ERROR,
--- 365,371 ----
expected_type_id, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (expr == NULL)
ereport(ERROR,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 1ee201c..f6b64d5 100644
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
*************** ATExecAddColumn(List **wqueue, AlteredTa
*** 4493,4499 ****
typmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (defval == NULL) /* should not happen */
elog(ERROR, "failed to coerce base type to domain");
}
--- 4493,4499 ----
typmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (defval == NULL) /* should not happen */
elog(ERROR, "failed to coerce base type to domain");
}
*************** ATPrepAlterColumnType(List **wqueue,
*** 6987,6993 ****
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (transform == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 6987,6993 ----
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (transform == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 7154,7160 ****
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (defaultexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 7154,7160 ----
targettype, targettypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (defaultexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 7178b52..c40a1bf 100644
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
*************** _copyAConst(const A_Const *from)
*** 2130,2135 ****
--- 2130,2136 ----
}
COPY_LOCATION_FIELD(location);
+ COPY_LOCATION_FIELD(tok_len);
return newnode;
}
*************** _copyTypeCast(const TypeCast *from)
*** 2284,2289 ****
--- 2285,2291 ----
COPY_NODE_FIELD(arg);
COPY_NODE_FIELD(typeName);
COPY_LOCATION_FIELD(location);
+ COPY_LOCATION_FIELD(tok_len);
return newnode;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c3e0ee1..1569b7d 100644
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 65,71 ****
#include "utils/numeric.h"
#include "utils/xml.h"
-
/* Location tracking support --- simpler than bison's default */
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \
--- 65,70 ----
*************** static void base_yyerror(YYLTYPE *yylloc
*** 109,123 ****
const char *msg);
static Node *makeColumnRef(char *colname, List *indirection,
int location, core_yyscan_t yyscanner);
! static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
! static Node *makeStringConst(char *str, int location);
! static Node *makeStringConstCast(char *str, int location, TypeName *typename);
! static Node *makeIntConst(int val, int location);
! static Node *makeFloatConst(char *str, int location);
! static Node *makeBitStringConst(char *str, int location);
! static Node *makeNullAConst(int location);
! static Node *makeAConst(Value *v, int location);
! static Node *makeBoolAConst(bool state, int location);
static FuncCall *makeOverlaps(List *largs, List *rargs,
int location, core_yyscan_t yyscanner);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
--- 108,122 ----
const char *msg);
static Node *makeColumnRef(char *colname, List *indirection,
int location, core_yyscan_t yyscanner);
! static Node *makeTypeCast(Node *arg, TypeName *typename, int location, int length);
! static Node *makeStringConst(char *str, int location, int length);
! static Node *makeStringConstCast(char *str, int location, int length, TypeName *typename);
! static Node *makeIntConst(int val, int location, int length);
! static Node *makeFloatConst(char *str, int location, int length);
! static Node *makeBitStringConst(char *str, int location, int length);
! static Node *makeNullAConst(int location, int length);
! static Node *makeAConst(Value *v, int location, int length);
! static Node *makeBoolAConst(bool state, int location, int length);
static FuncCall *makeOverlaps(List *largs, List *rargs,
int location, core_yyscan_t yyscanner);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
*************** static void insertSelectOptions(SelectSt
*** 131,137 ****
WithClause *withClause,
core_yyscan_t yyscanner);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
! static Node *doNegate(Node *n, int location);
static void doNegateFloat(Value *v);
static Node *makeAArrayExpr(List *elements, int location);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
--- 130,136 ----
WithClause *withClause,
core_yyscan_t yyscanner);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
! static Node *doNegate(Node *n, int location, int length);
static void doNegateFloat(Value *v);
static Node *makeAArrayExpr(List *elements, int location);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
*************** AlterOptRoleElem:
*** 912,918 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized role option \"%s\"", $1),
! parser_errposition(@1)));
}
;
--- 911,917 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized role option \"%s\"", $1),
! parser_errposition(@1.begins)));
}
;
*************** set_rest: /* Generic SET syntaxes: */
*** 1298,1304 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("current database cannot be changed"),
! parser_errposition(@2)));
$$ = NULL; /*not reached*/
}
| SCHEMA Sconst
--- 1297,1303 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("current database cannot be changed"),
! parser_errposition(@2.begins)));
$$ = NULL; /*not reached*/
}
| SCHEMA Sconst
*************** set_rest: /* Generic SET syntaxes: */
*** 1306,1312 ****
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "search_path";
! n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
| NAMES opt_encoding
--- 1305,1311 ----
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "search_path";
! n->args = list_make1(makeStringConst($2, @2.begins, @2.length));
$$ = n;
}
| NAMES opt_encoding
*************** set_rest: /* Generic SET syntaxes: */
*** 1315,1321 ****
n->kind = VAR_SET_VALUE;
n->name = "client_encoding";
if ($2 != NULL)
! n->args = list_make1(makeStringConst($2, @2));
else
n->kind = VAR_SET_DEFAULT;
$$ = n;
--- 1314,1320 ----
n->kind = VAR_SET_VALUE;
n->name = "client_encoding";
if ($2 != NULL)
! n->args = list_make1(makeStringConst($2, @2.begins, @2.length));
else
n->kind = VAR_SET_DEFAULT;
$$ = n;
*************** set_rest: /* Generic SET syntaxes: */
*** 1325,1331 ****
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "role";
! n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
| SESSION AUTHORIZATION ColId_or_Sconst
--- 1324,1330 ----
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "role";
! n->args = list_make1(makeStringConst($2, @2.begins, @2.length));
$$ = n;
}
| SESSION AUTHORIZATION ColId_or_Sconst
*************** set_rest: /* Generic SET syntaxes: */
*** 1333,1339 ****
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "session_authorization";
! n->args = list_make1(makeStringConst($3, @3));
$$ = n;
}
| SESSION AUTHORIZATION DEFAULT
--- 1332,1338 ----
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "session_authorization";
! n->args = list_make1(makeStringConst($3, @3.begins, @3.length));
$$ = n;
}
| SESSION AUTHORIZATION DEFAULT
*************** set_rest: /* Generic SET syntaxes: */
*** 1348,1354 ****
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "xmloption";
! n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3));
$$ = n;
}
/* Special syntaxes invented by PostgreSQL: */
--- 1347,1353 ----
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "xmloption";
! n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3.begins, @3.length));
$$ = n;
}
/* Special syntaxes invented by PostgreSQL: */
*************** set_rest: /* Generic SET syntaxes: */
*** 1357,1363 ****
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_MULTI;
n->name = "TRANSACTION SNAPSHOT";
! n->args = list_make1(makeStringConst($3, @3));
$$ = n;
}
;
--- 1356,1362 ----
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_MULTI;
n->name = "TRANSACTION SNAPSHOT";
! n->args = list_make1(makeStringConst($3, @3.begins, @3.length));
$$ = n;
}
;
*************** var_list: var_value { $$ = list_m
*** 1375,1383 ****
;
var_value: opt_boolean_or_string
! { $$ = makeStringConst($1, @1); }
| NumericOnly
! { $$ = makeAConst($1, @1); }
;
iso_level: READ UNCOMMITTED { $$ = "read uncommitted"; }
--- 1374,1382 ----
;
var_value: opt_boolean_or_string
! { $$ = makeStringConst($1, @1.begins, @1.length); }
| NumericOnly
! { $$ = makeAConst($1, @1.begins, @1.length); }
;
iso_level: READ UNCOMMITTED { $$ = "read uncommitted"; }
*************** opt_boolean_or_string:
*** 1409,1419 ****
zone_value:
Sconst
{
! $$ = makeStringConst($1, @1);
}
| IDENT
{
! $$ = makeStringConst($1, @1);
}
| ConstInterval Sconst opt_interval
{
--- 1408,1418 ----
zone_value:
Sconst
{
! $$ = makeStringConst($1, @1.begins, @1.length);
}
| IDENT
{
! $$ = makeStringConst($1, @1.begins, @1.length);
}
| ConstInterval Sconst opt_interval
{
*************** zone_value:
*** 1425,1434 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
! parser_errposition(@3)));
}
t->typmods = $3;
! $$ = makeStringConstCast($2, @2, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
--- 1424,1433 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
! parser_errposition(@3.begins)));
}
t->typmods = $3;
! $$ = makeStringConstCast($2, @2.begins, @2.length, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
*************** zone_value:
*** 1440,1459 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
! parser_errposition(@6)));
if (list_length($6) != 1)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1)));
! t->typmods = lappend($6, makeIntConst($3, @3));
}
else
! t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
! makeIntConst($3, @3));
! $$ = makeStringConstCast($5, @5, t);
}
! | NumericOnly { $$ = makeAConst($1, @1); }
| DEFAULT { $$ = NULL; }
| LOCAL { $$ = NULL; }
;
--- 1439,1458 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
! parser_errposition(@6.begins)));
if (list_length($6) != 1)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1.begins)));
! t->typmods = lappend($6, makeIntConst($3, @3.begins, @3.length));
}
else
! t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1, -1),
! makeIntConst($3, @3.begins, @3.length));
! $$ = makeStringConstCast($5, @5.begins, @5.length, t);
}
! | NumericOnly { $$ = makeAConst($1, @1.begins, @1.length); }
| DEFAULT { $$ = NULL; }
| LOCAL { $$ = NULL; }
;
*************** alter_table_cmd:
*** 1965,1971 ****
{
AlterTableCmd *n = makeNode(AlterTableCmd);
TypeName *def = makeTypeNameFromNameList($2);
! def->location = @2;
n->subtype = AT_AddOf;
n->def = (Node *) def;
$$ = (Node *)n;
--- 1964,1970 ----
{
AlterTableCmd *n = makeNode(AlterTableCmd);
TypeName *def = makeTypeNameFromNameList($2);
! def->location = @2.begins;
n->subtype = AT_AddOf;
n->def = (Node *) def;
$$ = (Node *)n;
*************** opt_collate_clause:
*** 2035,2041 ****
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
! n->location = @1;
$$ = (Node *) n;
}
| /* EMPTY */ { $$ = NULL; }
--- 2034,2040 ----
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
! n->location = @1.begins;
$$ = (Node *) n;
}
| /* EMPTY */ { $$ = NULL; }
*************** AlterCompositeTypeStmt:
*** 2094,2100 ****
AlterTableStmt *n = makeNode(AlterTableStmt);
/* can't use qualified_name, sigh */
! n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
n->cmds = $4;
n->relkind = OBJECT_TYPE;
$$ = (Node *)n;
--- 2093,2099 ----
AlterTableStmt *n = makeNode(AlterTableStmt);
/* can't use qualified_name, sigh */
! n->relation = makeRangeVarFromAnyName($3, @3.begins, yyscanner);
n->cmds = $4;
n->relkind = OBJECT_TYPE;
$$ = (Node *)n;
*************** CreateStmt: CREATE OptTemp TABLE qualifi
*** 2428,2434 ****
n->relation = $4;
n->tableElts = $7;
n->ofTypename = makeTypeNameFromNameList($6);
! n->ofTypename->location = @6;
n->constraints = NIL;
n->options = $8;
n->oncommit = $9;
--- 2427,2433 ----
n->relation = $4;
n->tableElts = $7;
n->ofTypename = makeTypeNameFromNameList($6);
! n->ofTypename->location = @6.begins;
n->constraints = NIL;
n->options = $8;
n->oncommit = $9;
*************** CreateStmt: CREATE OptTemp TABLE qualifi
*** 2444,2450 ****
n->relation = $7;
n->tableElts = $10;
n->ofTypename = makeTypeNameFromNameList($9);
! n->ofTypename->location = @9;
n->constraints = NIL;
n->options = $11;
n->oncommit = $12;
--- 2443,2449 ----
n->relation = $7;
n->tableElts = $10;
n->ofTypename = makeTypeNameFromNameList($9);
! n->ofTypename->location = @9.begins;
n->constraints = NIL;
n->options = $11;
n->oncommit = $12;
*************** ColConstraint:
*** 2564,2570 ****
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
! n->location = @1;
$$ = (Node *) n;
}
| ColConstraintElem { $$ = $1; }
--- 2563,2569 ----
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
! n->location = @1.begins;
$$ = (Node *) n;
}
| ColConstraintElem { $$ = $1; }
*************** ColConstraint:
*** 2579,2585 ****
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
! n->location = @1;
$$ = (Node *) n;
}
;
--- 2578,2584 ----
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
! n->location = @1.begins;
$$ = (Node *) n;
}
;
*************** ColConstraintElem:
*** 2604,2624 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NOTNULL;
! n->location = @1;
$$ = (Node *)n;
}
| NULL_P
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NULL;
! n->location = @1;
$$ = (Node *)n;
}
| UNIQUE opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1;
n->keys = NULL;
n->options = $2;
n->indexname = NULL;
--- 2603,2623 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NOTNULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| NULL_P
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| UNIQUE opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1.begins;
n->keys = NULL;
n->options = $2;
n->indexname = NULL;
*************** ColConstraintElem:
*** 2629,2635 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1;
n->keys = NULL;
n->options = $3;
n->indexname = NULL;
--- 2628,2634 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1.begins;
n->keys = NULL;
n->options = $3;
n->indexname = NULL;
*************** ColConstraintElem:
*** 2640,2646 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
! n->location = @1;
n->raw_expr = $3;
n->cooked_expr = NULL;
$$ = (Node *)n;
--- 2639,2645 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
! n->location = @1.begins;
n->raw_expr = $3;
n->cooked_expr = NULL;
$$ = (Node *)n;
*************** ColConstraintElem:
*** 2649,2655 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_DEFAULT;
! n->location = @1;
n->raw_expr = $2;
n->cooked_expr = NULL;
$$ = (Node *)n;
--- 2648,2654 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_DEFAULT;
! n->location = @1.begins;
n->raw_expr = $2;
n->cooked_expr = NULL;
$$ = (Node *)n;
*************** ColConstraintElem:
*** 2658,2664 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_FOREIGN;
! n->location = @1;
n->pktable = $2;
n->fk_attrs = NIL;
n->pk_attrs = $3;
--- 2657,2663 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_FOREIGN;
! n->location = @1.begins;
n->pktable = $2;
n->fk_attrs = NIL;
n->pk_attrs = $3;
*************** ConstraintAttr:
*** 2691,2718 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRABLE;
! n->location = @1;
$$ = (Node *)n;
}
| NOT DEFERRABLE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_NOT_DEFERRABLE;
! n->location = @1;
$$ = (Node *)n;
}
| INITIALLY DEFERRED
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRED;
! n->location = @1;
$$ = (Node *)n;
}
| INITIALLY IMMEDIATE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_IMMEDIATE;
! n->location = @1;
$$ = (Node *)n;
}
;
--- 2690,2717 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRABLE;
! n->location = @1.begins;
$$ = (Node *)n;
}
| NOT DEFERRABLE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_NOT_DEFERRABLE;
! n->location = @1.begins;
$$ = (Node *)n;
}
| INITIALLY DEFERRED
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRED;
! n->location = @1.begins;
$$ = (Node *)n;
}
| INITIALLY IMMEDIATE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_IMMEDIATE;
! n->location = @1.begins;
$$ = (Node *)n;
}
;
*************** TableConstraint:
*** 2762,2768 ****
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
! n->location = @1;
$$ = (Node *) n;
}
| ConstraintElem { $$ = $1; }
--- 2761,2767 ----
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
! n->location = @1.begins;
$$ = (Node *) n;
}
| ConstraintElem { $$ = $1; }
*************** ConstraintElem:
*** 2773,2782 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
! n->location = @1;
n->raw_expr = $3;
n->cooked_expr = NULL;
! processCASbits($5, @5, "CHECK",
NULL, NULL, &n->skip_validation,
yyscanner);
n->initially_valid = !n->skip_validation;
--- 2772,2781 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
! n->location = @1.begins;
n->raw_expr = $3;
n->cooked_expr = NULL;
! processCASbits($5, @5.begins, "CHECK",
NULL, NULL, &n->skip_validation,
yyscanner);
n->initially_valid = !n->skip_validation;
*************** ConstraintElem:
*** 2787,2798 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1;
n->keys = $3;
n->options = $5;
n->indexname = NULL;
n->indexspace = $6;
! processCASbits($7, @7, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
--- 2786,2797 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1.begins;
n->keys = $3;
n->options = $5;
n->indexname = NULL;
n->indexspace = $6;
! processCASbits($7, @7.begins, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
*************** ConstraintElem:
*** 2801,2812 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1;
n->keys = NIL;
n->options = NIL;
n->indexname = $2;
n->indexspace = NULL;
! processCASbits($3, @3, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
--- 2800,2811 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
! n->location = @1.begins;
n->keys = NIL;
n->options = NIL;
n->indexname = $2;
n->indexspace = NULL;
! processCASbits($3, @3.begins, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
*************** ConstraintElem:
*** 2816,2827 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1;
n->keys = $4;
n->options = $6;
n->indexname = NULL;
n->indexspace = $7;
! processCASbits($8, @8, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
--- 2815,2826 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1.begins;
n->keys = $4;
n->options = $6;
n->indexname = NULL;
n->indexspace = $7;
! processCASbits($8, @8.begins, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
*************** ConstraintElem:
*** 2830,2841 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1;
n->keys = NIL;
n->options = NIL;
n->indexname = $3;
n->indexspace = NULL;
! processCASbits($4, @4, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
--- 2829,2840 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
! n->location = @1.begins;
n->keys = NIL;
n->options = NIL;
n->indexname = $3;
n->indexspace = NULL;
! processCASbits($4, @4.begins, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
*************** ConstraintElem:
*** 2846,2859 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_EXCLUSION;
! n->location = @1;
n->access_method = $2;
n->exclusions = $4;
n->options = $6;
n->indexname = NULL;
n->indexspace = $7;
n->where_clause = $8;
! processCASbits($9, @9, "EXCLUDE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
--- 2845,2858 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_EXCLUSION;
! n->location = @1.begins;
n->access_method = $2;
n->exclusions = $4;
n->options = $6;
n->indexname = NULL;
n->indexspace = $7;
n->where_clause = $8;
! processCASbits($9, @9.begins, "EXCLUDE",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
$$ = (Node *)n;
*************** ConstraintElem:
*** 2863,2876 ****
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_FOREIGN;
! n->location = @1;
n->pktable = $7;
n->fk_attrs = $4;
n->pk_attrs = $8;
n->fk_matchtype = $9;
n->fk_upd_action = (char) ($10 >> 8);
n->fk_del_action = (char) ($10 & 0xFF);
! processCASbits($11, @11, "FOREIGN KEY",
&n->deferrable, &n->initdeferred,
&n->skip_validation,
yyscanner);
--- 2862,2875 ----
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_FOREIGN;
! n->location = @1.begins;
n->pktable = $7;
n->fk_attrs = $4;
n->pk_attrs = $8;
n->fk_matchtype = $9;
n->fk_upd_action = (char) ($10 >> 8);
n->fk_del_action = (char) ($10 & 0xFF);
! processCASbits($11, @11.begins, "FOREIGN KEY",
&n->deferrable, &n->initdeferred,
&n->skip_validation,
yyscanner);
*************** key_match: MATCH FULL
*** 2904,2910 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MATCH PARTIAL not yet implemented"),
! parser_errposition(@1)));
$$ = FKCONSTR_MATCH_PARTIAL;
}
| MATCH SIMPLE
--- 2903,2909 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MATCH PARTIAL not yet implemented"),
! parser_errposition(@1.begins)));
$$ = FKCONSTR_MATCH_PARTIAL;
}
| MATCH SIMPLE
*************** CreateTrigStmt:
*** 4029,4035 ****
n->columns = (List *) lsecond($6);
n->whenClause = $14;
n->isconstraint = TRUE;
! processCASbits($10, @10, "TRIGGER",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
n->constrrel = $9;
--- 4028,4034 ----
n->columns = (List *) lsecond($6);
n->whenClause = $14;
n->isconstraint = TRUE;
! processCASbits($10, @10.begins, "TRIGGER",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
n->constrrel = $9;
*************** ConstraintAttributeSpec:
*** 4150,4163 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
! parser_errposition(@2)));
/* generic message for other conflicts */
if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) ||
(newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting constraint properties"),
! parser_errposition(@2)));
$$ = newspec;
}
;
--- 4149,4162 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
! parser_errposition(@2.begins)));
/* generic message for other conflicts */
if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) ||
(newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting constraint properties"),
! parser_errposition(@2.begins)));
$$ = newspec;
}
;
*************** CreateAssertStmt:
*** 4211,4217 ****
n->trigname = $3;
n->args = list_make1($6);
n->isconstraint = TRUE;
! processCASbits($8, @8, "ASSERTION",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
--- 4210,4216 ----
n->trigname = $3;
n->args = list_make1($6);
n->isconstraint = TRUE;
! processCASbits($8, @8.begins, "ASSERTION",
&n->deferrable, &n->initdeferred, NULL,
yyscanner);
*************** DefineStmt:
*** 4304,4310 ****
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
/* can't use qualified_name, sigh */
! n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner);
n->coldeflist = $6;
$$ = (Node *)n;
}
--- 4303,4309 ----
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
/* can't use qualified_name, sigh */
! n->typevar = makeRangeVarFromAnyName($3, @3.begins, yyscanner);
n->coldeflist = $6;
$$ = (Node *)n;
}
*************** opt_recheck: RECHECK
*** 4578,4584 ****
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RECHECK is no longer required"),
errhint("Update your data type."),
! parser_errposition(@1)));
$$ = TRUE;
}
| /*EMPTY*/ { $$ = FALSE; }
--- 4577,4583 ----
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RECHECK is no longer required"),
errhint("Update your data type."),
! parser_errposition(@1.begins)));
$$ = TRUE;
}
| /*EMPTY*/ { $$ = FALSE; }
*************** CreateFunctionStmt:
*** 5826,5832 ****
n->funcname = $4;
n->parameters = mergeTableFuncParameters($5, $9);
n->returnType = TableFuncTypeName($9);
! n->returnType->location = @7;
n->options = $11;
n->withClause = $12;
$$ = (Node *)n;
--- 5825,5831 ----
n->funcname = $4;
n->parameters = mergeTableFuncParameters($5, $9);
n->returnType = TableFuncTypeName($9);
! n->returnType->location = @7.begins;
n->options = $11;
n->withClause = $12;
$$ = (Node *)n;
*************** func_type: Typename { $$ = $1; }
*** 5967,5980 ****
{
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
$$->pct_type = true;
! $$->location = @1;
}
| SETOF type_function_name attrs '%' TYPE_P
{
$$ = makeTypeNameFromNameList(lcons(makeString($2), $3));
$$->pct_type = true;
$$->setof = TRUE;
! $$->location = @2;
}
;
--- 5966,5979 ----
{
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
$$->pct_type = true;
! $$->location = @1.begins;
}
| SETOF type_function_name attrs '%' TYPE_P
{
$$ = makeTypeNameFromNameList(lcons(makeString($2), $3));
$$->pct_type = true;
$$->setof = TRUE;
! $$->location = @2.begins;
}
;
*************** oper_argtypes:
*** 6231,6237 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing argument"),
errhint("Use NONE to denote the missing argument of a unary operator."),
! parser_errposition(@3)));
}
| '(' Typename ',' Typename ')'
{ $$ = list_make2($2, $4); }
--- 6230,6236 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing argument"),
errhint("Use NONE to denote the missing argument of a unary operator."),
! parser_errposition(@3.begins)));
}
| '(' Typename ',' Typename ')'
{ $$ = list_make2($2, $4); }
*************** RenameStmt: ALTER AGGREGATE func_name ag
*** 6662,6668 ****
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_ATTRIBUTE;
n->relationType = OBJECT_TYPE;
! n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
n->subname = $6;
n->newname = $8;
n->behavior = $9;
--- 6661,6667 ----
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_ATTRIBUTE;
n->relationType = OBJECT_TYPE;
! n->relation = makeRangeVarFromAnyName($3, @3.begins, yyscanner);
n->subname = $6;
n->newname = $8;
n->behavior = $9;
*************** opt_transaction: WORK {}
*** 7257,7275 ****
transaction_mode_item:
ISOLATION LEVEL iso_level
{ $$ = makeDefElem("transaction_isolation",
! makeStringConst($3, @3)); }
| READ ONLY
{ $$ = makeDefElem("transaction_read_only",
! makeIntConst(TRUE, @1)); }
| READ WRITE
{ $$ = makeDefElem("transaction_read_only",
! makeIntConst(FALSE, @1)); }
| DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
! makeIntConst(TRUE, @1)); }
| NOT DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
! makeIntConst(FALSE, @1)); }
;
/* Syntax with commas is SQL-spec, without commas is Postgres historical */
--- 7256,7274 ----
transaction_mode_item:
ISOLATION LEVEL iso_level
{ $$ = makeDefElem("transaction_isolation",
! makeStringConst($3, @3.begins, @3.length)); }
| READ ONLY
{ $$ = makeDefElem("transaction_read_only",
! makeIntConst(TRUE, @1.begins, @1.length)); }
| READ WRITE
{ $$ = makeDefElem("transaction_read_only",
! makeIntConst(FALSE, @1.begins, @1.length)); }
| DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
! makeIntConst(TRUE, @1.begins, @1.length)); }
| NOT DEFERRABLE
{ $$ = makeDefElem("transaction_deferrable",
! makeIntConst(FALSE, @1.begins, @1.length)); }
;
/* Syntax with commas is SQL-spec, without commas is Postgres historical */
*************** insert_column_item:
*** 8116,8122 ****
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL;
! $$->location = @1;
}
;
--- 8115,8121 ----
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL;
! $$->location = @1.begins;
}
;
*************** multiple_set_clause:
*** 8246,8252 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("number of columns does not match number of values"),
! parser_errposition(@1)));
forboth(col_cell, $2, val_cell, $5)
{
ResTarget *res_col = (ResTarget *) lfirst(col_cell);
--- 8245,8251 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("number of columns does not match number of values"),
! parser_errposition(@1.begins)));
forboth(col_cell, $2, val_cell, $5)
{
ResTarget *res_col = (ResTarget *) lfirst(col_cell);
*************** set_target:
*** 8266,8272 ****
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL; /* upper production sets this */
! $$->location = @1;
}
;
--- 8265,8271 ----
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL; /* upper production sets this */
! $$->location = @1.begins;
}
;
*************** with_clause:
*** 8523,8536 ****
$$ = makeNode(WithClause);
$$->ctes = $2;
$$->recursive = false;
! $$->location = @1;
}
| WITH RECURSIVE cte_list
{
$$ = makeNode(WithClause);
$$->ctes = $3;
$$->recursive = true;
! $$->location = @1;
}
;
--- 8522,8535 ----
$$ = makeNode(WithClause);
$$->ctes = $2;
$$->recursive = false;
! $$->location = @1.begins;
}
| WITH RECURSIVE cte_list
{
$$ = makeNode(WithClause);
$$->ctes = $3;
$$->recursive = true;
! $$->location = @1.begins;
}
;
*************** common_table_expr: name opt_name_list A
*** 8545,8551 ****
n->ctename = $1;
n->aliascolnames = $2;
n->ctequery = $5;
! n->location = @1;
$$ = (Node *) n;
}
;
--- 8544,8550 ----
n->ctename = $1;
n->aliascolnames = $2;
n->ctequery = $5;
! n->location = @1.begins;
$$ = (Node *) n;
}
;
*************** sortby: a_expr USING qual_all_Op opt_nu
*** 8662,8668 ****
$$->sortby_dir = SORTBY_USING;
$$->sortby_nulls = $4;
$$->useOp = $3;
! $$->location = @3;
}
| a_expr opt_asc_desc opt_nulls_order
{
--- 8661,8667 ----
$$->sortby_dir = SORTBY_USING;
$$->sortby_nulls = $4;
$$->useOp = $3;
! $$->location = @3.begins;
}
| a_expr opt_asc_desc opt_nulls_order
{
*************** limit_clause:
*** 8698,8704 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("LIMIT #,# syntax is not supported"),
errhint("Use separate LIMIT and OFFSET clauses."),
! parser_errposition(@1)));
}
/* SQL:2008 syntax */
| FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
--- 8697,8703 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("LIMIT #,# syntax is not supported"),
errhint("Use separate LIMIT and OFFSET clauses."),
! parser_errposition(@1.begins)));
}
/* SQL:2008 syntax */
| FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
*************** select_limit_value:
*** 8718,8724 ****
| ALL
{
/* LIMIT ALL is represented as a NULL constant */
! $$ = makeNullAConst(@1);
}
;
--- 8717,8723 ----
| ALL
{
/* LIMIT ALL is represented as a NULL constant */
! $$ = makeNullAConst(@1.begins, @1.length);
}
;
*************** select_offset_value:
*** 8733,8741 ****
* default to 1.
*/
opt_select_fetch_first_value:
! SignedIconst { $$ = makeIntConst($1, @1); }
| '(' a_expr ')' { $$ = $2; }
! | /*EMPTY*/ { $$ = makeIntConst(1, -1); }
;
/*
--- 8732,8740 ----
* default to 1.
*/
opt_select_fetch_first_value:
! SignedIconst { $$ = makeIntConst($1, @1.begins, @1.length); }
| '(' a_expr ')' { $$ = $2; }
! | /*EMPTY*/ { $$ = makeIntConst(1, -1, -1); }
;
/*
*************** table_ref: relation_expr
*** 8917,8929 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("VALUES in FROM must have an alias"),
errhint("For example, FROM (VALUES ...) [AS] foo."),
! parser_errposition(@1)));
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery in FROM must have an alias"),
errhint("For example, FROM (SELECT ...) [AS] foo."),
! parser_errposition(@1)));
$$ = NULL;
}
| select_with_parens alias_clause
--- 8916,8928 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("VALUES in FROM must have an alias"),
errhint("For example, FROM (VALUES ...) [AS] foo."),
! parser_errposition(@1.begins)));
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery in FROM must have an alias"),
errhint("For example, FROM (SELECT ...) [AS] foo."),
! parser_errposition(@1.begins)));
$$ = NULL;
}
| select_with_parens alias_clause
*************** SimpleTypename:
*** 9283,9294 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1)));
! $$->typmods = lappend($5, makeIntConst($3, @3));
}
else
! $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
! makeIntConst($3, @3));
}
;
--- 9282,9293 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1.begins)));
! $$->typmods = lappend($5, makeIntConst($3, @3.begins, @3.length));
}
else
! $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1, -1),
! makeIntConst($3, @3.begins, @3.length));
}
;
*************** GenericType:
*** 9322,9334 ****
{
$$ = makeTypeName($1);
$$->typmods = $2;
! $$->location = @1;
}
| type_function_name attrs opt_type_modifiers
{
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
$$->typmods = $3;
! $$->location = @1;
}
;
--- 9321,9333 ----
{
$$ = makeTypeName($1);
$$->typmods = $2;
! $$->location = @1.begins;
}
| type_function_name attrs opt_type_modifiers
{
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
$$->typmods = $3;
! $$->location = @1.begins;
}
;
*************** opt_type_modifiers: '(' expr_list ')'
*** 9342,9401 ****
Numeric: INT_P
{
$$ = SystemTypeName("int4");
! $$->location = @1;
}
| INTEGER
{
$$ = SystemTypeName("int4");
! $$->location = @1;
}
| SMALLINT
{
$$ = SystemTypeName("int2");
! $$->location = @1;
}
| BIGINT
{
$$ = SystemTypeName("int8");
! $$->location = @1;
}
| REAL
{
$$ = SystemTypeName("float4");
! $$->location = @1;
}
| FLOAT_P opt_float
{
$$ = $2;
! $$->location = @1;
}
| DOUBLE_P PRECISION
{
$$ = SystemTypeName("float8");
! $$->location = @1;
}
| DECIMAL_P opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1;
}
| DEC opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1;
}
| NUMERIC opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1;
}
| BOOLEAN_P
{
$$ = SystemTypeName("bool");
! $$->location = @1;
}
;
--- 9341,9400 ----
Numeric: INT_P
{
$$ = SystemTypeName("int4");
! $$->location = @1.begins;
}
| INTEGER
{
$$ = SystemTypeName("int4");
! $$->location = @1.begins;
}
| SMALLINT
{
$$ = SystemTypeName("int2");
! $$->location = @1.begins;
}
| BIGINT
{
$$ = SystemTypeName("int8");
! $$->location = @1.begins;
}
| REAL
{
$$ = SystemTypeName("float4");
! $$->location = @1.begins;
}
| FLOAT_P opt_float
{
$$ = $2;
! $$->location = @1.begins;
}
| DOUBLE_P PRECISION
{
$$ = SystemTypeName("float8");
! $$->location = @1.begins;
}
| DECIMAL_P opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1.begins;
}
| DEC opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1.begins;
}
| NUMERIC opt_type_modifiers
{
$$ = SystemTypeName("numeric");
$$->typmods = $2;
! $$->location = @1.begins;
}
| BOOLEAN_P
{
$$ = SystemTypeName("bool");
! $$->location = @1.begins;
}
;
*************** opt_float: '(' Iconst ')'
*** 9409,9415 ****
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("precision for type float must be at least 1 bit"),
! parser_errposition(@2)));
else if ($2 <= 24)
$$ = SystemTypeName("float4");
else if ($2 <= 53)
--- 9408,9414 ----
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("precision for type float must be at least 1 bit"),
! parser_errposition(@2.begins)));
else if ($2 <= 24)
$$ = SystemTypeName("float4");
else if ($2 <= 53)
*************** opt_float: '(' Iconst ')'
*** 9418,9424 ****
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("precision for type float must be less than 54 bits"),
! parser_errposition(@2)));
}
| /*EMPTY*/
{
--- 9417,9423 ----
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("precision for type float must be less than 54 bits"),
! parser_errposition(@2.begins)));
}
| /*EMPTY*/
{
*************** BitWithLength:
*** 9461,9467 ****
typname = $2 ? "varbit" : "bit";
$$ = SystemTypeName(typname);
$$->typmods = $4;
! $$->location = @1;
}
;
--- 9460,9466 ----
typname = $2 ? "varbit" : "bit";
$$ = SystemTypeName(typname);
$$->typmods = $4;
! $$->location = @1.begins;
}
;
*************** BitWithoutLength:
*** 9476,9484 ****
else
{
$$ = SystemTypeName("bit");
! $$->typmods = list_make1(makeIntConst(1, -1));
}
! $$->location = @1;
}
;
--- 9475,9483 ----
else
{
$$ = SystemTypeName("bit");
! $$->typmods = list_make1(makeIntConst(1, -1, -1));
}
! $$->location = @1.begins;
}
;
*************** CharacterWithLength: character '(' Icon
*** 9528,9535 ****
}
$$ = SystemTypeName($1);
! $$->typmods = list_make1(makeIntConst($3, @3));
! $$->location = @1;
}
;
--- 9527,9534 ----
}
$$ = SystemTypeName($1);
! $$->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$->location = @1.begins;
}
;
*************** CharacterWithoutLength: character opt_c
*** 9550,9558 ****
/* char defaults to char(1), varchar to no limit */
if (strcmp($1, "bpchar") == 0)
! $$->typmods = list_make1(makeIntConst(1, -1));
! $$->location = @1;
}
;
--- 9549,9557 ----
/* char defaults to char(1), varchar to no limit */
if (strcmp($1, "bpchar") == 0)
! $$->typmods = list_make1(makeIntConst(1, -1, -1));
! $$->location = @1.begins;
}
;
*************** ConstDatetime:
*** 9590,9597 ****
$$ = SystemTypeName("timestamptz");
else
$$ = SystemTypeName("timestamp");
! $$->typmods = list_make1(makeIntConst($3, @3));
! $$->location = @1;
}
| TIMESTAMP opt_timezone
{
--- 9589,9596 ----
$$ = SystemTypeName("timestamptz");
else
$$ = SystemTypeName("timestamp");
! $$->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$->location = @1.begins;
}
| TIMESTAMP opt_timezone
{
*************** ConstDatetime:
*** 9599,9605 ****
$$ = SystemTypeName("timestamptz");
else
$$ = SystemTypeName("timestamp");
! $$->location = @1;
}
| TIME '(' Iconst ')' opt_timezone
{
--- 9598,9604 ----
$$ = SystemTypeName("timestamptz");
else
$$ = SystemTypeName("timestamp");
! $$->location = @1.begins;
}
| TIME '(' Iconst ')' opt_timezone
{
*************** ConstDatetime:
*** 9607,9614 ****
$$ = SystemTypeName("timetz");
else
$$ = SystemTypeName("time");
! $$->typmods = list_make1(makeIntConst($3, @3));
! $$->location = @1;
}
| TIME opt_timezone
{
--- 9606,9613 ----
$$ = SystemTypeName("timetz");
else
$$ = SystemTypeName("time");
! $$->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$->location = @1.begins;
}
| TIME opt_timezone
{
*************** ConstDatetime:
*** 9616,9622 ****
$$ = SystemTypeName("timetz");
else
$$ = SystemTypeName("time");
! $$->location = @1;
}
;
--- 9615,9621 ----
$$ = SystemTypeName("timetz");
else
$$ = SystemTypeName("time");
! $$->location = @1.begins;
}
;
*************** ConstInterval:
*** 9624,9630 ****
INTERVAL
{
$$ = SystemTypeName("interval");
! $$->location = @1;
}
;
--- 9623,9629 ----
INTERVAL
{
$$ = SystemTypeName("interval");
! $$->location = @1.begins;
}
;
*************** opt_timezone:
*** 9636,9667 ****
opt_interval:
YEAR_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR), @1)); }
| MONTH_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(MONTH), @1)); }
| DAY_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY), @1)); }
| HOUR_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR), @1)); }
| MINUTE_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), @1)); }
| interval_second
{ $$ = $1; }
| YEAR_P TO MONTH_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR) |
! INTERVAL_MASK(MONTH), @1));
}
| DAY_P TO HOUR_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
! INTERVAL_MASK(HOUR), @1));
}
| DAY_P TO MINUTE_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
! INTERVAL_MASK(MINUTE), @1));
}
| DAY_P TO interval_second
{
--- 9635,9666 ----
opt_interval:
YEAR_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR), @1.begins, @1.length)); }
| MONTH_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(MONTH), @1.begins, @1.length)); }
| DAY_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY), @1.begins, @1.length)); }
| HOUR_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR), @1.begins, @1.length)); }
| MINUTE_P
! { $$ = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), @1.begins, @1.length)); }
| interval_second
{ $$ = $1; }
| YEAR_P TO MONTH_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR) |
! INTERVAL_MASK(MONTH), @1.begins, @1.length));
}
| DAY_P TO HOUR_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
! INTERVAL_MASK(HOUR), @1.begins, @1.length));
}
| DAY_P TO MINUTE_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
! INTERVAL_MASK(MINUTE), @1.begins, @1.length));
}
| DAY_P TO interval_second
{
*************** opt_interval:
*** 9669,9693 ****
linitial($$) = makeIntConst(INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1);
}
| HOUR_P TO MINUTE_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR) |
! INTERVAL_MASK(MINUTE), @1));
}
| HOUR_P TO interval_second
{
$$ = $3;
linitial($$) = makeIntConst(INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1);
}
| MINUTE_P TO interval_second
{
$$ = $3;
linitial($$) = makeIntConst(INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1);
}
| /*EMPTY*/
{ $$ = NIL; }
--- 9668,9692 ----
linitial($$) = makeIntConst(INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1.begins, @1.length);
}
| HOUR_P TO MINUTE_P
{
$$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR) |
! INTERVAL_MASK(MINUTE), @1.begins, @1.length));
}
| HOUR_P TO interval_second
{
$$ = $3;
linitial($$) = makeIntConst(INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1.begins, @1.length);
}
| MINUTE_P TO interval_second
{
$$ = $3;
linitial($$) = makeIntConst(INTERVAL_MASK(MINUTE) |
! INTERVAL_MASK(SECOND), @1.begins, @1.length);
}
| /*EMPTY*/
{ $$ = NIL; }
*************** opt_interval:
*** 9696,9707 ****
interval_second:
SECOND_P
{
! $$ = list_make1(makeIntConst(INTERVAL_MASK(SECOND), @1));
}
| SECOND_P '(' Iconst ')'
{
! $$ = list_make2(makeIntConst(INTERVAL_MASK(SECOND), @1),
! makeIntConst($3, @3));
}
;
--- 9695,9706 ----
interval_second:
SECOND_P
{
! $$ = list_make1(makeIntConst(INTERVAL_MASK(SECOND), @1.begins, @1.length));
}
| SECOND_P '(' Iconst ')'
{
! $$ = list_make2(makeIntConst(INTERVAL_MASK(SECOND), @1.begins, @1.length),
! makeIntConst($3, @3.begins, @3.length));
}
;
*************** interval_second:
*** 9730,9742 ****
*/
a_expr: c_expr { $$ = $1; }
| a_expr TYPECAST Typename
! { $$ = makeTypeCast($1, $3, @2); }
| a_expr COLLATE any_name
{
CollateClause *n = makeNode(CollateClause);
n->arg = $1;
n->collname = $3;
! n->location = @2;
$$ = (Node *) n;
}
| a_expr AT TIME ZONE a_expr %prec AT
--- 9729,9741 ----
*/
a_expr: c_expr { $$ = $1; }
| a_expr TYPECAST Typename
! { $$ = makeTypeCast($1, $3, @2.begins, @2.length); }
| a_expr COLLATE any_name
{
CollateClause *n = makeNode(CollateClause);
n->arg = $1;
n->collname = $3;
! n->location = @2.begins;
$$ = (Node *) n;
}
| a_expr AT TIME ZONE a_expr %prec AT
*************** a_expr: c_expr { $$ = $1; }
*** 9749,9755 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
$$ = (Node *) n;
}
/*
--- 9748,9754 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
$$ = (Node *) n;
}
/*
*************** a_expr: c_expr { $$ = $1; }
*** 9762,9805 ****
* also to b_expr and to the MathOp list above.
*/
| '+' a_expr %prec UMINUS
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
| '-' a_expr %prec UMINUS
! { $$ = doNegate($2, @1); }
| a_expr '+' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }
| a_expr '-' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }
| a_expr '*' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }
| a_expr '/' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }
| a_expr '%' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }
| a_expr '^' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }
| a_expr '<' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }
| a_expr '>' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
| a_expr '=' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
| a_expr qual_Op a_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
| qual_Op a_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }
| a_expr qual_Op %prec POSTFIXOP
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }
| a_expr AND a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3, @2); }
| a_expr OR a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3, @2); }
| NOT a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2, @1); }
| a_expr LIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3, @2); }
| a_expr LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
--- 9761,9804 ----
* also to b_expr and to the MathOp list above.
*/
| '+' a_expr %prec UMINUS
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1.begins); }
| '-' a_expr %prec UMINUS
! { $$ = doNegate($2, @1.begins, @1.length); }
| a_expr '+' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2.begins); }
| a_expr '-' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2.begins); }
| a_expr '*' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2.begins); }
| a_expr '/' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2.begins); }
| a_expr '%' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2.begins); }
| a_expr '^' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2.begins); }
| a_expr '<' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2.begins); }
| a_expr '>' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2.begins); }
| a_expr '=' a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2.begins); }
| a_expr qual_Op a_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2.begins); }
| qual_Op a_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1.begins); }
| a_expr qual_Op %prec POSTFIXOP
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2.begins); }
| a_expr AND a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, $1, $3, @2.begins); }
| a_expr OR a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, $1, $3, @2.begins); }
| NOT a_expr
! { $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, $2, @1.begins); }
| a_expr LIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3, @2.begins); }
| a_expr LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
*************** a_expr: c_expr { $$ = $1; }
*** 9810,9820 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2);
}
| a_expr NOT LIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2); }
| a_expr NOT LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
--- 9809,9819 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2.begins);
}
| a_expr NOT LIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2.begins); }
| a_expr NOT LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
*************** a_expr: c_expr { $$ = $1; }
*** 9825,9835 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2);
}
| a_expr ILIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3, @2); }
| a_expr ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
--- 9824,9834 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2.begins);
}
| a_expr ILIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3, @2.begins); }
| a_expr ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
*************** a_expr: c_expr { $$ = $1; }
*** 9840,9850 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2);
}
| a_expr NOT ILIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2); }
| a_expr NOT ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
--- 9839,9849 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2.begins);
}
| a_expr NOT ILIKE a_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2.begins); }
| a_expr NOT ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
*************** a_expr: c_expr { $$ = $1; }
*** 9855,9876 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2);
}
| a_expr SIMILAR TO a_expr %prec SIMILAR
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
! n->args = list_make2($4, makeNullAConst(-1));
n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2);
}
| a_expr SIMILAR TO a_expr ESCAPE a_expr
{
--- 9854,9875 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2.begins);
}
| a_expr SIMILAR TO a_expr %prec SIMILAR
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
! n->args = list_make2($4, makeNullAConst(-1, -1));
n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2.begins);
}
| a_expr SIMILAR TO a_expr ESCAPE a_expr
{
*************** a_expr: c_expr { $$ = $1; }
*** 9882,9902 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr %prec SIMILAR
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
! n->args = list_make2($5, makeNullAConst(-1));
n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
{
--- 9881,9901 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2.begins);
}
| a_expr NOT SIMILAR TO a_expr %prec SIMILAR
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
! n->args = list_make2($5, makeNullAConst(-1, -1));
n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2.begins);
}
| a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
{
*************** a_expr: c_expr { $$ = $1; }
*** 9908,9915 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
/* NullTest clause
--- 9907,9914 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @2.begins;
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2.begins);
}
/* NullTest clause
*************** a_expr: c_expr { $$ = $1; }
*** 9951,9957 ****
}
| row OVERLAPS row
{
! $$ = (Node *)makeOverlaps($1, $3, @2, yyscanner);
}
| a_expr IS TRUE_P %prec IS
{
--- 9950,9956 ----
}
| row OVERLAPS row
{
! $$ = (Node *)makeOverlaps($1, $3, @2.begins, yyscanner);
}
| a_expr IS TRUE_P %prec IS
{
*************** a_expr: c_expr { $$ = $1; }
*** 9997,10019 ****
}
| a_expr IS DISTINCT FROM a_expr %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2);
}
| a_expr IS NOT DISTINCT FROM a_expr %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
(Node *) makeSimpleA_Expr(AEXPR_DISTINCT,
! "=", $1, $6, @2),
! @2);
}
| a_expr IS OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2);
}
| a_expr IS NOT OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2);
}
/*
* Ideally we would not use hard-wired operators below but
--- 9996,10018 ----
}
| a_expr IS DISTINCT FROM a_expr %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2.begins);
}
| a_expr IS NOT DISTINCT FROM a_expr %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
(Node *) makeSimpleA_Expr(AEXPR_DISTINCT,
! "=", $1, $6, @2.begins),
! @2.begins);
}
| a_expr IS OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2.begins);
}
| a_expr IS NOT OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2.begins);
}
/*
* Ideally we would not use hard-wired operators below but
*************** a_expr: c_expr { $$ = $1; }
*** 10024,10065 ****
| a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2),
! @2);
}
| a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2),
! @2);
}
| a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeA_Expr(AEXPR_AND, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2),
! @2),
(Node *) makeA_Expr(AEXPR_AND, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4, @2),
! @2),
! @2);
}
| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2),
! @2),
(Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2),
! @2),
! @2);
}
| a_expr IN_P in_expr
{
--- 10023,10065 ----
| a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2.begins),
! @2.begins);
}
| a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2.begins),
! @2.begins);
}
| a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_OR, NIL,
(Node *) makeA_Expr(AEXPR_AND, NIL,
!
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $4, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2.begins),
! @2.begins),
(Node *) makeA_Expr(AEXPR_AND, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4, @2.begins),
! @2.begins),
! @2.begins);
}
| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
(Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2.begins),
! @2.begins),
(Node *) makeA_Expr(AEXPR_OR, NIL,
! (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2.begins),
! (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2.begins),
! @2.begins),
! @2.begins);
}
| a_expr IN_P in_expr
{
*************** a_expr: c_expr { $$ = $1; }
*** 10071,10083 ****
n->subLinkType = ANY_SUBLINK;
n->testexpr = $1;
n->operName = list_make1(makeString("="));
! n->location = @2;
$$ = (Node *)n;
}
else
{
/* generate scalar IN expression */
! $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2);
}
}
| a_expr NOT IN_P in_expr
--- 10071,10083 ----
n->subLinkType = ANY_SUBLINK;
n->testexpr = $1;
n->operName = list_make1(makeString("="));
! n->location = @2.begins;
$$ = (Node *)n;
}
else
{
/* generate scalar IN expression */
! $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2.begins);
}
}
| a_expr NOT IN_P in_expr
*************** a_expr: c_expr { $$ = $1; }
*** 10091,10104 ****
n->subLinkType = ANY_SUBLINK;
n->testexpr = $1;
n->operName = list_make1(makeString("="));
! n->location = @3;
/* Stick a NOT on top */
! $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2);
}
else
{
/* generate scalar NOT IN expression */
! $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2);
}
}
| a_expr subquery_Op sub_type select_with_parens %prec Op
--- 10091,10104 ----
n->subLinkType = ANY_SUBLINK;
n->testexpr = $1;
n->operName = list_make1(makeString("="));
! n->location = @3.begins;
/* Stick a NOT on top */
! $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2.begins);
}
else
{
/* generate scalar NOT IN expression */
! $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2.begins);
}
}
| a_expr subquery_Op sub_type select_with_parens %prec Op
*************** a_expr: c_expr { $$ = $1; }
*** 10108,10122 ****
n->testexpr = $1;
n->operName = $2;
n->subselect = $4;
! n->location = @2;
$$ = (Node *)n;
}
| a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
{
if ($3 == ANY_SUBLINK)
! $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2);
else
! $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2);
}
| UNIQUE select_with_parens
{
--- 10108,10122 ----
n->testexpr = $1;
n->operName = $2;
n->subselect = $4;
! n->location = @2.begins;
$$ = (Node *)n;
}
| a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
{
if ($3 == ANY_SUBLINK)
! $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2.begins);
else
! $$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2.begins);
}
| UNIQUE select_with_parens
{
*************** a_expr: c_expr { $$ = $1; }
*** 10132,10150 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("UNIQUE predicate is not yet implemented"),
! parser_errposition(@1)));
}
| a_expr IS DOCUMENT_P %prec IS
{
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2);
}
| a_expr IS NOT DOCUMENT_P %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2),
! @2);
}
;
--- 10132,10150 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("UNIQUE predicate is not yet implemented"),
! parser_errposition(@1.begins)));
}
| a_expr IS DOCUMENT_P %prec IS
{
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2.begins);
}
| a_expr IS NOT DOCUMENT_P %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2.begins),
! @2.begins);
}
;
*************** a_expr: c_expr { $$ = $1; }
*** 10160,10222 ****
b_expr: c_expr
{ $$ = $1; }
| b_expr TYPECAST Typename
! { $$ = makeTypeCast($1, $3, @2); }
| '+' b_expr %prec UMINUS
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1); }
| '-' b_expr %prec UMINUS
! { $$ = doNegate($2, @1); }
| b_expr '+' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2); }
| b_expr '-' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2); }
| b_expr '*' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2); }
| b_expr '/' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2); }
| b_expr '%' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2); }
| b_expr '^' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2); }
| b_expr '<' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2); }
| b_expr '>' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
| b_expr '=' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
| b_expr qual_Op b_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
| qual_Op b_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }
| b_expr qual_Op %prec POSTFIXOP
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }
| b_expr IS DISTINCT FROM b_expr %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2);
}
| b_expr IS NOT DISTINCT FROM b_expr %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL,
! NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6, @2), @2);
}
| b_expr IS OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2);
}
| b_expr IS NOT OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2);
}
| b_expr IS DOCUMENT_P %prec IS
{
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2);
}
| b_expr IS NOT DOCUMENT_P %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2),
! @2);
}
;
--- 10160,10222 ----
b_expr: c_expr
{ $$ = $1; }
| b_expr TYPECAST Typename
! { $$ = makeTypeCast($1, $3, @2.begins, @2.length); }
| '+' b_expr %prec UMINUS
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, $2, @1.begins); }
| '-' b_expr %prec UMINUS
! { $$ = doNegate($2, @1.begins, @1.length); }
| b_expr '+' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, $3, @2.begins); }
| b_expr '-' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "-", $1, $3, @2.begins); }
| b_expr '*' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "*", $1, $3, @2.begins); }
| b_expr '/' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "/", $1, $3, @2.begins); }
| b_expr '%' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3, @2.begins); }
| b_expr '^' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "^", $1, $3, @2.begins); }
| b_expr '<' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $3, @2.begins); }
| b_expr '>' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2.begins); }
| b_expr '=' b_expr
! { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2.begins); }
| b_expr qual_Op b_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2.begins); }
| qual_Op b_expr %prec Op
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1.begins); }
| b_expr qual_Op %prec POSTFIXOP
! { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2.begins); }
| b_expr IS DISTINCT FROM b_expr %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2.begins);
}
| b_expr IS NOT DISTINCT FROM b_expr %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL,
! NULL, (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $6, @2.begins), @2.begins);
}
| b_expr IS OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2.begins);
}
| b_expr IS NOT OF '(' type_list ')' %prec IS
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2.begins);
}
| b_expr IS DOCUMENT_P %prec IS
{
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2.begins);
}
| b_expr IS NOT DOCUMENT_P %prec IS
{
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
makeXmlExpr(IS_DOCUMENT, NULL, NIL,
! list_make1($1), @2.begins),
! @2.begins);
}
;
*************** c_expr: columnref { $$ = $1; }
*** 10234,10240 ****
{
ParamRef *p = makeNode(ParamRef);
p->number = $1;
! p->location = @1;
if ($2)
{
A_Indirection *n = makeNode(A_Indirection);
--- 10234,10240 ----
{
ParamRef *p = makeNode(ParamRef);
p->number = $1;
! p->location = @1.begins;
if ($2)
{
A_Indirection *n = makeNode(A_Indirection);
*************** c_expr: columnref { $$ = $1; }
*** 10268,10274 ****
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $1;
! n->location = @1;
$$ = (Node *)n;
}
| EXISTS select_with_parens
--- 10268,10274 ----
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $1;
! n->location = @1.begins;
$$ = (Node *)n;
}
| EXISTS select_with_parens
*************** c_expr: columnref { $$ = $1; }
*** 10278,10284 ****
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $2;
! n->location = @1;
$$ = (Node *)n;
}
| ARRAY select_with_parens
--- 10278,10284 ----
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $2;
! n->location = @1.begins;
$$ = (Node *)n;
}
| ARRAY select_with_parens
*************** c_expr: columnref { $$ = $1; }
*** 10288,10294 ****
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $2;
! n->location = @1;
$$ = (Node *)n;
}
| ARRAY array_expr
--- 10288,10294 ----
n->testexpr = NULL;
n->operName = NIL;
n->subselect = $2;
! n->location = @1.begins;
$$ = (Node *)n;
}
| ARRAY array_expr
*************** c_expr: columnref { $$ = $1; }
*** 10296,10302 ****
A_ArrayExpr *n = (A_ArrayExpr *) $2;
Assert(IsA(n, A_ArrayExpr));
/* point outermost A_ArrayExpr to the ARRAY keyword */
! n->location = @1;
$$ = (Node *)n;
}
| row
--- 10296,10302 ----
A_ArrayExpr *n = (A_ArrayExpr *) $2;
Assert(IsA(n, A_ArrayExpr));
/* point outermost A_ArrayExpr to the ARRAY keyword */
! n->location = @1.begins;
$$ = (Node *)n;
}
| row
*************** c_expr: columnref { $$ = $1; }
*** 10304,10310 ****
RowExpr *r = makeNode(RowExpr);
r->args = $1;
r->row_typeid = InvalidOid; /* not analyzed yet */
! r->location = @1;
$$ = (Node *)r;
}
;
--- 10304,10310 ----
RowExpr *r = makeNode(RowExpr);
r->args = $1;
r->row_typeid = InvalidOid; /* not analyzed yet */
! r->location = @1.begins;
$$ = (Node *)r;
}
;
*************** func_expr: func_name '(' ')' over_clause
*** 10327,10333 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $4;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' func_arg_list ')' over_clause
--- 10327,10333 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $4;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' func_arg_list ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10340,10346 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $5;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' VARIADIC func_arg_expr ')' over_clause
--- 10340,10346 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $5;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' VARIADIC func_arg_expr ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10353,10359 ****
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->over = $6;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
--- 10353,10359 ----
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->over = $6;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10366,10372 ****
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->over = $8;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' func_arg_list sort_clause ')' over_clause
--- 10366,10372 ----
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->over = $8;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' func_arg_list sort_clause ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10379,10385 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $6;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
--- 10379,10385 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $6;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10396,10402 ****
*/
n->func_variadic = FALSE;
n->over = $7;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
--- 10396,10402 ----
*/
n->func_variadic = FALSE;
n->over = $7;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10409,10415 ****
n->agg_distinct = TRUE;
n->func_variadic = FALSE;
n->over = $7;
! n->location = @1;
$$ = (Node *)n;
}
| func_name '(' '*' ')' over_clause
--- 10409,10415 ----
n->agg_distinct = TRUE;
n->func_variadic = FALSE;
n->over = $7;
! n->location = @1.begins;
$$ = (Node *)n;
}
| func_name '(' '*' ')' over_clause
*************** func_expr: func_name '(' ')' over_clause
*** 10432,10438 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $5;
! n->location = @1;
$$ = (Node *)n;
}
| CURRENT_DATE
--- 10432,10438 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = $5;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CURRENT_DATE
*************** func_expr: func_name '(' ')' over_clause
*** 10453,10460 ****
* to rely on it.)
*/
Node *n;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("date"), -1);
}
| CURRENT_TIME
{
--- 10453,10460 ----
* to rely on it.)
*/
Node *n;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("date"), -1, -1);
}
| CURRENT_TIME
{
*************** func_expr: func_name '(' ')' over_clause
*** 10463,10470 ****
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("timetz"), -1);
}
| CURRENT_TIME '(' Iconst ')'
{
--- 10463,10470 ----
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("timetz"), -1, -1);
}
| CURRENT_TIME '(' Iconst ')'
{
*************** func_expr: func_name '(' ')' over_clause
*** 10474,10483 ****
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
d = SystemTypeName("timetz");
! d->typmods = list_make1(makeIntConst($3, @3));
! $$ = makeTypeCast(n, d, -1);
}
| CURRENT_TIMESTAMP
{
--- 10474,10483 ----
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
d = SystemTypeName("timetz");
! d->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$ = makeTypeCast(n, d, -1, -1);
}
| CURRENT_TIMESTAMP
{
*************** func_expr: func_name '(' ')' over_clause
*** 10493,10499 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| CURRENT_TIMESTAMP '(' Iconst ')'
--- 10493,10499 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CURRENT_TIMESTAMP '(' Iconst ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10504,10513 ****
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
d = SystemTypeName("timestamptz");
! d->typmods = list_make1(makeIntConst($3, @3));
! $$ = makeTypeCast(n, d, -1);
}
| LOCALTIME
{
--- 10504,10513 ----
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
d = SystemTypeName("timestamptz");
! d->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$ = makeTypeCast(n, d, -1, -1);
}
| LOCALTIME
{
*************** func_expr: func_name '(' ')' over_clause
*** 10516,10523 ****
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
! $$ = makeTypeCast((Node *)n, SystemTypeName("time"), -1);
}
| LOCALTIME '(' Iconst ')'
{
--- 10516,10523 ----
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
! $$ = makeTypeCast((Node *)n, SystemTypeName("time"), -1, -1);
}
| LOCALTIME '(' Iconst ')'
{
*************** func_expr: func_name '(' ')' over_clause
*** 10527,10536 ****
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
d = SystemTypeName("time");
! d->typmods = list_make1(makeIntConst($3, @3));
! $$ = makeTypeCast((Node *)n, d, -1);
}
| LOCALTIMESTAMP
{
--- 10527,10536 ----
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
d = SystemTypeName("time");
! d->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$ = makeTypeCast((Node *)n, d, -1, -1);
}
| LOCALTIMESTAMP
{
*************** func_expr: func_name '(' ')' over_clause
*** 10539,10546 ****
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("timestamp"), -1);
}
| LOCALTIMESTAMP '(' Iconst ')'
{
--- 10539,10546 ----
* See comments for CURRENT_DATE.
*/
Node *n;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
! $$ = makeTypeCast(n, SystemTypeName("timestamp"), -1, -1);
}
| LOCALTIMESTAMP '(' Iconst ')'
{
*************** func_expr: func_name '(' ')' over_clause
*** 10550,10559 ****
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1, SystemTypeName("text"));
d = SystemTypeName("timestamp");
! d->typmods = list_make1(makeIntConst($3, @3));
! $$ = makeTypeCast(n, d, -1);
}
| CURRENT_ROLE
{
--- 10550,10559 ----
*/
Node *n;
TypeName *d;
! n = makeStringConstCast("now", @1.begins, @1.length, SystemTypeName("text"));
d = SystemTypeName("timestamp");
! d->typmods = list_make1(makeIntConst($3, @3.begins, @3.length));
! $$ = makeTypeCast(n, d, -1, -1);
}
| CURRENT_ROLE
{
*************** func_expr: func_name '(' ')' over_clause
*** 10565,10571 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| CURRENT_USER
--- 10565,10571 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CURRENT_USER
*************** func_expr: func_name '(' ')' over_clause
*** 10578,10584 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| SESSION_USER
--- 10578,10584 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| SESSION_USER
*************** func_expr: func_name '(' ')' over_clause
*** 10591,10597 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| USER
--- 10591,10597 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| USER
*************** func_expr: func_name '(' ')' over_clause
*** 10604,10610 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| CURRENT_CATALOG
--- 10604,10610 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CURRENT_CATALOG
*************** func_expr: func_name '(' ')' over_clause
*** 10617,10623 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| CURRENT_SCHEMA
--- 10617,10623 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CURRENT_SCHEMA
*************** func_expr: func_name '(' ')' over_clause
*** 10630,10640 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| CAST '(' a_expr AS Typename ')'
! { $$ = makeTypeCast($3, $5, @1); }
| EXTRACT '(' extract_list ')'
{
FuncCall *n = makeNode(FuncCall);
--- 10630,10640 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| CAST '(' a_expr AS Typename ')'
! { $$ = makeTypeCast($3, $5, @1.begins, @1.length); }
| EXTRACT '(' extract_list ')'
{
FuncCall *n = makeNode(FuncCall);
*************** func_expr: func_name '(' ')' over_clause
*** 10645,10651 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| OVERLAY '(' overlay_list ')'
--- 10645,10651 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| OVERLAY '(' overlay_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10663,10669 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
--- 10663,10669 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10677,10683 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| SUBSTRING '(' substr_list ')'
--- 10677,10683 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| SUBSTRING '(' substr_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10693,10699 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| TREAT '(' a_expr AS Typename ')'
--- 10693,10699 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| TREAT '(' a_expr AS Typename ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10715,10721 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| TRIM '(' BOTH trim_list ')'
--- 10715,10721 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| TRIM '(' BOTH trim_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10731,10737 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| TRIM '(' LEADING trim_list ')'
--- 10731,10737 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| TRIM '(' LEADING trim_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10744,10750 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| TRIM '(' TRAILING trim_list ')'
--- 10744,10750 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| TRIM '(' TRAILING trim_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10757,10763 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| TRIM '(' trim_list ')'
--- 10757,10763 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| TRIM '(' trim_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10770,10787 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| NULLIF '(' a_expr ',' a_expr ')'
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5, @1);
}
| COALESCE '(' expr_list ')'
{
CoalesceExpr *c = makeNode(CoalesceExpr);
c->args = $3;
! c->location = @1;
$$ = (Node *)c;
}
| GREATEST '(' expr_list ')'
--- 10770,10787 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| NULLIF '(' a_expr ',' a_expr ')'
{
! $$ = (Node *) makeSimpleA_Expr(AEXPR_NULLIF, "=", $3, $5, @1.begins);
}
| COALESCE '(' expr_list ')'
{
CoalesceExpr *c = makeNode(CoalesceExpr);
c->args = $3;
! c->location = @1.begins;
$$ = (Node *)c;
}
| GREATEST '(' expr_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10789,10795 ****
MinMaxExpr *v = makeNode(MinMaxExpr);
v->args = $3;
v->op = IS_GREATEST;
! v->location = @1;
$$ = (Node *)v;
}
| LEAST '(' expr_list ')'
--- 10789,10795 ----
MinMaxExpr *v = makeNode(MinMaxExpr);
v->args = $3;
v->op = IS_GREATEST;
! v->location = @1.begins;
$$ = (Node *)v;
}
| LEAST '(' expr_list ')'
*************** func_expr: func_name '(' ')' over_clause
*** 10797,10824 ****
MinMaxExpr *v = makeNode(MinMaxExpr);
v->args = $3;
v->op = IS_LEAST;
! v->location = @1;
$$ = (Node *)v;
}
| XMLCONCAT '(' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3, @1);
}
| XMLELEMENT '(' NAME_P ColLabel ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL, @1);
}
| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL, @1);
}
| XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6, @1);
}
| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8, @1);
}
| XMLEXISTS '(' c_expr xmlexists_argument ')'
{
--- 10797,10824 ----
MinMaxExpr *v = makeNode(MinMaxExpr);
v->args = $3;
v->op = IS_LEAST;
! v->location = @1.begins;
$$ = (Node *)v;
}
| XMLCONCAT '(' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3, @1.begins);
}
| XMLELEMENT '(' NAME_P ColLabel ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL, @1.begins);
}
| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL, @1.begins);
}
| XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6, @1.begins);
}
| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'
{
! $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8, @1.begins);
}
| XMLEXISTS '(' c_expr xmlexists_argument ')'
{
*************** func_expr: func_name '(' ')' over_clause
*** 10832,10865 ****
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1;
$$ = (Node *)n;
}
| XMLFOREST '(' xml_attribute_list ')'
{
! $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL, @1);
}
| XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
{
XmlExpr *x = (XmlExpr *)
makeXmlExpr(IS_XMLPARSE, NULL, NIL,
! list_make2($4, makeBoolAConst($5, -1)),
! @1);
x->xmloption = $3;
$$ = (Node *)x;
}
| XMLPI '(' NAME_P ColLabel ')'
{
! $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL, @1);
}
| XMLPI '(' NAME_P ColLabel ',' a_expr ')'
{
! $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6), @1);
}
| XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
{
$$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
! list_make3($3, $5, $6), @1);
}
| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'
{
--- 10832,10865 ----
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
! n->location = @1.begins;
$$ = (Node *)n;
}
| XMLFOREST '(' xml_attribute_list ')'
{
! $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL, @1.begins);
}
| XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
{
XmlExpr *x = (XmlExpr *)
makeXmlExpr(IS_XMLPARSE, NULL, NIL,
! list_make2($4, makeBoolAConst($5, -1, -1)),
! @1.begins);
x->xmloption = $3;
$$ = (Node *)x;
}
| XMLPI '(' NAME_P ColLabel ')'
{
! $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL, @1.begins);
}
| XMLPI '(' NAME_P ColLabel ',' a_expr ')'
{
! $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6), @1.begins);
}
| XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
{
$$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
! list_make3($3, $5, $6), @1.begins);
}
| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'
{
*************** func_expr: func_name '(' ')' over_clause
*** 10867,10873 ****
n->xmloption = $3;
n->expr = $4;
n->typeName = $6;
! n->location = @1;
$$ = (Node *)n;
}
;
--- 10867,10873 ----
n->xmloption = $3;
n->expr = $4;
n->typeName = $6;
! n->location = @1.begins;
$$ = (Node *)n;
}
;
*************** func_expr: func_name '(' ')' over_clause
*** 10878,10894 ****
xml_root_version: VERSION_P a_expr
{ $$ = $2; }
| VERSION_P NO VALUE_P
! { $$ = makeNullAConst(-1); }
;
opt_xml_root_standalone: ',' STANDALONE_P YES_P
! { $$ = makeIntConst(XML_STANDALONE_YES, -1); }
| ',' STANDALONE_P NO
! { $$ = makeIntConst(XML_STANDALONE_NO, -1); }
| ',' STANDALONE_P NO VALUE_P
! { $$ = makeIntConst(XML_STANDALONE_NO_VALUE, -1); }
| /*EMPTY*/
! { $$ = makeIntConst(XML_STANDALONE_OMITTED, -1); }
;
xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
--- 10878,10894 ----
xml_root_version: VERSION_P a_expr
{ $$ = $2; }
| VERSION_P NO VALUE_P
! { $$ = makeNullAConst(-1, -1); }
;
opt_xml_root_standalone: ',' STANDALONE_P YES_P
! { $$ = makeIntConst(XML_STANDALONE_YES, -1, -1); }
| ',' STANDALONE_P NO
! { $$ = makeIntConst(XML_STANDALONE_NO, -1, -1); }
| ',' STANDALONE_P NO VALUE_P
! { $$ = makeIntConst(XML_STANDALONE_NO_VALUE, -1, -1); }
| /*EMPTY*/
! { $$ = makeIntConst(XML_STANDALONE_OMITTED, -1, -1); }
;
xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
*************** xml_attribute_el: a_expr AS ColLabel
*** 10904,10910 ****
$$->name = $3;
$$->indirection = NIL;
$$->val = (Node *) $1;
! $$->location = @1;
}
| a_expr
{
--- 10904,10910 ----
$$->name = $3;
$$->indirection = NIL;
$$->val = (Node *) $1;
! $$->location = @1.begins;
}
| a_expr
{
*************** xml_attribute_el: a_expr AS ColLabel
*** 10912,10918 ****
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *) $1;
! $$->location = @1;
}
;
--- 10912,10918 ----
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *) $1;
! $$->location = @1.begins;
}
;
*************** over_clause: OVER window_specification
*** 10981,10987 ****
n->frameOptions = FRAMEOPTION_DEFAULTS;
n->startOffset = NULL;
n->endOffset = NULL;
! n->location = @2;
$$ = n;
}
| /*EMPTY*/
--- 10981,10987 ----
n->frameOptions = FRAMEOPTION_DEFAULTS;
n->startOffset = NULL;
n->endOffset = NULL;
! n->location = @2.begins;
$$ = n;
}
| /*EMPTY*/
*************** window_specification: '(' opt_existing_w
*** 11000,11006 ****
n->frameOptions = $5->frameOptions;
n->startOffset = $5->startOffset;
n->endOffset = $5->endOffset;
! n->location = @1;
$$ = n;
}
;
--- 11000,11006 ----
n->frameOptions = $5->frameOptions;
n->startOffset = $5->startOffset;
n->endOffset = $5->endOffset;
! n->location = @1.begins;
$$ = n;
}
;
*************** opt_frame_clause:
*** 11040,11052 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RANGE PRECEDING is only supported with UNBOUNDED"),
! parser_errposition(@1)));
if (n->frameOptions & (FRAMEOPTION_START_VALUE_FOLLOWING |
FRAMEOPTION_END_VALUE_FOLLOWING))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RANGE FOLLOWING is only supported with UNBOUNDED"),
! parser_errposition(@1)));
$$ = n;
}
| ROWS frame_extent
--- 11040,11052 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RANGE PRECEDING is only supported with UNBOUNDED"),
! parser_errposition(@1.begins)));
if (n->frameOptions & (FRAMEOPTION_START_VALUE_FOLLOWING |
FRAMEOPTION_END_VALUE_FOLLOWING))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("RANGE FOLLOWING is only supported with UNBOUNDED"),
! parser_errposition(@1.begins)));
$$ = n;
}
| ROWS frame_extent
*************** frame_extent: frame_bound
*** 11073,11084 ****
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
! parser_errposition(@1)));
if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from following row cannot end with current row"),
! parser_errposition(@1)));
n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW;
$$ = n;
}
--- 11073,11084 ----
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
! parser_errposition(@1.begins)));
if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from following row cannot end with current row"),
! parser_errposition(@1.begins)));
n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW;
$$ = n;
}
*************** frame_extent: frame_bound
*** 11096,11120 ****
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
! parser_errposition(@2)));
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame end cannot be UNBOUNDED PRECEDING"),
! parser_errposition(@4)));
if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) &&
(frameOptions & FRAMEOPTION_END_VALUE_PRECEDING))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from current row cannot have preceding rows"),
! parser_errposition(@4)));
if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) &&
(frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING |
FRAMEOPTION_END_CURRENT_ROW)))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from following row cannot have preceding rows"),
! parser_errposition(@4)));
n1->frameOptions = frameOptions;
n1->endOffset = n2->startOffset;
$$ = n1;
--- 11096,11120 ----
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
! parser_errposition(@2.begins)));
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame end cannot be UNBOUNDED PRECEDING"),
! parser_errposition(@4.begins)));
if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) &&
(frameOptions & FRAMEOPTION_END_VALUE_PRECEDING))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from current row cannot have preceding rows"),
! parser_errposition(@4.begins)));
if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) &&
(frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING |
FRAMEOPTION_END_CURRENT_ROW)))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame starting from following row cannot have preceding rows"),
! parser_errposition(@4.begins)));
n1->frameOptions = frameOptions;
n1->endOffset = n2->startOffset;
$$ = n1;
*************** func_arg_expr: a_expr
*** 11272,11278 ****
na->name = $1;
na->arg = (Expr *) $3;
na->argnumber = -1; /* until determined */
! na->location = @1;
$$ = (Node *) na;
}
;
--- 11272,11278 ----
na->name = $1;
na->arg = (Expr *) $3;
na->argnumber = -1; /* until determined */
! na->location = @1.begins;
$$ = (Node *) na;
}
;
*************** type_list: Typename { $$ = list_m
*** 11283,11297 ****
array_expr: '[' expr_list ']'
{
! $$ = makeAArrayExpr($2, @1);
}
| '[' array_expr_list ']'
{
! $$ = makeAArrayExpr($2, @1);
}
| '[' ']'
{
! $$ = makeAArrayExpr(NIL, @1);
}
;
--- 11283,11297 ----
array_expr: '[' expr_list ']'
{
! $$ = makeAArrayExpr($2, @1.begins);
}
| '[' array_expr_list ']'
{
! $$ = makeAArrayExpr($2, @1.begins);
}
| '[' ']'
{
! $$ = makeAArrayExpr(NIL, @1.begins);
}
;
*************** array_expr_list: array_expr { $$ =
*** 11303,11309 ****
extract_list:
extract_arg FROM a_expr
{
! $$ = list_make2(makeStringConst($1, @1), $3);
}
| /*EMPTY*/ { $$ = NIL; }
;
--- 11303,11309 ----
extract_list:
extract_arg FROM a_expr
{
! $$ = list_make2(makeStringConst($1, @1.begins, @1.length), $3);
}
| /*EMPTY*/ { $$ = NIL; }
;
*************** substr_list:
*** 11388,11396 ****
* which it is likely to do if the second argument
* is unknown or doesn't have an implicit cast to int4.
*/
! $$ = list_make3($1, makeIntConst(1, -1),
makeTypeCast($2,
! SystemTypeName("int4"), -1));
}
| expr_list
{
--- 11388,11396 ----
* which it is likely to do if the second argument
* is unknown or doesn't have an implicit cast to int4.
*/
! $$ = list_make3($1, makeIntConst(1, -1, -1),
makeTypeCast($2,
! SystemTypeName("int4"), -1, -1));
}
| expr_list
{
*************** case_expr: CASE case_arg when_clause_lis
*** 11436,11442 ****
c->arg = (Expr *) $2;
c->args = $3;
c->defresult = (Expr *) $4;
! c->location = @1;
$$ = (Node *)c;
}
;
--- 11436,11442 ----
c->arg = (Expr *) $2;
c->args = $3;
c->defresult = (Expr *) $4;
! c->location = @1.begins;
$$ = (Node *)c;
}
;
*************** when_clause:
*** 11453,11459 ****
CaseWhen *w = makeNode(CaseWhen);
w->expr = (Expr *) $2;
w->result = (Expr *) $4;
! w->location = @1;
$$ = (Node *)w;
}
;
--- 11453,11459 ----
CaseWhen *w = makeNode(CaseWhen);
w->expr = (Expr *) $2;
w->result = (Expr *) $4;
! w->location = @1.begins;
$$ = (Node *)w;
}
;
*************** case_arg: a_expr { $$ = $1; }
*** 11469,11479 ****
columnref: ColId
{
! $$ = makeColumnRef($1, NIL, @1, yyscanner);
}
| ColId indirection
{
! $$ = makeColumnRef($1, $2, @1, yyscanner);
}
;
--- 11469,11479 ----
columnref: ColId
{
! $$ = makeColumnRef($1, NIL, @1.begins, yyscanner);
}
| ColId indirection
{
! $$ = makeColumnRef($1, $2, @1.begins, yyscanner);
}
;
*************** ctext_expr:
*** 11528,11534 ****
| DEFAULT
{
SetToDefault *n = makeNode(SetToDefault);
! n->location = @1;
$$ = (Node *) n;
}
;
--- 11528,11534 ----
| DEFAULT
{
SetToDefault *n = makeNode(SetToDefault);
! n->location = @1.begins;
$$ = (Node *) n;
}
;
*************** target_el: a_expr AS ColLabel
*** 11564,11570 ****
$$->name = $3;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1;
}
/*
* We support omitting AS only for column labels that aren't
--- 11564,11570 ----
$$->name = $3;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1.begins;
}
/*
* We support omitting AS only for column labels that aren't
*************** target_el: a_expr AS ColLabel
*** 11580,11586 ****
$$->name = $2;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1;
}
| a_expr
{
--- 11580,11586 ----
$$->name = $2;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1.begins;
}
| a_expr
{
*************** target_el: a_expr AS ColLabel
*** 11588,11606 ****
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1;
}
| '*'
{
ColumnRef *n = makeNode(ColumnRef);
n->fields = list_make1(makeNode(A_Star));
! n->location = @1;
$$ = makeNode(ResTarget);
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *)n;
! $$->location = @1;
}
;
--- 11588,11606 ----
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *)$1;
! $$->location = @1.begins;
}
| '*'
{
ColumnRef *n = makeNode(ColumnRef);
n->fields = list_make1(makeNode(A_Star));
! n->location = @1.begins;
$$ = makeNode(ResTarget);
$$->name = NULL;
$$->indirection = NIL;
$$->val = (Node *)n;
! $$->location = @1.begins;
}
;
*************** qualified_name_list:
*** 11626,11637 ****
qualified_name:
ColId
{
! $$ = makeRangeVar(NULL, $1, @1);
}
| ColId indirection
{
check_qualified_name($2, yyscanner);
! $$ = makeRangeVar(NULL, NULL, @1);
switch (list_length($2))
{
case 1:
--- 11626,11637 ----
qualified_name:
ColId
{
! $$ = makeRangeVar(NULL, $1, @1.begins);
}
| ColId indirection
{
check_qualified_name($2, yyscanner);
! $$ = makeRangeVar(NULL, NULL, @1.begins);
switch (list_length($2))
{
case 1:
*************** qualified_name:
*** 11649,11655 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper qualified name (too many dotted names): %s",
NameListToString(lcons(makeString($1), $2))),
! parser_errposition(@1)));
break;
}
}
--- 11649,11655 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("improper qualified name (too many dotted names): %s",
NameListToString(lcons(makeString($1), $2))),
! parser_errposition(@1.begins)));
break;
}
}
*************** func_name: type_function_name
*** 11699,11717 ****
*/
AexprConst: Iconst
{
! $$ = makeIntConst($1, @1);
}
| FCONST
{
! $$ = makeFloatConst($1, @1);
}
| Sconst
{
! $$ = makeStringConst($1, @1);
}
| BCONST
{
! $$ = makeBitStringConst($1, @1);
}
| XCONST
{
--- 11699,11717 ----
*/
AexprConst: Iconst
{
! $$ = makeIntConst($1, @1.begins, @1.length);
}
| FCONST
{
! $$ = makeFloatConst($1, @1.begins, @1.length);
}
| Sconst
{
! $$ = makeStringConst($1, @1.begins, @1.length);
}
| BCONST
{
! $$ = makeBitStringConst($1, @1.begins, @1.length);
}
| XCONST
{
*************** AexprConst: Iconst
*** 11720,11733 ****
* a <general literal> shall not be a
* <bit string literal> or a <hex string literal>.
*/
! $$ = makeBitStringConst($1, @1);
}
| func_name Sconst
{
/* generic type 'literal' syntax */
TypeName *t = makeTypeNameFromNameList($1);
! t->location = @1;
! $$ = makeStringConstCast($2, @2, t);
}
| func_name '(' func_arg_list ')' Sconst
{
--- 11720,11733 ----
* a <general literal> shall not be a
* <bit string literal> or a <hex string literal>.
*/
! $$ = makeBitStringConst($1, @1.begins, @1.length);
}
| func_name Sconst
{
/* generic type 'literal' syntax */
TypeName *t = makeTypeNameFromNameList($1);
! t->location = @1.begins;
! $$ = makeStringConstCast($2, @2.begins, @2.length, t);
}
| func_name '(' func_arg_list ')' Sconst
{
*************** AexprConst: Iconst
*** 11751,11768 ****
parser_errposition(arg->location)));
}
t->typmods = $3;
! t->location = @1;
! $$ = makeStringConstCast($5, @5, t);
}
| ConstTypename Sconst
{
! $$ = makeStringConstCast($2, @2, $1);
}
| ConstInterval Sconst opt_interval
{
TypeName *t = $1;
t->typmods = $3;
! $$ = makeStringConstCast($2, @2, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
--- 11751,11768 ----
parser_errposition(arg->location)));
}
t->typmods = $3;
! t->location = @1.begins;
! $$ = makeStringConstCast($5, @5.begins, @5.length, t);
}
| ConstTypename Sconst
{
! $$ = makeStringConstCast($2, @2.begins, @2.length, $1);
}
| ConstInterval Sconst opt_interval
{
TypeName *t = $1;
t->typmods = $3;
! $$ = makeStringConstCast($2, @2.begins, @2.length, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
*************** AexprConst: Iconst
*** 11773,11797 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1)));
! t->typmods = lappend($6, makeIntConst($3, @3));
}
else
! t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
! makeIntConst($3, @3));
! $$ = makeStringConstCast($5, @5, t);
}
| TRUE_P
{
! $$ = makeBoolAConst(TRUE, @1);
}
| FALSE_P
{
! $$ = makeBoolAConst(FALSE, @1);
}
| NULL_P
{
! $$ = makeNullAConst(@1);
}
;
--- 11773,11797 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("interval precision specified twice"),
! parser_errposition(@1.begins)));
! t->typmods = lappend($6, makeIntConst($3, @3.begins, @3.length));
}
else
! t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1, -1),
! makeIntConst($3, @3.begins, @3.length));
! $$ = makeStringConstCast($5, @5.begins, @5.length, t);
}
| TRUE_P
{
! $$ = makeBoolAConst(TRUE, @1.begins, @1.length);
}
| FALSE_P
{
! $$ = makeBoolAConst(FALSE, @1.begins, @1.length);
}
| NULL_P
{
! $$ = makeNullAConst(@1.begins, @1.length);
}
;
*************** makeColumnRef(char *colname, List *indir
*** 12352,12451 ****
}
static Node *
! makeTypeCast(Node *arg, TypeName *typename, int location)
{
TypeCast *n = makeNode(TypeCast);
n->arg = arg;
n->typeName = typename;
n->location = location;
return (Node *) n;
}
static Node *
! makeStringConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = str;
n->location = location;
return (Node *)n;
}
static Node *
! makeStringConstCast(char *str, int location, TypeName *typename)
{
! Node *s = makeStringConst(str, location);
! return makeTypeCast(s, typename, -1);
}
static Node *
! makeIntConst(int val, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Integer;
n->val.val.ival = val;
n->location = location;
return (Node *)n;
}
static Node *
! makeFloatConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Float;
n->val.val.str = str;
n->location = location;
return (Node *)n;
}
static Node *
! makeBitStringConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_BitString;
n->val.val.str = str;
n->location = location;
return (Node *)n;
}
static Node *
! makeNullAConst(int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
n->location = location;
return (Node *)n;
}
static Node *
! makeAConst(Value *v, int location)
{
Node *n;
switch (v->type)
{
case T_Float:
! n = makeFloatConst(v->val.str, location);
break;
case T_Integer:
! n = makeIntConst(v->val.ival, location);
break;
case T_String:
default:
! n = makeStringConst(v->val.str, location);
break;
}
--- 12352,12457 ----
}
static Node *
! makeTypeCast(Node *arg, TypeName *typename, int location, int length)
{
TypeCast *n = makeNode(TypeCast);
n->arg = arg;
n->typeName = typename;
n->location = location;
+ n->tok_len = length;
return (Node *) n;
}
static Node *
! makeStringConst(char *str, int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = str;
n->location = location;
+ n->tok_len = length;
return (Node *)n;
}
static Node *
! makeStringConstCast(char *str, int location, int length, TypeName *typename)
{
! Node *s = makeStringConst(str, location, length);
! return makeTypeCast(s, typename, location, length);
}
static Node *
! makeIntConst(int val, int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Integer;
n->val.val.ival = val;
n->location = location;
+ n->tok_len = length;
return (Node *)n;
}
static Node *
! makeFloatConst(char *str, int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Float;
n->val.val.str = str;
n->location = location;
+ n->tok_len = length;
return (Node *)n;
}
static Node *
! makeBitStringConst(char *str, int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_BitString;
n->val.val.str = str;
n->location = location;
+ n->tok_len = length;
return (Node *)n;
}
static Node *
! makeNullAConst(int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
n->location = location;
+ n->tok_len = length;
return (Node *)n;
}
static Node *
! makeAConst(Value *v, int location, int length)
{
Node *n;
switch (v->type)
{
case T_Float:
! n = makeFloatConst(v->val.str, location, length);
break;
case T_Integer:
! n = makeIntConst(v->val.ival, location, length);
break;
case T_String:
default:
! n = makeStringConst(v->val.str, location, length);
break;
}
*************** makeAConst(Value *v, int location)
*** 12456,12470 ****
* Create an A_Const string node and put it inside a boolean cast.
*/
static Node *
! makeBoolAConst(bool state, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = (state ? "t" : "f");
n->location = location;
! return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
}
/* makeOverlaps()
--- 12462,12477 ----
* Create an A_Const string node and put it inside a boolean cast.
*/
static Node *
! makeBoolAConst(bool state, int location, int length)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = (state ? "t" : "f");
n->location = location;
+ n->tok_len = length;
! return makeTypeCast((Node *)n, SystemTypeName("bool"), -1, -1);
}
/* makeOverlaps()
*************** SystemTypeName(char *name)
*** 12696,12702 ****
* until we know what the desired type is.
*/
static Node *
! doNegate(Node *n, int location)
{
if (IsA(n, A_Const))
{
--- 12703,12709 ----
* until we know what the desired type is.
*/
static Node *
! doNegate(Node *n, int location, int length)
{
if (IsA(n, A_Const))
{
*************** doNegate(Node *n, int location)
*** 12704,12718 ****
--- 12711,12729 ----
/* report the constant's location as that of the '-' sign */
con->location = location;
+ /* TODO: A more elegant job of calculating length than this */
+ /*con->tok_len = length; */
if (con->val.type == T_Integer)
{
con->val.val.ival = -con->val.val.ival;
+ con->tok_len = (con->val.val.ival==0? 2: ((int) log10(fabs(con->val.val.ival)) + 2 ) );
return n;
}
if (con->val.type == T_Float)
{
doNegateFloat(&con->val);
+ con->tok_len = strlen(con->val.val.str);
return n;
}
}
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index e8177bc..6aaa4d2 100644
*** a/src/backend/parser/parse_clause.c
--- b/src/backend/parser/parse_clause.c
*************** buildMergedJoinVar(ParseState *pstate, J
*** 1073,1079 ****
if (l_colvar->vartype != outcoltype)
l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
outcoltype, outcoltypmod,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
else if (l_colvar->vartypmod != outcoltypmod)
l_node = (Node *) makeRelabelType((Expr *) l_colvar,
outcoltype, outcoltypmod,
--- 1073,1079 ----
if (l_colvar->vartype != outcoltype)
l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
outcoltype, outcoltypmod,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, -1);
else if (l_colvar->vartypmod != outcoltypmod)
l_node = (Node *) makeRelabelType((Expr *) l_colvar,
outcoltype, outcoltypmod,
*************** buildMergedJoinVar(ParseState *pstate, J
*** 1085,1091 ****
if (r_colvar->vartype != outcoltype)
r_node = coerce_type(pstate, (Node *) r_colvar, r_colvar->vartype,
outcoltype, outcoltypmod,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
else if (r_colvar->vartypmod != outcoltypmod)
r_node = (Node *) makeRelabelType((Expr *) r_colvar,
outcoltype, outcoltypmod,
--- 1085,1091 ----
if (r_colvar->vartype != outcoltype)
r_node = coerce_type(pstate, (Node *) r_colvar, r_colvar->vartype,
outcoltype, outcoltypmod,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, -1);
else if (r_colvar->vartypmod != outcoltypmod)
r_node = (Node *) makeRelabelType((Expr *) r_colvar,
outcoltype, outcoltypmod,
*************** addTargetToSortList(ParseState *pstate,
*** 1965,1971 ****
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1);
restype = TEXTOID;
}
--- 1965,1971 ----
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1, -1);
restype = TEXTOID;
}
*************** addTargetToGroupList(ParseState *pstate,
*** 2108,2114 ****
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1);
restype = TEXTOID;
}
--- 2108,2114 ----
restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1, -1);
restype = TEXTOID;
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index c072325..004cea9 100644
*** a/src/backend/parser/parse_coerce.c
--- b/src/backend/parser/parse_coerce.c
*************** coerce_to_target_type(ParseState *pstate
*** 76,82 ****
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
! int location)
{
Node *result;
--- 76,83 ----
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
! int location,
! int tok_len)
{
Node *result;
*************** coerce_to_target_type(ParseState *pstate
*** 85,91 ****
result = coerce_type(pstate, expr, exprtype,
targettype, targettypmod,
! ccontext, cformat, location);
/*
* If the target is a fixed-length type, it may need a length coercion as
--- 86,92 ----
result = coerce_type(pstate, expr, exprtype,
targettype, targettypmod,
! ccontext, cformat, location, tok_len);
/*
* If the target is a fixed-length type, it may need a length coercion as
*************** coerce_to_target_type(ParseState *pstate
*** 127,133 ****
Node *
coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
! CoercionContext ccontext, CoercionForm cformat, int location)
{
Node *result;
CoercionPathType pathtype;
--- 128,134 ----
Node *
coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
! CoercionContext ccontext, CoercionForm cformat, int location, int tok_len)
{
Node *result;
CoercionPathType pathtype;
*************** coerce_type(ParseState *pstate, Node *no
*** 256,266 ****
--- 257,276 ----
newcon->constisnull = con->constisnull;
/* Use the leftmost of the constant's and coercion's locations */
if (location < 0)
+ {
newcon->location = con->location;
+ newcon->tok_len = con->tok_len;
+ }
else if (con->location >= 0 && con->location < location)
+ {
newcon->location = con->location;
+ newcon->tok_len = con->tok_len;
+ }
else
+ {
newcon->location = location;
+ newcon->tok_len = tok_len;
+ }
/*
* Set up to point at the constant's text if the input routine throws
*************** coerce_type(ParseState *pstate, Node *no
*** 326,332 ****
newcoll->arg = (Expr *)
coerce_type(pstate, (Node *) coll->arg,
inputTypeId, targetTypeId, targetTypeMod,
! ccontext, cformat, location);
newcoll->collOid = coll->collOid;
newcoll->location = coll->location;
return (Node *) newcoll;
--- 336,342 ----
newcoll->arg = (Expr *)
coerce_type(pstate, (Node *) coll->arg,
inputTypeId, targetTypeId, targetTypeMod,
! ccontext, cformat, location, tok_len);
newcoll->collOid = coll->collOid;
newcoll->location = coll->location;
return (Node *) newcoll;
*************** coerce_record_to_complex(ParseState *pst
*** 947,953 ****
tupdesc->attrs[i]->atttypmod,
ccontext,
COERCE_IMPLICIT_CAST,
! -1);
if (cexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
--- 957,963 ----
tupdesc->attrs[i]->atttypmod,
ccontext,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (cexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
*************** coerce_to_boolean(ParseState *pstate, No
*** 1007,1013 ****
BOOLOID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 1017,1023 ----
BOOLOID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** coerce_to_specific_type(ParseState *psta
*** 1054,1060 ****
targetTypeId, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 1064,1070 ----
targetTypeId, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (newnode == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** coerce_to_common_type(ParseState *pstate
*** 1254,1260 ****
return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
else
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
--- 1264,1270 ----
return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
! COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1, -1);
else
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 75236c7..5849900 100644
*** a/src/backend/parser/parse_expr.c
--- b/src/backend/parser/parse_expr.c
*************** transformExpr(ParseState *pstate, Node *
*** 125,131 ****
A_Const *con = (A_Const *) expr;
Value *val = &con->val;
! result = (Node *) make_const(pstate, val, con->location);
break;
}
--- 125,131 ----
A_Const *con = (A_Const *) expr;
Value *val = &con->val;
! result = (Node *) make_const(pstate, val, con->location, con->tok_len);
break;
}
*************** transformCaseExpr(ParseState *pstate, Ca
*** 1347,1352 ****
--- 1347,1353 ----
n->val.type = T_Null;
n->location = -1;
+ n->tok_len = -1;
defresult = (Node *) n;
}
newc->defresult = (Expr *) transformExpr(pstate, defresult);
*************** transformArrayExpr(ParseState *pstate, A
*** 1663,1669 ****
typmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
! -1);
if (newe == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
--- 1664,1670 ----
typmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
! -1, -1);
if (newe == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
*************** transformXmlSerialize(ParseState *pstate
*** 1942,1948 ****
TEXTOID, targetType, targetTypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
--- 1943,1949 ----
TEXTOID, targetType, targetTypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
*************** transformTypeCast(ParseState *pstate, Ty
*** 2092,2098 ****
Oid inputType = exprType(expr);
Oid targetType;
int32 targetTypmod;
! int location;
typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
--- 2093,2099 ----
Oid inputType = exprType(expr);
Oid targetType;
int32 targetTypmod;
! int location, tok_len;
typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
*************** transformTypeCast(ParseState *pstate, Ty
*** 2105,2110 ****
--- 2106,2112 ----
* name (this can happen in TypeName 'string' syntax, for instance).
*/
location = tc->location;
+ tok_len = tc->tok_len;
if (location < 0)
location = tc->typeName->location;
*************** transformTypeCast(ParseState *pstate, Ty
*** 2112,2118 ****
targetType, targetTypmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
! location);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
--- 2114,2120 ----
targetType, targetTypmod,
COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST,
! location, tok_len);
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 01ed85b..ccebc9f 100644
*** a/src/backend/parser/parse_func.c
--- b/src/backend/parser/parse_func.c
*************** ParseFuncOrColumn(ParseState *pstate, Li
*** 222,228 ****
*/
return coerce_type(pstate, linitial(fargs),
actual_arg_types[0], rettype, -1,
! COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location);
}
else if (fdresult == FUNCDETAIL_NORMAL)
{
--- 222,228 ----
*/
return coerce_type(pstate, linitial(fargs),
actual_arg_types[0], rettype, -1,
! COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location, -1);
}
else if (fdresult == FUNCDETAIL_NORMAL)
{
*************** make_fn_arguments(ParseState *pstate,
*** 1356,1362 ****
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1);
na->arg = (Expr *) node;
}
else
--- 1356,1362 ----
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1, -1);
na->arg = (Expr *) node;
}
else
*************** make_fn_arguments(ParseState *pstate,
*** 1367,1373 ****
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1);
lfirst(current_fargs) = node;
}
}
--- 1367,1373 ----
declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
! -1, -1);
lfirst(current_fargs) = node;
}
}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 7b5c040..2d0e610 100644
*** a/src/backend/parser/parse_node.c
--- b/src/backend/parser/parse_node.c
*************** transformArraySubscripts(ParseState *pst
*** 335,341 ****
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 335,341 ----
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** transformArraySubscripts(ParseState *pst
*** 362,368 ****
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 362,368 ----
INT4OID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (subexpr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** transformArraySubscripts(ParseState *pst
*** 386,392 ****
typeneeded, arrayTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (newFrom == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 386,392 ----
typeneeded, arrayTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (newFrom == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** transformArraySubscripts(ParseState *pst
*** 434,440 ****
* too many examples that fail if we try.
*/
Const *
! make_const(ParseState *pstate, Value *value, int location)
{
Const *con;
Datum val;
--- 434,440 ----
* too many examples that fail if we try.
*/
Const *
! make_const(ParseState *pstate, Value *value, int location, int tok_len)
{
Const *con;
Datum val;
*************** make_const(ParseState *pstate, Value *va
*** 533,538 ****
--- 533,539 ----
true,
false);
con->location = location;
+ con->tok_len = tok_len;
return con;
default:
*************** make_const(ParseState *pstate, Value *va
*** 548,553 ****
--- 549,555 ----
false,
typebyval);
con->location = location;
+ con->tok_len = tok_len;
return con;
}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 2f2e87f..651f72a 100644
*** a/src/backend/parser/parse_target.c
--- b/src/backend/parser/parse_target.c
*************** transformAssignedExpr(ParseState *pstate
*** 478,484 ****
attrtype, attrtypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 478,484 ----
attrtype, attrtypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
*************** transformAssignmentIndirection(ParseStat
*** 722,728 ****
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (result == NULL)
{
if (targetIsArray)
--- 722,728 ----
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (result == NULL)
{
if (targetIsArray)
*************** transformAssignmentSubscripts(ParseState
*** 822,828 ****
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
/* probably shouldn't fail, but check */
if (result == NULL)
ereport(ERROR,
--- 822,828 ----
targetTypeId, targetTypMod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
/* probably shouldn't fail, but check */
if (result == NULL)
ereport(ERROR,
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 12db190..329a15b 100644
*** a/src/backend/parser/scan.l
--- b/src/backend/parser/scan.l
*************** bool standard_conforming_strings = tru
*** 73,84 ****
* this should be done in the first such rule, else yylloc will point
* into the middle of the token.
*/
! #define SET_YYLLOC() (*(yylloc) = yytext - yyextra->scanbuf)
/*
* Advance yylloc by the given number of bytes.
*/
! #define ADVANCE_YYLLOC(delta) ( *(yylloc) += (delta) )
#define startlit() ( yyextra->literallen = 0 )
static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner);
--- 73,86 ----
* this should be done in the first such rule, else yylloc will point
* into the middle of the token.
*/
! #define SET_YYLLOC_BEGINS() yylloc->length = 0; yylloc->begins = yytext - yyextra->scanbuf;
! #define SET_YYLLOC_LEN() yylloc->length += strlen(yytext);
!
/*
* Advance yylloc by the given number of bytes.
*/
! #define ADVANCE_YYLLOC(delta) ( yylloc->begins += (delta) )
#define startlit() ( yyextra->literallen = 0 )
static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner);
*************** static void addunicode(pg_wchar c, yysca
*** 94,100 ****
#define yyerror(msg) scanner_yyerror(msg, yyscanner)
! #define lexer_errposition() scanner_errposition(*(yylloc), yyscanner)
static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner);
static void check_escape_warning(core_yyscan_t yyscanner);
--- 96,102 ----
#define yyerror(msg) scanner_yyerror(msg, yyscanner)
! #define lexer_errposition() scanner_errposition(yylloc->begins, yyscanner)
static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner);
static void check_escape_warning(core_yyscan_t yyscanner);
*************** other .
*** 377,393 ****
{xcstart} {
/* Set location in case of syntax error in comment */
! SET_YYLLOC();
yyextra->xcdepth = 0;
BEGIN(xc);
/* Put back any characters past slash-star; see above */
yyless(2);
}
<xc>{xcstart} {
(yyextra->xcdepth)++;
/* Put back any characters past slash-star; see above */
yyless(2);
}
<xc>{xcstop} {
--- 379,397 ----
{xcstart} {
/* Set location in case of syntax error in comment */
! SET_YYLLOC_BEGINS();
yyextra->xcdepth = 0;
BEGIN(xc);
/* Put back any characters past slash-star; see above */
yyless(2);
+ SET_YYLLOC_LEN();
}
<xc>{xcstart} {
(yyextra->xcdepth)++;
/* Put back any characters past slash-star; see above */
yyless(2);
+ SET_YYLLOC_LEN();
}
<xc>{xcstop} {
*************** other .
*** 395,400 ****
--- 399,405 ----
BEGIN(INITIAL);
else
(yyextra->xcdepth)--;
+ SET_YYLLOC_LEN();
}
<xc>{xcinside} {
*************** other .
*** 418,438 ****
* In the meantime, place a leading "b" on the string
* to mark it for the input routine as a binary string.
*/
! SET_YYLLOC();
BEGIN(xb);
startlit();
addlitchar('b', yyscanner);
}
<xb>{quotestop} |
<xb>{quotefail} {
yyless(1);
BEGIN(INITIAL);
yylval->str = litbufdup(yyscanner);
return BCONST;
}
<xh>{xhinside} |
<xb>{xbinside} {
addlit(yytext, yyleng, yyscanner);
}
<xh>{quotecontinue} |
<xb>{quotecontinue} {
--- 423,446 ----
* In the meantime, place a leading "b" on the string
* to mark it for the input routine as a binary string.
*/
! SET_YYLLOC_BEGINS();
BEGIN(xb);
startlit();
addlitchar('b', yyscanner);
+ SET_YYLLOC_LEN();
}
<xb>{quotestop} |
<xb>{quotefail} {
yyless(1);
BEGIN(INITIAL);
yylval->str = litbufdup(yyscanner);
+ SET_YYLLOC_LEN();
return BCONST;
}
<xh>{xhinside} |
<xb>{xbinside} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xh>{quotecontinue} |
<xb>{quotecontinue} {
*************** other .
*** 447,462 ****
* In the meantime, place a leading "x" on the string
* to mark it for the input routine as a hex string.
*/
! SET_YYLLOC();
BEGIN(xh);
startlit();
addlitchar('x', yyscanner);
}
<xh>{quotestop} |
<xh>{quotefail} {
yyless(1);
BEGIN(INITIAL);
yylval->str = litbufdup(yyscanner);
return XCONST;
}
<xh><<EOF>> { yyerror("unterminated hexadecimal string literal"); }
--- 455,472 ----
* In the meantime, place a leading "x" on the string
* to mark it for the input routine as a hex string.
*/
! SET_YYLLOC_BEGINS();
BEGIN(xh);
startlit();
addlitchar('x', yyscanner);
+ SET_YYLLOC_LEN();
}
<xh>{quotestop} |
<xh>{quotefail} {
yyless(1);
BEGIN(INITIAL);
yylval->str = litbufdup(yyscanner);
+ SET_YYLLOC_LEN();
return XCONST;
}
<xh><<EOF>> { yyerror("unterminated hexadecimal string literal"); }
*************** other .
*** 468,474 ****
*/
const ScanKeyword *keyword;
! SET_YYLLOC();
yyless(1); /* eat only 'n' this time */
keyword = ScanKeywordLookup("nchar",
--- 478,485 ----
*/
const ScanKeyword *keyword;
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
yyless(1); /* eat only 'n' this time */
keyword = ScanKeywordLookup("nchar",
*************** other .
*** 490,511 ****
{xqstart} {
yyextra->warn_on_first_escape = true;
yyextra->saw_non_ascii = false;
! SET_YYLLOC();
if (standard_conforming_strings)
BEGIN(xq);
else
BEGIN(xe);
startlit();
}
{xestart} {
yyextra->warn_on_first_escape = false;
yyextra->saw_non_ascii = false;
! SET_YYLLOC();
BEGIN(xe);
startlit();
}
{xusstart} {
! SET_YYLLOC();
if (!standard_conforming_strings)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
--- 501,525 ----
{xqstart} {
yyextra->warn_on_first_escape = true;
yyextra->saw_non_ascii = false;
! SET_YYLLOC_BEGINS();
if (standard_conforming_strings)
BEGIN(xq);
else
BEGIN(xe);
startlit();
+ yylloc->length = 0;
+ SET_YYLLOC_LEN();
}
{xestart} {
yyextra->warn_on_first_escape = false;
yyextra->saw_non_ascii = false;
! SET_YYLLOC_BEGINS();
BEGIN(xe);
startlit();
+ SET_YYLLOC_LEN();
}
{xusstart} {
! SET_YYLLOC_BEGINS();
if (!standard_conforming_strings)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
*************** other .
*** 513,518 ****
--- 527,533 ----
errdetail("String constants with Unicode escapes cannot be used when standard_conforming_strings is off."),
lexer_errposition()));
BEGIN(xus);
+ SET_YYLLOC_LEN();
startlit();
}
<xq,xe>{quotestop} |
*************** other .
*** 528,533 ****
--- 543,549 ----
yyextra->literallen,
false);
yylval->str = litbufdup(yyscanner);
+ SET_YYLLOC_LEN();
return SCONST;
}
<xus>{xusstop1} {
*************** other .
*** 535,555 ****
--- 551,576 ----
yyless(1);
BEGIN(INITIAL);
yylval->str = litbuf_udeescape('\\', yyscanner);
+ SET_YYLLOC_LEN();
return SCONST;
}
<xus>{xusstop2} {
BEGIN(INITIAL);
yylval->str = litbuf_udeescape(yytext[yyleng-2], yyscanner);
+ SET_YYLLOC_LEN();
return SCONST;
}
<xq,xe,xus>{xqdouble} {
addlitchar('\'', yyscanner);
+ SET_YYLLOC_LEN();
}
<xq,xus>{xqinside} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xe>{xeinside} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xe>{xeunicode} {
pg_wchar c = strtoul(yytext+2, NULL, 16);
*************** other .
*** 565,570 ****
--- 586,592 ----
yyerror("invalid Unicode surrogate pair");
else
addunicode(c, yyscanner);
+ SET_YYLLOC_LEN();
}
<xeu>{xeunicode} {
pg_wchar c = strtoul(yytext+2, NULL, 16);
*************** other .
*** 577,582 ****
--- 599,605 ----
addunicode(c, yyscanner);
BEGIN(xe);
+ SET_YYLLOC_LEN();
}
<xeu>. { yyerror("invalid Unicode surrogate pair"); }
<xeu>\n { yyerror("invalid Unicode surrogate pair"); }
*************** other .
*** 603,608 ****
--- 626,632 ----
check_string_escape_warning(yytext[1], yyscanner);
addlitchar(unescape_single_char(yytext[1], yyscanner),
yyscanner);
+ SET_YYLLOC_LEN();
}
<xe>{xeoctesc} {
unsigned char c = strtoul(yytext+1, NULL, 8);
*************** other .
*** 611,616 ****
--- 635,641 ----
addlitchar(c, yyscanner);
if (c == '\0' || IS_HIGHBIT_SET(c))
yyextra->saw_non_ascii = true;
+ SET_YYLLOC_LEN();
}
<xe>{xehexesc} {
unsigned char c = strtoul(yytext+2, NULL, 16);
*************** other .
*** 619,624 ****
--- 644,650 ----
addlitchar(c, yyscanner);
if (c == '\0' || IS_HIGHBIT_SET(c))
yyextra->saw_non_ascii = true;
+ SET_YYLLOC_LEN();
}
<xq,xe,xus>{quotecontinue} {
/* ignore */
*************** other .
*** 626,644 ****
<xe>. {
/* This is only needed for \ just before EOF */
addlitchar(yytext[0], yyscanner);
}
<xq,xe,xus><<EOF>> { yyerror("unterminated quoted string"); }
{dolqdelim} {
! SET_YYLLOC();
yyextra->dolqstart = pstrdup(yytext);
BEGIN(xdolq);
startlit();
}
{dolqfailed} {
! SET_YYLLOC();
/* throw back all but the initial "$" */
yyless(1);
/* and treat it as {other} */
return yytext[0];
}
--- 652,674 ----
<xe>. {
/* This is only needed for \ just before EOF */
addlitchar(yytext[0], yyscanner);
+ SET_YYLLOC_LEN();
}
<xq,xe,xus><<EOF>> { yyerror("unterminated quoted string"); }
{dolqdelim} {
! SET_YYLLOC_BEGINS();
yyextra->dolqstart = pstrdup(yytext);
BEGIN(xdolq);
startlit();
+ yylloc->length = 0;
+ SET_YYLLOC_LEN();
}
{dolqfailed} {
! SET_YYLLOC_BEGINS();
/* throw back all but the initial "$" */
yyless(1);
+ SET_YYLLOC_LEN();
/* and treat it as {other} */
return yytext[0];
}
*************** other .
*** 649,654 ****
--- 679,685 ----
yyextra->dolqstart = NULL;
BEGIN(INITIAL);
yylval->str = litbufdup(yyscanner);
+ SET_YYLLOC_LEN();
return SCONST;
}
else
*************** other .
*** 660,688 ****
*/
addlit(yytext, yyleng-1, yyscanner);
yyless(yyleng-1);
}
}
<xdolq>{dolqinside} {
addlit(yytext, yyleng, yyscanner);
}
<xdolq>{dolqfailed} {
addlit(yytext, yyleng, yyscanner);
}
<xdolq>. {
/* This is only needed for $ inside the quoted text */
addlitchar(yytext[0], yyscanner);
}
<xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); }
{xdstart} {
! SET_YYLLOC();
BEGIN(xd);
startlit();
}
{xuistart} {
! SET_YYLLOC();
BEGIN(xui);
startlit();
}
<xd>{xdstop} {
char *ident;
--- 691,725 ----
*/
addlit(yytext, yyleng-1, yyscanner);
yyless(yyleng-1);
+ SET_YYLLOC_LEN();
}
}
<xdolq>{dolqinside} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xdolq>{dolqfailed} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xdolq>. {
/* This is only needed for $ inside the quoted text */
addlitchar(yytext[0], yyscanner);
+ SET_YYLLOC_LEN();
}
<xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); }
{xdstart} {
! SET_YYLLOC_BEGINS();
BEGIN(xd);
startlit();
+ SET_YYLLOC_LEN();
}
{xuistart} {
! SET_YYLLOC_BEGINS();
BEGIN(xui);
startlit();
+ SET_YYLLOC_LEN();
}
<xd>{xdstop} {
char *ident;
*************** other .
*** 694,699 ****
--- 731,737 ----
if (yyextra->literallen >= NAMEDATALEN)
truncate_identifier(ident, yyextra->literallen, true);
yylval->str = ident;
+ SET_YYLLOC_LEN();
return IDENT;
}
<xui>{xuistop1} {
*************** other .
*** 708,713 ****
--- 746,752 ----
yylval->str = ident;
/* throw back all but the quote */
yyless(1);
+ SET_YYLLOC_LEN();
return IDENT;
}
<xui>{xuistop2} {
*************** other .
*** 720,764 ****
if (yyextra->literallen >= NAMEDATALEN)
truncate_identifier(ident, yyextra->literallen, true);
yylval->str = ident;
return IDENT;
}
<xd,xui>{xddouble} {
addlitchar('"', yyscanner);
}
<xd,xui>{xdinside} {
addlit(yytext, yyleng, yyscanner);
}
<xd,xui><<EOF>> { yyerror("unterminated quoted identifier"); }
{xufailed} {
char *ident;
! SET_YYLLOC();
/* throw back all but the initial u/U */
yyless(1);
/* and treat it as {identifier} */
ident = downcase_truncate_identifier(yytext, yyleng, true);
yylval->str = ident;
return IDENT;
}
{typecast} {
! SET_YYLLOC();
return TYPECAST;
}
{dot_dot} {
! SET_YYLLOC();
return DOT_DOT;
}
{colon_equals} {
! SET_YYLLOC();
return COLON_EQUALS;
}
{self} {
! SET_YYLLOC();
return yytext[0];
}
--- 759,811 ----
if (yyextra->literallen >= NAMEDATALEN)
truncate_identifier(ident, yyextra->literallen, true);
yylval->str = ident;
+ SET_YYLLOC_LEN();
return IDENT;
}
<xd,xui>{xddouble} {
addlitchar('"', yyscanner);
+ SET_YYLLOC_LEN();
}
<xd,xui>{xdinside} {
addlit(yytext, yyleng, yyscanner);
+ SET_YYLLOC_LEN();
}
<xd,xui><<EOF>> { yyerror("unterminated quoted identifier"); }
{xufailed} {
char *ident;
! SET_YYLLOC_BEGINS();
/* throw back all but the initial u/U */
yyless(1);
/* and treat it as {identifier} */
ident = downcase_truncate_identifier(yytext, yyleng, true);
yylval->str = ident;
+ SET_YYLLOC_LEN();
return IDENT;
}
{typecast} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return TYPECAST;
}
{dot_dot} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return DOT_DOT;
}
{colon_equals} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return COLON_EQUALS;
}
{self} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return yytext[0];
}
*************** other .
*** 808,814 ****
nchars--; /* else remove the +/-, and check again */
}
! SET_YYLLOC();
if (nchars < yyleng)
{
--- 855,861 ----
nchars--; /* else remove the +/-, and check again */
}
! SET_YYLLOC_BEGINS();
if (nchars < yyleng)
{
*************** other .
*** 839,871 ****
yylval->str = pstrdup("<>");
else
yylval->str = pstrdup(yytext);
return Op;
}
{param} {
! SET_YYLLOC();
yylval->ival = atol(yytext + 1);
return PARAM;
}
{integer} {
! SET_YYLLOC();
return process_integer_literal(yytext, yylval);
}
{decimal} {
! SET_YYLLOC();
yylval->str = pstrdup(yytext);
return FCONST;
}
{decimalfail} {
/* throw back the .., and treat as integer */
yyless(yyleng-2);
! SET_YYLLOC();
return process_integer_literal(yytext, yylval);
}
{real} {
! SET_YYLLOC();
yylval->str = pstrdup(yytext);
return FCONST;
}
{realfail1} {
--- 886,924 ----
yylval->str = pstrdup("<>");
else
yylval->str = pstrdup(yytext);
+ SET_YYLLOC_LEN();
return Op;
}
{param} {
! SET_YYLLOC_BEGINS();
yylval->ival = atol(yytext + 1);
+ SET_YYLLOC_LEN();
return PARAM;
}
{integer} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return process_integer_literal(yytext, yylval);
}
{decimal} {
! SET_YYLLOC_BEGINS();
yylval->str = pstrdup(yytext);
+ SET_YYLLOC_LEN();
return FCONST;
}
{decimalfail} {
/* throw back the .., and treat as integer */
yyless(yyleng-2);
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return process_integer_literal(yytext, yylval);
}
{real} {
! SET_YYLLOC_BEGINS();
yylval->str = pstrdup(yytext);
+ SET_YYLLOC_LEN();
return FCONST;
}
{realfail1} {
*************** other .
*** 876,890 ****
* syntax error anyway, we don't bother to distinguish.
*/
yyless(yyleng-1);
! SET_YYLLOC();
yylval->str = pstrdup(yytext);
return FCONST;
}
{realfail2} {
/* throw back the [Ee][+-], and proceed as above */
yyless(yyleng-2);
! SET_YYLLOC();
yylval->str = pstrdup(yytext);
return FCONST;
}
--- 929,945 ----
* syntax error anyway, we don't bother to distinguish.
*/
yyless(yyleng-1);
! SET_YYLLOC_BEGINS();
yylval->str = pstrdup(yytext);
+ SET_YYLLOC_LEN();
return FCONST;
}
{realfail2} {
/* throw back the [Ee][+-], and proceed as above */
yyless(yyleng-2);
! SET_YYLLOC_BEGINS();
yylval->str = pstrdup(yytext);
+ SET_YYLLOC_LEN();
return FCONST;
}
*************** other .
*** 893,904 ****
const ScanKeyword *keyword;
char *ident;
! SET_YYLLOC();
/* Is it a keyword? */
keyword = ScanKeywordLookup(yytext,
yyextra->keywords,
yyextra->num_keywords);
if (keyword != NULL)
{
yylval->keyword = keyword->name;
--- 948,961 ----
const ScanKeyword *keyword;
char *ident;
! SET_YYLLOC_BEGINS();
+ yylloc->length = 0;
/* Is it a keyword? */
keyword = ScanKeywordLookup(yytext,
yyextra->keywords,
yyextra->num_keywords);
+ SET_YYLLOC_LEN();
if (keyword != NULL)
{
yylval->keyword = keyword->name;
*************** other .
*** 915,926 ****
}
{other} {
! SET_YYLLOC();
return yytext[0];
}
<<EOF>> {
! SET_YYLLOC();
yyterminate();
}
--- 972,985 ----
}
{other} {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
return yytext[0];
}
<<EOF>> {
! SET_YYLLOC_BEGINS();
! SET_YYLLOC_LEN();
yyterminate();
}
*************** scanner_errposition(int location, core_y
*** 982,988 ****
void
scanner_yyerror(const char *message, core_yyscan_t yyscanner)
{
! const char *loc = yyextra->scanbuf + *yylloc;
if (*loc == YY_END_OF_BUFFER_CHAR)
{
--- 1041,1047 ----
void
scanner_yyerror(const char *message, core_yyscan_t yyscanner)
{
! const char *loc = yyextra->scanbuf + yylloc->begins;
if (*loc == YY_END_OF_BUFFER_CHAR)
{
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index a6f4141..5763991 100644
*** a/src/backend/rewrite/rewriteHandler.c
--- b/src/backend/rewrite/rewriteHandler.c
*************** build_column_default(Relation rel, int a
*** 1023,1029 ****
atttype, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
--- 1023,1029 ----
atttype, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
! -1, -1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9e277c5..2de221e 100644
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct A_Const
*** 252,257 ****
--- 252,258 ----
NodeTag type;
Value val; /* value (includes type info, see value.h) */
int location; /* token location, or -1 if unknown */
+ int tok_len; /* token length (in bytes) */
} A_Const;
/*
*************** typedef struct TypeCast
*** 263,268 ****
--- 264,270 ----
Node *arg; /* the expression being casted */
TypeName *typeName; /* the target type */
int location; /* token location, or -1 if unknown */
+ int tok_len; /* token length (in bytes) */
} TypeCast;
/*
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 28a2b12..c164a55 100644
*** a/src/include/nodes/primnodes.h
--- b/src/include/nodes/primnodes.h
*************** typedef struct Const
*** 171,176 ****
--- 171,177 ----
* in the Datum. If false, then the Datum
* contains a pointer to the information. */
int location; /* token location, or -1 if unknown */
+ int tok_len; /* token length (in bytes) */
} Const;
/* ----------------
diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h
index ceaff2f..85f3fdd 100644
*** a/src/include/parser/parse_coerce.h
--- b/src/include/parser/parse_coerce.h
*************** extern Node *coerce_to_target_type(Parse
*** 40,51 ****
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
! int location);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
CoercionContext ccontext);
extern Node *coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
! CoercionContext ccontext, CoercionForm cformat, int location);
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
Oid typeId,
CoercionForm cformat, int location,
--- 40,52 ----
Oid targettype, int32 targettypmod,
CoercionContext ccontext,
CoercionForm cformat,
! int location,
! int tok_len);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
CoercionContext ccontext);
extern Node *coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
! CoercionContext ccontext, CoercionForm cformat, int location, int tok_len);
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
Oid typeId,
CoercionForm cformat, int location,
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 0ca7914..fde2a93 100644
*** a/src/include/parser/parse_node.h
--- b/src/include/parser/parse_node.h
*************** extern ArrayRef *transformArraySubscript
*** 148,153 ****
int32 arrayTypMod,
List *indirection,
Node *assignFrom);
! extern Const *make_const(ParseState *pstate, Value *value, int location);
#endif /* PARSE_NODE_H */
--- 148,153 ----
int32 arrayTypMod,
List *indirection,
Node *assignFrom);
! extern Const *make_const(ParseState *pstate, Value *value, int location, int tok_len);
#endif /* PARSE_NODE_H */
diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h
index 2a88e97..e12ccf4 100644
*** a/src/include/parser/scanner.h
--- b/src/include/parser/scanner.h
*************** typedef union core_YYSTYPE
*** 36,47 ****
/*
* We track token locations in terms of byte offsets from the start of the
* source string, not the column number/line number representation that
! * bison uses by default. Also, to minimize overhead we track only one
! * location (usually the first token location) for each construct, not
! * the beginning and ending locations as bison does by default. It's
! * therefore sufficient to make YYLTYPE an int.
*/
! #define YYLTYPE int
/*
* Another important component of the scanner's API is the token code numbers.
--- 36,51 ----
/*
* We track token locations in terms of byte offsets from the start of the
* source string, not the column number/line number representation that
! * bison uses by default. We track the beginning of the token, as well
! * as its total length.
*/
! typedef struct my_yyltype
! {
! int begins;
! int length;
! } my_yyltype;
!
! #define YYLTYPE my_yyltype
/*
* Another important component of the scanner's API is the token code numbers.
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 8c4c2f7..ce932c4 100644
*** a/src/pl/plpgsql/src/gram.y
--- b/src/pl/plpgsql/src/gram.y
*************** pl_block : decl_sect K_BEGIN proc_sect
*** 367,380 ****
new = palloc0(sizeof(PLpgSQL_stmt_block));
new->cmd_type = PLPGSQL_STMT_BLOCK;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1.label;
new->n_initvars = $1.n_initvars;
new->initvarnos = $1.initvarnos;
new->body = $3;
new->exceptions = $4;
! check_labels($1.label, $6, @6);
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
--- 367,380 ----
new = palloc0(sizeof(PLpgSQL_stmt_block));
new->cmd_type = PLPGSQL_STMT_BLOCK;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1.label;
new->n_initvars = $1.n_initvars;
new->initvarnos = $1.initvarnos;
new->body = $3;
new->exceptions = $4;
! check_labels($1.label, $6, @6.begins);
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
*************** decl_stmt : decl_statement
*** 436,442 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("block label must be placed before DECLARE, not after"),
! parser_errposition(@1)));
}
;
--- 436,442 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("block label must be placed before DECLARE, not after"),
! parser_errposition(@1.begins)));
}
;
*************** decl_statement : decl_varname decl_const
*** 457,463 ****
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("collations are not supported by type %s",
format_type_be($3->typoid)),
! parser_errposition(@4)));
$3->collation = $4;
}
--- 457,463 ----
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("collations are not supported by type %s",
format_type_be($3->typoid)),
! parser_errposition(@4.begins)));
$3->collation = $4;
}
*************** decl_statement : decl_varname decl_const
*** 471,477 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row or record variable cannot be CONSTANT"),
! parser_errposition(@2)));
}
if ($5)
{
--- 471,477 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row or record variable cannot be CONSTANT"),
! parser_errposition(@2.begins)));
}
if ($5)
{
*************** decl_statement : decl_varname decl_const
*** 481,487 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row or record variable cannot be NOT NULL"),
! parser_errposition(@4)));
}
if ($6 != NULL)
--- 481,487 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row or record variable cannot be NOT NULL"),
! parser_errposition(@4.begins)));
}
if ($6 != NULL)
*************** decl_statement : decl_varname decl_const
*** 492,498 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("default value for row or record variable is not supported"),
! parser_errposition(@5)));
}
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
--- 492,498 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("default value for row or record variable is not supported"),
! parser_errposition(@5.begins)));
}
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
*************** decl_cursor_args :
*** 584,590 ****
new = palloc0(sizeof(PLpgSQL_row));
new->dtype = PLPGSQL_DTYPE_ROW;
! new->lineno = plpgsql_location_to_lineno(@1);
new->rowtupdesc = NULL;
new->nfields = list_length($2);
new->fieldnames = palloc(new->nfields * sizeof(char *));
--- 584,590 ----
new = palloc0(sizeof(PLpgSQL_row));
new->dtype = PLPGSQL_DTYPE_ROW;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->rowtupdesc = NULL;
new->nfields = list_length($2);
new->fieldnames = palloc(new->nfields * sizeof(char *));
*************** decl_aliasitem : T_WORD
*** 638,644 ****
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("variable \"%s\" does not exist",
$1.ident),
! parser_errposition(@1)));
$$ = nsi;
}
| T_CWORD
--- 638,644 ----
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("variable \"%s\" does not exist",
$1.ident),
! parser_errposition(@1.begins)));
$$ = nsi;
}
| T_CWORD
*************** decl_aliasitem : T_WORD
*** 664,670 ****
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("variable \"%s\" does not exist",
NameListToString($1.idents)),
! parser_errposition(@1)));
$$ = nsi;
}
;
--- 664,670 ----
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("variable \"%s\" does not exist",
NameListToString($1.idents)),
! parser_errposition(@1.begins)));
$$ = nsi;
}
;
*************** decl_aliasitem : T_WORD
*** 672,678 ****
decl_varname : T_WORD
{
$$.name = $1.ident;
! $$.lineno = plpgsql_location_to_lineno(@1);
/*
* Check to make sure name isn't already declared
* in the current block.
--- 672,678 ----
decl_varname : T_WORD
{
$$.name = $1.ident;
! $$.lineno = plpgsql_location_to_lineno(@1.begins);
/*
* Check to make sure name isn't already declared
* in the current block.
*************** decl_varname : T_WORD
*** 685,691 ****
| unreserved_keyword
{
$$.name = pstrdup($1);
! $$.lineno = plpgsql_location_to_lineno(@1);
/*
* Check to make sure name isn't already declared
* in the current block.
--- 685,691 ----
| unreserved_keyword
{
$$.name = pstrdup($1);
! $$.lineno = plpgsql_location_to_lineno(@1.begins);
/*
* Check to make sure name isn't already declared
* in the current block.
*************** stmt_perform : K_PERFORM expr_until_semi
*** 819,825 ****
new = palloc0(sizeof(PLpgSQL_stmt_perform));
new->cmd_type = PLPGSQL_STMT_PERFORM;
! new->lineno = plpgsql_location_to_lineno(@1);
new->expr = $2;
$$ = (PLpgSQL_stmt *)new;
--- 819,825 ----
new = palloc0(sizeof(PLpgSQL_stmt_perform));
new->cmd_type = PLPGSQL_STMT_PERFORM;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->expr = $2;
$$ = (PLpgSQL_stmt *)new;
*************** stmt_assign : assign_var assign_operato
*** 832,838 ****
new = palloc0(sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
! new->lineno = plpgsql_location_to_lineno(@1);
new->varno = $1;
new->expr = $3;
--- 832,838 ----
new = palloc0(sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->varno = $1;
new->expr = $3;
*************** stmt_getdiag : K_GET getdiag_area_opt K_
*** 847,853 ****
new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
new->cmd_type = PLPGSQL_STMT_GETDIAG;
! new->lineno = plpgsql_location_to_lineno(@1);
new->is_stacked = $2;
new->diag_items = $4;
--- 847,853 ----
new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
new->cmd_type = PLPGSQL_STMT_GETDIAG;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->is_stacked = $2;
new->diag_items = $4;
*************** stmt_getdiag : K_GET getdiag_area_opt K_
*** 868,874 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS",
plpgsql_getdiag_kindname(ditem->kind)),
! parser_errposition(@1)));
break;
/* these fields are disallowed in current case */
case PLPGSQL_GETDIAG_ERROR_CONTEXT:
--- 868,874 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS",
plpgsql_getdiag_kindname(ditem->kind)),
! parser_errposition(@1.begins)));
break;
/* these fields are disallowed in current case */
case PLPGSQL_GETDIAG_ERROR_CONTEXT:
*************** stmt_getdiag : K_GET getdiag_area_opt K_
*** 881,887 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS",
plpgsql_getdiag_kindname(ditem->kind)),
! parser_errposition(@1)));
break;
default:
elog(ERROR, "unrecognized diagnostic item kind: %d",
--- 881,887 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS",
plpgsql_getdiag_kindname(ditem->kind)),
! parser_errposition(@1.begins)));
break;
default:
elog(ERROR, "unrecognized diagnostic item kind: %d",
*************** getdiag_item :
*** 962,993 ****
getdiag_target : T_DATUM
{
! check_assignable($1.datum, @1);
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
$1.datum->dtype == PLPGSQL_DTYPE_REC)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("\"%s\" is not a scalar variable",
NameOfDatum(&($1))),
! parser_errposition(@1)));
$$ = $1.datum->dno;
}
| T_WORD
{
/* just to give a better message than "syntax error" */
! word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1);
}
;
assign_var : T_DATUM
{
! check_assignable($1.datum, @1);
$$ = $1.datum->dno;
}
| assign_var '[' expr_until_rightbracket
--- 962,993 ----
getdiag_target : T_DATUM
{
! check_assignable($1.datum, @1.begins);
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
$1.datum->dtype == PLPGSQL_DTYPE_REC)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("\"%s\" is not a scalar variable",
NameOfDatum(&($1))),
! parser_errposition(@1.begins)));
$$ = $1.datum->dno;
}
| T_WORD
{
/* just to give a better message than "syntax error" */
! word_is_not_variable(&($1), @1.begins);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1.begins);
}
;
assign_var : T_DATUM
{
! check_assignable($1.datum, @1.begins);
$$ = $1.datum->dno;
}
| assign_var '[' expr_until_rightbracket
*************** stmt_if : K_IF expr_until_then proc_se
*** 1013,1019 ****
new = palloc0(sizeof(PLpgSQL_stmt_if));
new->cmd_type = PLPGSQL_STMT_IF;
! new->lineno = plpgsql_location_to_lineno(@1);
new->cond = $2;
new->then_body = $3;
new->elsif_list = $4;
--- 1013,1019 ----
new = palloc0(sizeof(PLpgSQL_stmt_if));
new->cmd_type = PLPGSQL_STMT_IF;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->cond = $2;
new->then_body = $3;
new->elsif_list = $4;
*************** stmt_elsifs :
*** 1032,1038 ****
PLpgSQL_if_elsif *new;
new = palloc0(sizeof(PLpgSQL_if_elsif));
! new->lineno = plpgsql_location_to_lineno(@2);
new->cond = $3;
new->stmts = $4;
--- 1032,1038 ----
PLpgSQL_if_elsif *new;
new = palloc0(sizeof(PLpgSQL_if_elsif));
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->cond = $3;
new->stmts = $4;
*************** stmt_else :
*** 1052,1058 ****
stmt_case : K_CASE opt_expr_until_when case_when_list opt_case_else K_END K_CASE ';'
{
! $$ = make_case(@1, $2, $3, $4);
}
;
--- 1052,1058 ----
stmt_case : K_CASE opt_expr_until_when case_when_list opt_case_else K_END K_CASE ';'
{
! $$ = make_case(@1.begins, $2, $3, $4);
}
;
*************** case_when : K_WHEN expr_until_then proc
*** 1085,1091 ****
{
PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when));
! new->lineno = plpgsql_location_to_lineno(@1);
new->expr = $2;
new->stmts = $3;
$$ = new;
--- 1085,1091 ----
{
PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when));
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->expr = $2;
new->stmts = $3;
$$ = new;
*************** stmt_loop : opt_block_label K_LOOP loop
*** 1117,1123 ****
new = palloc0(sizeof(PLpgSQL_stmt_loop));
new->cmd_type = PLPGSQL_STMT_LOOP;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1;
new->body = $3.stmts;
--- 1117,1123 ----
new = palloc0(sizeof(PLpgSQL_stmt_loop));
new->cmd_type = PLPGSQL_STMT_LOOP;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1;
new->body = $3.stmts;
*************** stmt_while : opt_block_label K_WHILE ex
*** 1134,1140 ****
new = palloc0(sizeof(PLpgSQL_stmt_while));
new->cmd_type = PLPGSQL_STMT_WHILE;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1;
new->cond = $3;
new->body = $4.stmts;
--- 1134,1140 ----
new = palloc0(sizeof(PLpgSQL_stmt_while));
new->cmd_type = PLPGSQL_STMT_WHILE;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1;
new->cond = $3;
new->body = $4.stmts;
*************** stmt_for : opt_block_label K_FOR for_co
*** 1154,1160 ****
PLpgSQL_stmt_fori *new;
new = (PLpgSQL_stmt_fori *) $3;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1;
new->body = $4.stmts;
$$ = (PLpgSQL_stmt *) new;
--- 1154,1160 ----
PLpgSQL_stmt_fori *new;
new = (PLpgSQL_stmt_fori *) $3;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1;
new->body = $4.stmts;
$$ = (PLpgSQL_stmt *) new;
*************** stmt_for : opt_block_label K_FOR for_co
*** 1168,1174 ****
$3->cmd_type == PLPGSQL_STMT_DYNFORS);
/* forq is the common supertype of all three */
new = (PLpgSQL_stmt_forq *) $3;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1;
new->body = $4.stmts;
$$ = (PLpgSQL_stmt *) new;
--- 1168,1174 ----
$3->cmd_type == PLPGSQL_STMT_DYNFORS);
/* forq is the common supertype of all three */
new = (PLpgSQL_stmt_forq *) $3;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1;
new->body = $4.stmts;
$$ = (PLpgSQL_stmt *) new;
*************** stmt_for : opt_block_label K_FOR for_co
*** 1183,1189 ****
for_control : for_variable K_IN
{
int tok = yylex();
! int tokloc = yylloc;
if (tok == K_EXECUTE)
{
--- 1183,1189 ----
for_control : for_variable K_IN
{
int tok = yylex();
! int tokloc = yylloc.begins;
if (tok == K_EXECUTE)
{
*************** for_control : for_variable K_IN
*** 1201,1218 ****
if ($1.rec)
{
new->rec = $1.rec;
! check_assignable((PLpgSQL_datum *) new->rec, @1);
}
else if ($1.row)
{
new->row = $1.row;
! check_assignable((PLpgSQL_datum *) new->row, @1);
}
else if ($1.scalar)
{
/* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar,
! $1.lineno, @1);
/* no need for check_assignable */
}
else
--- 1201,1218 ----
if ($1.rec)
{
new->rec = $1.rec;
! check_assignable((PLpgSQL_datum *) new->rec, @1.begins);
}
else if ($1.row)
{
new->row = $1.row;
! check_assignable((PLpgSQL_datum *) new->row, @1.begins);
}
else if ($1.scalar)
{
/* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar,
! $1.lineno, @1.begins);
/* no need for check_assignable */
}
else
*************** for_control : for_variable K_IN
*** 1220,1226 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("loop variable of loop over rows must be a record or row variable or list of scalar variables"),
! parser_errposition(@1)));
}
new->query = expr;
--- 1220,1226 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("loop variable of loop over rows must be a record or row variable or list of scalar variables"),
! parser_errposition(@1.begins)));
}
new->query = expr;
*************** for_control : for_variable K_IN
*** 1254,1260 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor FOR loop must have only one target variable"),
! parser_errposition(@1)));
/* can't use an unbound cursor this way */
if (cursor->cursor_explicit_expr == NULL)
--- 1254,1260 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor FOR loop must have only one target variable"),
! parser_errposition(@1.begins)));
/* can't use an unbound cursor this way */
if (cursor->cursor_explicit_expr == NULL)
*************** for_control : for_variable K_IN
*** 1344,1350 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("integer FOR loop must have only one target variable"),
! parser_errposition(@1)));
/* create loop's private variable */
fvar = (PLpgSQL_var *)
--- 1344,1350 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("integer FOR loop must have only one target variable"),
! parser_errposition(@1.begins)));
/* create loop's private variable */
fvar = (PLpgSQL_var *)
*************** for_control : for_variable K_IN
*** 1394,1411 ****
if ($1.rec)
{
new->rec = $1.rec;
! check_assignable((PLpgSQL_datum *) new->rec, @1);
}
else if ($1.row)
{
new->row = $1.row;
! check_assignable((PLpgSQL_datum *) new->row, @1);
}
else if ($1.scalar)
{
/* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar,
! $1.lineno, @1);
/* no need for check_assignable */
}
else
--- 1394,1411 ----
if ($1.rec)
{
new->rec = $1.rec;
! check_assignable((PLpgSQL_datum *) new->rec, @1.begins);
}
else if ($1.row)
{
new->row = $1.row;
! check_assignable((PLpgSQL_datum *) new->row, @1.begins);
}
else if ($1.scalar)
{
/* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar,
! $1.lineno, @1.begins);
/* no need for check_assignable */
}
else
*************** for_control : for_variable K_IN
*** 1413,1419 ****
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("loop variable of loop over rows must be a record or row variable or list of scalar variables"),
! parser_errposition(@1)));
}
new->query = expr1;
--- 1413,1419 ----
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("loop variable of loop over rows must be a record or row variable or list of scalar variables"),
! parser_errposition(@1.begins)));
}
new->query = expr1;
*************** for_control : for_variable K_IN
*** 1444,1450 ****
for_variable : T_DATUM
{
$$.name = NameOfDatum(&($1));
! $$.lineno = plpgsql_location_to_lineno(@1);
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW)
{
$$.scalar = NULL;
--- 1444,1450 ----
for_variable : T_DATUM
{
$$.name = NameOfDatum(&($1));
! $$.lineno = plpgsql_location_to_lineno(@1.begins);
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW)
{
$$.scalar = NULL;
*************** for_variable : T_DATUM
*** 1470,1476 ****
if (tok == ',')
$$.row = read_into_scalar_list($$.name,
$$.scalar,
! @1);
}
}
| T_WORD
--- 1470,1476 ----
if (tok == ',')
$$.row = read_into_scalar_list($$.name,
$$.scalar,
! @1.begins);
}
}
| T_WORD
*************** for_variable : T_DATUM
*** 1478,1484 ****
int tok;
$$.name = $1.ident;
! $$.lineno = plpgsql_location_to_lineno(@1);
$$.scalar = NULL;
$$.rec = NULL;
$$.row = NULL;
--- 1478,1484 ----
int tok;
$$.name = $1.ident;
! $$.lineno = plpgsql_location_to_lineno(@1.begins);
$$.scalar = NULL;
$$.rec = NULL;
$$.row = NULL;
*************** for_variable : T_DATUM
*** 1486,1497 ****
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == ',')
! word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1);
}
;
--- 1486,1497 ----
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == ',')
! word_is_not_variable(&($1), @1.begins);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1.begins);
}
;
*************** stmt_foreach_a : opt_block_label K_FOREA
*** 1501,1507 ****
new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
new->cmd_type = PLPGSQL_STMT_FOREACH_A;
! new->lineno = plpgsql_location_to_lineno(@2);
new->label = $1;
new->slice = $4;
new->expr = $7;
--- 1501,1507 ----
new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
new->cmd_type = PLPGSQL_STMT_FOREACH_A;
! new->lineno = plpgsql_location_to_lineno(@2.begins);
new->label = $1;
new->slice = $4;
new->expr = $7;
*************** stmt_foreach_a : opt_block_label K_FOREA
*** 1510,1533 ****
if ($3.rec)
{
new->varno = $3.rec->dno;
! check_assignable((PLpgSQL_datum *) $3.rec, @3);
}
else if ($3.row)
{
new->varno = $3.row->dno;
! check_assignable((PLpgSQL_datum *) $3.row, @3);
}
else if ($3.scalar)
{
new->varno = $3.scalar->dno;
! check_assignable($3.scalar, @3);
}
else
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("loop variable of FOREACH must be a known variable or list of variables"),
! parser_errposition(@3)));
}
check_labels($1, $8.end_label, $8.end_label_location);
--- 1510,1533 ----
if ($3.rec)
{
new->varno = $3.rec->dno;
! check_assignable((PLpgSQL_datum *) $3.rec, @3.begins);
}
else if ($3.row)
{
new->varno = $3.row->dno;
! check_assignable((PLpgSQL_datum *) $3.row, @3.begins);
}
else if ($3.scalar)
{
new->varno = $3.scalar->dno;
! check_assignable($3.scalar, @3.begins);
}
else
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("loop variable of FOREACH must be a known variable or list of variables"),
! parser_errposition(@3.begins)));
}
check_labels($1, $8.end_label, $8.end_label_location);
*************** stmt_exit : exit_type opt_label opt_exi
*** 1554,1560 ****
new = palloc0(sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->is_exit = $1;
! new->lineno = plpgsql_location_to_lineno(@1);
new->label = $2;
new->cond = $3;
--- 1554,1560 ----
new = palloc0(sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->is_exit = $1;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->label = $2;
new->cond = $3;
*************** stmt_return : K_RETURN
*** 1583,1599 ****
if (tok_is_keyword(tok, &yylval,
K_NEXT, "next"))
{
! $$ = make_return_next_stmt(@1);
}
else if (tok_is_keyword(tok, &yylval,
K_QUERY, "query"))
{
! $$ = make_return_query_stmt(@1);
}
else
{
plpgsql_push_back_token(tok);
! $$ = make_return_stmt(@1);
}
}
;
--- 1583,1599 ----
if (tok_is_keyword(tok, &yylval,
K_NEXT, "next"))
{
! $$ = make_return_next_stmt(@1.begins);
}
else if (tok_is_keyword(tok, &yylval,
K_QUERY, "query"))
{
! $$ = make_return_query_stmt(@1.begins);
}
else
{
plpgsql_push_back_token(tok);
! $$ = make_return_stmt(@1.begins);
}
}
;
*************** stmt_raise : K_RAISE
*** 1606,1612 ****
new = palloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
! new->lineno = plpgsql_location_to_lineno(@1);
new->elog_level = ERROR; /* default */
new->condname = NULL;
new->message = NULL;
--- 1606,1612 ----
new = palloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->elog_level = ERROR; /* default */
new->condname = NULL;
new->message = NULL;
*************** loop_body : proc_sect K_END K_LOOP opt_
*** 1741,1747 ****
{
$$.stmts = $1;
$$.end_label = $4;
! $$.end_label_location = @4;
}
;
--- 1741,1747 ----
{
$$.stmts = $1;
$$.end_label = $4;
! $$.end_label_location = @4.begins;
}
;
*************** loop_body : proc_sect K_END K_LOOP opt_
*** 1757,1763 ****
*/
stmt_execsql : K_INSERT
{
! $$ = make_execsql_stmt(K_INSERT, @1);
}
| T_WORD
{
--- 1757,1763 ----
*/
stmt_execsql : K_INSERT
{
! $$ = make_execsql_stmt(K_INSERT, @1.begins);
}
| T_WORD
{
*************** stmt_execsql : K_INSERT
*** 1766,1773 ****
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == '=' || tok == COLON_EQUALS || tok == '[')
! word_is_not_variable(&($1), @1);
! $$ = make_execsql_stmt(T_WORD, @1);
}
| T_CWORD
{
--- 1766,1773 ----
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == '=' || tok == COLON_EQUALS || tok == '[')
! word_is_not_variable(&($1), @1.begins);
! $$ = make_execsql_stmt(T_WORD, @1.begins);
}
| T_CWORD
{
*************** stmt_execsql : K_INSERT
*** 1776,1783 ****
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == '=' || tok == COLON_EQUALS || tok == '[')
! cword_is_not_variable(&($1), @1);
! $$ = make_execsql_stmt(T_CWORD, @1);
}
;
--- 1776,1783 ----
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == '=' || tok == COLON_EQUALS || tok == '[')
! cword_is_not_variable(&($1), @1.begins);
! $$ = make_execsql_stmt(T_CWORD, @1.begins);
}
;
*************** stmt_dynexecute : K_EXECUTE
*** 1795,1801 ****
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
! new->lineno = plpgsql_location_to_lineno(@1);
new->query = expr;
new->into = false;
new->strict = false;
--- 1795,1801 ----
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->query = expr;
new->into = false;
new->strict = false;
*************** stmt_open : K_OPEN cursor_variable
*** 1852,1858 ****
new = palloc0(sizeof(PLpgSQL_stmt_open));
new->cmd_type = PLPGSQL_STMT_OPEN;
! new->lineno = plpgsql_location_to_lineno(@1);
new->curvar = $2->dno;
new->cursor_options = CURSOR_OPT_FAST_PLAN;
--- 1852,1858 ----
new = palloc0(sizeof(PLpgSQL_stmt_open));
new->cmd_type = PLPGSQL_STMT_OPEN;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->curvar = $2->dno;
new->cursor_options = CURSOR_OPT_FAST_PLAN;
*************** stmt_fetch : K_FETCH opt_fetch_directio
*** 1942,1950 ****
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("FETCH statement cannot return multiple rows"),
! parser_errposition(@1)));
! fetch->lineno = plpgsql_location_to_lineno(@1);
fetch->rec = rec;
fetch->row = row;
fetch->curvar = $3->dno;
--- 1942,1950 ----
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("FETCH statement cannot return multiple rows"),
! parser_errposition(@1.begins)));
! fetch->lineno = plpgsql_location_to_lineno(@1.begins);
fetch->rec = rec;
fetch->row = row;
fetch->curvar = $3->dno;
*************** stmt_move : K_MOVE opt_fetch_direction
*** 1958,1964 ****
{
PLpgSQL_stmt_fetch *fetch = $2;
! fetch->lineno = plpgsql_location_to_lineno(@1);
fetch->curvar = $3->dno;
fetch->is_move = true;
--- 1958,1964 ----
{
PLpgSQL_stmt_fetch *fetch = $2;
! fetch->lineno = plpgsql_location_to_lineno(@1.begins);
fetch->curvar = $3->dno;
fetch->is_move = true;
*************** stmt_close : K_CLOSE cursor_variable ';
*** 1978,1984 ****
new = palloc(sizeof(PLpgSQL_stmt_close));
new->cmd_type = PLPGSQL_STMT_CLOSE;
! new->lineno = plpgsql_location_to_lineno(@1);
new->curvar = $2->dno;
$$ = (PLpgSQL_stmt *)new;
--- 1978,1984 ----
new = palloc(sizeof(PLpgSQL_stmt_close));
new->cmd_type = PLPGSQL_STMT_CLOSE;
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->curvar = $2->dno;
$$ = (PLpgSQL_stmt *)new;
*************** cursor_variable : T_DATUM
*** 1998,2022 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cursor variable must be a simple variable"),
! parser_errposition(@1)));
if (((PLpgSQL_var *) $1.datum)->datatype->typoid != REFCURSOROID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("variable \"%s\" must be of type cursor or refcursor",
((PLpgSQL_var *) $1.datum)->refname),
! parser_errposition(@1)));
$$ = (PLpgSQL_var *) $1.datum;
}
| T_WORD
{
/* just to give a better message than "syntax error" */
! word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1);
}
;
--- 1998,2022 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cursor variable must be a simple variable"),
! parser_errposition(@1.begins)));
if (((PLpgSQL_var *) $1.datum)->datatype->typoid != REFCURSOROID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("variable \"%s\" must be of type cursor or refcursor",
((PLpgSQL_var *) $1.datum)->refname),
! parser_errposition(@1.begins)));
$$ = (PLpgSQL_var *) $1.datum;
}
| T_WORD
{
/* just to give a better message than "syntax error" */
! word_is_not_variable(&($1), @1.begins);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
! cword_is_not_variable(&($1), @1.begins);
}
;
*************** exception_sect :
*** 2031,2037 ****
* scope of the names extends to the end of the
* current block.
*/
! int lineno = plpgsql_location_to_lineno(@1);
PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
PLpgSQL_variable *var;
--- 2031,2037 ----
* scope of the names extends to the end of the
* current block.
*/
! int lineno = plpgsql_location_to_lineno(@1.begins);
PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
PLpgSQL_variable *var;
*************** proc_exception : K_WHEN proc_conditions
*** 2077,2083 ****
PLpgSQL_exception *new;
new = palloc0(sizeof(PLpgSQL_exception));
! new->lineno = plpgsql_location_to_lineno(@1);
new->conditions = $2;
new->action = $4;
--- 2077,2083 ----
PLpgSQL_exception *new;
new = palloc0(sizeof(PLpgSQL_exception));
! new->lineno = plpgsql_location_to_lineno(@1.begins);
new->conditions = $2;
new->action = $4;
*************** static void
*** 2310,2318 ****
current_token_is_not_variable(int tok)
{
if (tok == T_WORD)
! word_is_not_variable(&(yylval.word), yylloc);
else if (tok == T_CWORD)
! cword_is_not_variable(&(yylval.cword), yylloc);
else
yyerror("syntax error");
}
--- 2310,2318 ----
current_token_is_not_variable(int tok)
{
if (tok == T_WORD)
! word_is_not_variable(&(yylval.word), yylloc.begins);
else if (tok == T_CWORD)
! cword_is_not_variable(&(yylval.cword), yylloc.begins);
else
yyerror("syntax error");
}
*************** read_sql_construct(int until,
*** 2385,2391 ****
{
tok = yylex();
if (startlocation < 0) /* remember loc of first token */
! startlocation = yylloc;
if (tok == until && parenlevel == 0)
break;
if (tok == until2 && parenlevel == 0)
--- 2385,2391 ----
{
tok = yylex();
if (startlocation < 0) /* remember loc of first token */
! startlocation = yylloc.begins;
if (tok == until && parenlevel == 0)
break;
if (tok == until2 && parenlevel == 0)
*************** read_sql_construct(int until,
*** 2414,2426 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing \"%s\" at end of SQL expression",
expected),
! parser_errposition(yylloc)));
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing \"%s\" at end of SQL statement",
expected),
! parser_errposition(yylloc)));
}
}
--- 2414,2426 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing \"%s\" at end of SQL expression",
expected),
! parser_errposition(yylloc.begins)));
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("missing \"%s\" at end of SQL statement",
expected),
! parser_errposition(yylloc.begins)));
}
}
*************** read_sql_construct(int until,
*** 2432,2438 ****
*endtoken = tok;
/* give helpful complaint about empty input */
! if (startlocation >= yylloc)
{
if (isexpression)
yyerror("missing expression");
--- 2432,2438 ----
*endtoken = tok;
/* give helpful complaint about empty input */
! if (startlocation >= yylloc.begins)
{
if (isexpression)
yyerror("missing expression");
*************** read_sql_construct(int until,
*** 2440,2446 ****
yyerror("missing SQL statement");
}
! plpgsql_append_source_text(&ds, startlocation, yylloc);
/* trim any trailing whitespace, for neatness */
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
--- 2440,2446 ----
yyerror("missing SQL statement");
}
! plpgsql_append_source_text(&ds, startlocation, yylloc.begins);
/* trim any trailing whitespace, for neatness */
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
*************** read_datatype(int tok)
*** 2476,2482 ****
if (tok == YYEMPTY)
tok = yylex();
! startlocation = yylloc;
/*
* If we have a simple or composite identifier, check for %TYPE
--- 2476,2482 ----
if (tok == YYEMPTY)
tok = yylex();
! startlocation = yylloc.begins;
/*
* If we have a simple or composite identifier, check for %TYPE
*************** read_datatype(int tok)
*** 2557,2563 ****
/* set up ds to contain complete typename text */
initStringInfo(&ds);
! plpgsql_append_source_text(&ds, startlocation, yylloc);
type_name = ds.data;
if (type_name[0] == '\0')
--- 2557,2563 ----
/* set up ds to contain complete typename text */
initStringInfo(&ds);
! plpgsql_append_source_text(&ds, startlocation, yylloc.begins);
type_name = ds.data;
if (type_name[0] == '\0')
*************** make_execsql_stmt(int firsttoken, int lo
*** 2608,2614 ****
prev_tok = tok;
tok = yylex();
if (have_into && into_end_loc < 0)
! into_end_loc = yylloc; /* token after the INTO part */
if (tok == ';')
break;
if (tok == 0)
--- 2608,2614 ----
prev_tok = tok;
tok = yylex();
if (have_into && into_end_loc < 0)
! into_end_loc = yylloc.begins; /* token after the INTO part */
if (tok == ';')
break;
if (tok == 0)
*************** make_execsql_stmt(int firsttoken, int lo
*** 2619,2625 ****
if (have_into)
yyerror("INTO specified more than once");
have_into = true;
! into_start_loc = yylloc;
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
read_into_target(&rec, &row, &have_strict);
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
--- 2619,2625 ----
if (have_into)
yyerror("INTO specified more than once");
have_into = true;
! into_start_loc = yylloc.begins;
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
read_into_target(&rec, &row, &have_strict);
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
*************** make_execsql_stmt(int firsttoken, int lo
*** 2637,2646 ****
*/
plpgsql_append_source_text(&ds, location, into_start_loc);
appendStringInfoSpaces(&ds, into_end_loc - into_start_loc);
! plpgsql_append_source_text(&ds, into_end_loc, yylloc);
}
else
! plpgsql_append_source_text(&ds, location, yylloc);
/* trim any trailing whitespace, for neatness */
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
--- 2637,2646 ----
*/
plpgsql_append_source_text(&ds, location, into_start_loc);
appendStringInfoSpaces(&ds, into_end_loc - into_start_loc);
! plpgsql_append_source_text(&ds, into_end_loc, yylloc.begins);
}
else
! plpgsql_append_source_text(&ds, location, yylloc.begins);
/* trim any trailing whitespace, for neatness */
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
*************** make_return_stmt(int location)
*** 2847,2853 ****
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function returning set"),
errhint("Use RETURN NEXT or RETURN QUERY."),
! parser_errposition(yylloc)));
}
else if (plpgsql_curr_compile->out_param_varno >= 0)
{
--- 2847,2853 ----
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function returning set"),
errhint("Use RETURN NEXT or RETURN QUERY."),
! parser_errposition(yylloc.begins)));
}
else if (plpgsql_curr_compile->out_param_varno >= 0)
{
*************** make_return_stmt(int location)
*** 2855,2861 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function with OUT parameters"),
! parser_errposition(yylloc)));
new->retvarno = plpgsql_curr_compile->out_param_varno;
}
else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
--- 2855,2861 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function with OUT parameters"),
! parser_errposition(yylloc.begins)));
new->retvarno = plpgsql_curr_compile->out_param_varno;
}
else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
*************** make_return_stmt(int location)
*** 2864,2870 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function returning void"),
! parser_errposition(yylloc)));
}
else if (plpgsql_curr_compile->fn_retistuple)
{
--- 2864,2870 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN cannot have a parameter in function returning void"),
! parser_errposition(yylloc.begins)));
}
else if (plpgsql_curr_compile->fn_retistuple)
{
*************** make_return_stmt(int location)
*** 2882,2895 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN must specify a record or row variable in function returning row"),
! parser_errposition(yylloc)));
break;
default:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN must specify a record or row variable in function returning row"),
! parser_errposition(yylloc)));
break;
}
if (yylex() != ';')
--- 2882,2895 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN must specify a record or row variable in function returning row"),
! parser_errposition(yylloc.begins)));
break;
default:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN must specify a record or row variable in function returning row"),
! parser_errposition(yylloc.begins)));
break;
}
if (yylex() != ';')
*************** make_return_next_stmt(int location)
*** 2931,2937 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT cannot have a parameter in function with OUT parameters"),
! parser_errposition(yylloc)));
new->retvarno = plpgsql_curr_compile->out_param_varno;
}
else if (plpgsql_curr_compile->fn_retistuple)
--- 2931,2937 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT cannot have a parameter in function with OUT parameters"),
! parser_errposition(yylloc.begins)));
new->retvarno = plpgsql_curr_compile->out_param_varno;
}
else if (plpgsql_curr_compile->fn_retistuple)
*************** make_return_next_stmt(int location)
*** 2946,2959 ****
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT must specify a record or row variable in function returning row"),
! parser_errposition(yylloc)));
break;
default:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT must specify a record or row variable in function returning row"),
! parser_errposition(yylloc)));
break;
}
if (yylex() != ';')
--- 2946,2959 ----
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT must specify a record or row variable in function returning row"),
! parser_errposition(yylloc.begins)));
break;
default:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("RETURN NEXT must specify a record or row variable in function returning row"),
! parser_errposition(yylloc.begins)));
break;
}
if (yylex() != ';')
*************** read_into_target(PLpgSQL_rec **rec, PLpg
*** 3087,3118 ****
case T_DATUM:
if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW)
{
! check_assignable(yylval.wdatum.datum, yylloc);
*row = (PLpgSQL_row *) yylval.wdatum.datum;
if ((tok = yylex()) == ',')
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("record or row variable cannot be part of multiple-item INTO list"),
! parser_errposition(yylloc)));
plpgsql_push_back_token(tok);
}
else if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
{
! check_assignable(yylval.wdatum.datum, yylloc);
*rec = (PLpgSQL_rec *) yylval.wdatum.datum;
if ((tok = yylex()) == ',')
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("record or row variable cannot be part of multiple-item INTO list"),
! parser_errposition(yylloc)));
plpgsql_push_back_token(tok);
}
else
{
*row = read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
! yylval.wdatum.datum, yylloc);
}
break;
--- 3087,3118 ----
case T_DATUM:
if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW)
{
! check_assignable(yylval.wdatum.datum, yylloc.begins);
*row = (PLpgSQL_row *) yylval.wdatum.datum;
if ((tok = yylex()) == ',')
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("record or row variable cannot be part of multiple-item INTO list"),
! parser_errposition(yylloc.begins)));
plpgsql_push_back_token(tok);
}
else if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
{
! check_assignable(yylval.wdatum.datum, yylloc.begins);
*rec = (PLpgSQL_rec *) yylval.wdatum.datum;
if ((tok = yylex()) == ',')
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("record or row variable cannot be part of multiple-item INTO list"),
! parser_errposition(yylloc.begins)));
plpgsql_push_back_token(tok);
}
else
{
*row = read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
! yylval.wdatum.datum, yylloc.begins);
}
break;
*************** read_into_scalar_list(char *initial_name
*** 3151,3170 ****
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many INTO variables specified"),
! parser_errposition(yylloc)));
tok = yylex();
switch (tok)
{
case T_DATUM:
! check_assignable(yylval.wdatum.datum, yylloc);
if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("\"%s\" is not a scalar variable",
NameOfDatum(&(yylval.wdatum))),
! parser_errposition(yylloc)));
fieldnames[nfields] = NameOfDatum(&(yylval.wdatum));
varnos[nfields++] = yylval.wdatum.datum->dno;
break;
--- 3151,3170 ----
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many INTO variables specified"),
! parser_errposition(yylloc.begins)));
tok = yylex();
switch (tok)
{
case T_DATUM:
! check_assignable(yylval.wdatum.datum, yylloc.begins);
if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("\"%s\" is not a scalar variable",
NameOfDatum(&(yylval.wdatum))),
! parser_errposition(yylloc.begins)));
fieldnames[nfields] = NameOfDatum(&(yylval.wdatum));
varnos[nfields++] = yylval.wdatum.datum->dno;
break;
*************** read_cursor_args(PLpgSQL_var *cursor, in
*** 3394,3400 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor \"%s\" has no arguments",
cursor->refname),
! parser_errposition(yylloc)));
if (tok != until)
yyerror("syntax error");
--- 3394,3400 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor \"%s\" has no arguments",
cursor->refname),
! parser_errposition(yylloc.begins)));
if (tok != until)
yyerror("syntax error");
*************** read_cursor_args(PLpgSQL_var *cursor, in
*** 3408,3414 ****
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor \"%s\" has arguments",
cursor->refname),
! parser_errposition(yylloc)));
/*
* Read expressions until the matching ')'.
--- 3408,3414 ----
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cursor \"%s\" has arguments",
cursor->refname),
! parser_errposition(yylloc.begins)));
/*
* Read expressions until the matching ')'.
diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c
index 76e8436..7f18560 100644
*** a/src/pl/plpgsql/src/pl_scanner.c
--- b/src/pl/plpgsql/src/pl_scanner.c
*************** plpgsql_yylex(void)
*** 283,289 ****
push_back_token(tok3, &aux3);
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
! core_yy.scanbuf + aux1.lloc,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
--- 283,289 ----
push_back_token(tok3, &aux3);
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
! core_yy.scanbuf + aux1.lloc.begins,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
*************** plpgsql_yylex(void)
*** 304,310 ****
/* not A.B, so just process A */
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
! core_yy.scanbuf + aux1.lloc,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
--- 304,310 ----
/* not A.B, so just process A */
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
! core_yy.scanbuf + aux1.lloc.begins,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
*************** internal_yylex(TokenAuxData *auxdata)
*** 356,362 ****
yyscanner);
/* remember the length of yytext before it gets changed */
! yytext = core_yy.scanbuf + auxdata->lloc;
auxdata->leng = strlen(yytext);
/* Check for << >> and #, which the core considers operators */
--- 356,362 ----
yyscanner);
/* remember the length of yytext before it gets changed */
! yytext = core_yy.scanbuf + auxdata->lloc.begins;
auxdata->leng = strlen(yytext);
/* Check for << >> and #, which the core considers operators */
*************** plpgsql_scanner_errposition(int location
*** 464,470 ****
void
plpgsql_yyerror(const char *message)
{
! char *yytext = core_yy.scanbuf + plpgsql_yylloc;
if (*yytext == '\0')
{
--- 464,470 ----
void
plpgsql_yyerror(const char *message)
{
! char *yytext = core_yy.scanbuf + plpgsql_yylloc.begins;
if (*yytext == '\0')
{
*************** plpgsql_yyerror(const char *message)
*** 472,478 ****
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: %s is typically the translation of "syntax error" */
errmsg("%s at end of input", _(message)),
! plpgsql_scanner_errposition(plpgsql_yylloc)));
}
else
{
--- 472,478 ----
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: %s is typically the translation of "syntax error" */
errmsg("%s at end of input", _(message)),
! plpgsql_scanner_errposition(plpgsql_yylloc.begins)));
}
else
{
*************** plpgsql_yyerror(const char *message)
*** 488,494 ****
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: first %s is typically the translation of "syntax error" */
errmsg("%s at or near \"%s\"", _(message), yytext),
! plpgsql_scanner_errposition(plpgsql_yylloc)));
}
}
--- 488,494 ----
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: first %s is typically the translation of "syntax error" */
errmsg("%s at or near \"%s\"", _(message), yytext),
! plpgsql_scanner_errposition(plpgsql_yylloc.begins)));
}
}