diff --git a/README.md b/README.md
index 60b3347cb..821b968a4 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@
-
+
diff --git a/RELEASE b/RELEASE
index 329a93076..66da63878 100644
--- a/RELEASE
+++ b/RELEASE
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-Release Notes for Apache AGE release 0.0.0 for PG 14
+Release Notes for Apache AGE release 0.0.0 for PG 15
Apache AGE 0.0.0 - Release Notes
diff --git a/docker/Dockerfile b/docker/Dockerfile
index c30d69313..45298538e 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -16,17 +16,29 @@
# limitations under the License.
#
-FROM postgres:14
+FROM postgres:15
-RUN apt-get update
-RUN apt-get install --assume-yes --no-install-recommends --no-install-suggests \
- bison \
- build-essential \
- flex \
- postgresql-server-dev-14
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends --no-install-suggests \
+ bison \
+ build-essential \
+ flex \
+ postgresql-server-dev-15 \
+ locales
+
+ENV LANG=en_US.UTF-8
+ENV LC_COLLATE=en_US.UTF-8
+ENV LC_CTYPE=en_US.UTF-8
+
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
+ && locale-gen \
+ && update-locale LANG=en_US.UTF-8
COPY . /age
-RUN cd /age && make install
+
+WORKDIR /age
+
+RUN make && make install
COPY docker/docker-entrypoint-initdb.d/00-create-extension-age.sql /docker-entrypoint-initdb.d/00-create-extension-age.sql
diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev
index 5e47d49b7..8d5c0000c 100644
--- a/docker/Dockerfile.dev
+++ b/docker/Dockerfile.dev
@@ -17,15 +17,23 @@
#
-FROM postgres:14-buster
+FROM postgres:14
RUN apt-get update
RUN apt-get install --assume-yes --no-install-recommends --no-install-suggests \
bison \
build-essential \
flex \
- postgresql-server-dev-14
+ postgresql-server-dev-15 \
+ locales
+ENV LANG=en_US.UTF-8
+ENV LC_COLLATE=en_US.UTF-8
+ENV LC_CTYPE=en_US.UTF-8
+
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
+ && locale-gen \
+ && update-locale LANG=en_US.UTF-8
COPY . /age
# Set current working directory to /age/ and build.
diff --git a/src/backend/catalog/ag_catalog.c b/src/backend/catalog/ag_catalog.c
index f7ed249ce..60a576a9e 100644
--- a/src/backend/catalog/ag_catalog.c
+++ b/src/backend/catalog/ag_catalog.c
@@ -137,8 +137,8 @@ static bool is_age_drop(PlannedStmt *pstmt)
if (IsA(obj, String))
{
- Value *val = (Value *)obj;
- char *str = val->val.str;
+ String *val = (String *)obj;
+ char *str = val->sval;
if (!pg_strcasecmp(str, "age"))
return true;
diff --git a/src/backend/commands/graph_commands.c b/src/backend/commands/graph_commands.c
index 7df40b948..2d70e65a5 100644
--- a/src/backend/commands/graph_commands.c
+++ b/src/backend/commands/graph_commands.c
@@ -148,7 +148,7 @@ static Oid create_schema_for_graph(const Name graph_name)
integer = SystemTypeName("int4");
data_type = makeDefElem("as", (Node *)integer, -1);
maxvalue = makeDefElem("maxvalue", (Node *)makeInteger(LABEL_ID_MAX), -1);
- cycle = makeDefElem("cycle", (Node *)makeInteger(true), -1);
+ cycle = makeDefElem("cycle", (Node *)makeBoolean(true), -1);
seq_stmt->options = list_make3(data_type, maxvalue, cycle);
seq_stmt->ownerId = InvalidOid;
seq_stmt->for_identity = false;
@@ -198,7 +198,7 @@ Datum drop_graph(PG_FUNCTION_ARGS)
static void drop_schema_for_graph(char *graph_name_str, const bool cascade)
{
DropStmt *drop_stmt;
- Value *schema_name;
+ String *schema_name;
List *label_id_seq_name;
DropBehavior behavior;
diff --git a/src/backend/commands/label_commands.c b/src/backend/commands/label_commands.c
index 6eb991da4..b2e078702 100644
--- a/src/backend/commands/label_commands.c
+++ b/src/backend/commands/label_commands.c
@@ -516,12 +516,12 @@ static FuncCall *build_id_default_func_expr(char *graph_name, char *label_name,
label_id_func_name = list_make2(makeString("ag_catalog"),
makeString("_label_id"));
graph_name_const = makeNode(A_Const);
- graph_name_const->val.type = T_String;
- graph_name_const->val.val.str = graph_name;
+ graph_name_const->val.sval.type = T_String;
+ graph_name_const->val.sval.sval = graph_name;
graph_name_const->location = -1;
label_name_const = makeNode(A_Const);
- label_name_const->val.type = T_String;
- label_name_const->val.val.str = label_name;
+ label_name_const->val.sval.type = T_String;
+ label_name_const->val.sval.sval = label_name;
label_name_const->location = -1;
label_id_func_args = list_make2(graph_name_const, label_name_const);
label_id_func = makeFuncCall(label_id_func_name, label_id_func_args, COERCE_SQL_SYNTAX, -1);
@@ -530,8 +530,8 @@ static FuncCall *build_id_default_func_expr(char *graph_name, char *label_name,
nextval_func_name = SystemFuncName("nextval");
qualified_seq_name = quote_qualified_identifier(schema_name, seq_name);
qualified_seq_name_const = makeNode(A_Const);
- qualified_seq_name_const->val.type = T_String;
- qualified_seq_name_const->val.val.str = qualified_seq_name;
+ qualified_seq_name_const->val.sval.type = T_String;
+ qualified_seq_name_const->val.sval.sval = qualified_seq_name;
qualified_seq_name_const->location = -1;
regclass_cast = makeNode(TypeCast);
regclass_cast->typeName = SystemTypeName("regclass");
diff --git a/src/backend/executor/cypher_delete.c b/src/backend/executor/cypher_delete.c
index 68fafae77..795d4c0ec 100644
--- a/src/backend/executor/cypher_delete.c
+++ b/src/backend/executor/cypher_delete.c
@@ -377,13 +377,13 @@ static void process_delete_list(CustomScanState *node)
ResultRelInfo *resultRelInfo;
HeapTuple heap_tuple;
char *label_name;
- Value *pos;
+ Integer *pos;
int entity_position;
item = lfirst(lc);
pos = item->entity_position;
- entity_position = pos->val.ival;
+ entity_position = pos->ival;
/* skip if the entity is null */
if (scanTupleSlot->tts_isnull[entity_position - 1])
diff --git a/src/backend/parser/cypher_analyze.c b/src/backend/parser/cypher_analyze.c
index f1c481c85..a154960c1 100644
--- a/src/backend/parser/cypher_analyze.c
+++ b/src/backend/parser/cypher_analyze.c
@@ -756,11 +756,19 @@ static Query *analyze_cypher_and_coerce(List *stmt, RangeTblFunction *rtfunc,
pnsi = addRangeTableEntryForSubquery(pstate, subquery, makeAlias("_", NIL),
lateral, true);
+
rtindex = list_length(pstate->p_rtable);
Assert(rtindex == 1); // rte is the only RangeTblEntry in pstate
+ if (rtindex !=1 )
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("invalid value for rtindex")));
+ }
+
addNSItemToQuery(pstate, pnsi, true, true, true);
- query->targetList = expandNSItemAttrs(pstate, pnsi, 0, -1);
+ query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
markTargetListOrigins(pstate, query->targetList);
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index cb1c48bf0..ba74db062 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -1334,7 +1334,14 @@ static Query *transform_cypher_unwind(cypher_parsestate *cpstate,
pnsi = transform_prev_cypher_clause(cpstate, clause->prev, true);
rtindex = list_length(pstate->p_rtable);
Assert(rtindex == 1); // rte is the first RangeTblEntry in pstate
- query->targetList = expandNSItemAttrs(pstate, pnsi, 0, -1);
+ if (rtindex != 1)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("invalid value for rtindex")));
+ }
+
+ query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
}
target_syntax_loc = exprLocation((const Node *) self->target);
@@ -1393,7 +1400,8 @@ static List *transform_cypher_delete_item_list(cypher_parsestate *cpstate,
{
Node *expr = lfirst(lc);
ColumnRef *col;
- Value *val, *pos;
+ String *val;
+ Integer *pos;
int resno;
cypher_delete_item *item = make_ag_node(cypher_delete_item);
@@ -1420,13 +1428,13 @@ static List *transform_cypher_delete_item_list(cypher_parsestate *cpstate,
(errmsg_internal("unexpected Node for cypher_clause")));
}
- resno = get_target_entry_resno(query->targetList, val->val.str);
+ resno = get_target_entry_resno(query->targetList, val->sval);
if (resno == -1)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("undefined reference to variable %s in DELETE clause",
- val->val.str),
+ val->sval),
parser_errposition(pstate, col->location)));
}
@@ -1434,7 +1442,7 @@ static List *transform_cypher_delete_item_list(cypher_parsestate *cpstate,
pos = makeInteger(resno);
- item->var_name = val->val.str;
+ item->var_name = val->sval;
item->entity_position = pos;
items = lappend(items, item);
@@ -1532,7 +1540,7 @@ cypher_update_information *transform_cypher_remove_item_list(
ColumnRef *ref;
A_Indirection *ind;
char *variable_name, *property_name;
- Value *property_node, *variable_node;
+ String *property_node, *variable_node;
item = make_ag_node(cypher_update_item);
@@ -1578,7 +1586,7 @@ cypher_update_information *transform_cypher_remove_item_list(
variable_node = linitial(ref->fields);
- variable_name = variable_node->val.str;
+ variable_name = variable_node->sval;
item->var_name = variable_name;
item->entity_position = get_target_entry_resno(query->targetList,
@@ -1613,7 +1621,7 @@ cypher_update_information *transform_cypher_remove_item_list(
errmsg("REMOVE clause expects a property name"),
parser_errposition(pstate, set_item->location)));
}
- property_name = property_node->val.str;
+ property_name = property_node->sval;
item->prop_name = property_name;
info->set_items = lappend(info->set_items, item);
@@ -1641,7 +1649,7 @@ cypher_update_information *transform_cypher_set_item_list(
ColumnRef *ref;
A_Indirection *ind;
char *variable_name, *property_name;
- Value *property_node, *variable_node;
+ String *property_node, *variable_node;
int is_entire_prop_update = 0; // true if a map is assigned to variable
// LHS of set_item must be a variable or an indirection.
@@ -1741,7 +1749,7 @@ cypher_update_information *transform_cypher_set_item_list(
parser_errposition(pstate, set_item->location)));
}
- property_name = property_node->val.str;
+ property_name = property_node->sval;
item->prop_name = property_name;
}
@@ -1755,7 +1763,7 @@ cypher_update_information *transform_cypher_set_item_list(
parser_errposition(pstate, set_item->location)));
}
- variable_name = variable_node->val.str;
+ variable_name = variable_node->sval;
item->var_name = variable_name;
item->entity_position = get_target_entry_resno(query->targetList,
@@ -2311,13 +2319,19 @@ static Query *transform_cypher_clause_with_where(cypher_parsestate *cpstate,
Assert(pnsi != NULL);
rtindex = list_length(pstate->p_rtable);
Assert(rtindex == 1); // rte is the only RangeTblEntry in pstate
+ if (rtindex != 1)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("invalid value for rtindex")));
+ }
/*
* add all the target entries in pnsi to the current target list to pass
* all the variables that are introduced in the previous clause to the
* next clause
*/
- query->targetList = expandNSItemAttrs(pstate, pnsi, 0, -1);
+ query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
markTargetListOrigins(pstate, query->targetList);
@@ -2585,6 +2599,12 @@ static Query *transform_cypher_match_pattern(cypher_parsestate *cpstate,
rte = pnsi->p_rte;
rtindex = list_length(pstate->p_rtable);
Assert(rtindex == 1); // rte is the first RangeTblEntry in pstate
+ if (rtindex != 1)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("invalid value for rtindex")));
+ }
/*
* add all the target entries in rte to the current target list to pass
@@ -2592,7 +2612,7 @@ static Query *transform_cypher_match_pattern(cypher_parsestate *cpstate,
* next clause
*/
pnsi = get_namespace_item(pstate, rte);
- query->targetList = expandNSItemAttrs(pstate, pnsi, 0, -1);
+ query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
}
transform_match_pattern(cpstate, query, self->pattern, where);
@@ -3030,7 +3050,7 @@ static FuncCall *prevent_duplicate_edges(cypher_parsestate *cpstate,
List *edges = NIL;
ListCell *lc;
List *qualified_function_name;
- Value *ag_catalog, *edge_fn;
+ String *ag_catalog, *edge_fn;
ag_catalog = makeString("ag_catalog");
edge_fn = makeString("_ag_enforce_edge_uniqueness");
@@ -3135,8 +3155,8 @@ static List *make_join_condition_for_edge(cypher_parsestate *cpstate,
{
Node *left_id = NULL;
Node *right_id = NULL;
- Value *ag_catalog = makeString("ag_catalog");
- Value *func_name;
+ String *ag_catalog = makeString("ag_catalog");
+ String *func_name;
List *qualified_func_name;
List *args = NIL;
List *quals = NIL;
@@ -3186,7 +3206,7 @@ static List *make_join_condition_for_edge(cypher_parsestate *cpstate,
prev_edge->type == ENT_VLE_EDGE)
{
List *qualified_name, *args;
- Value *match_qual;
+ String *match_qual;
FuncCall *fc;
match_qual = makeString("age_match_two_vle_edges");
@@ -3329,8 +3349,8 @@ static List *make_join_condition_for_edge(cypher_parsestate *cpstate,
static Node *make_type_cast_to_agtype(Node *arg)
{
TypeCast *n = makeNode(TypeCast);
- Value *ag_catalog = makeString("ag_catalog");
- Value *agtype_str = makeString("agtype");
+ String *ag_catalog = makeString("ag_catalog");
+ String *agtype_str = makeString("agtype");
List *qualified_name = list_make2(ag_catalog, agtype_str);
n->arg = arg;
@@ -3347,8 +3367,8 @@ static Node *make_bool_a_const(bool state)
{
A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = (state ? "true" : "false");
+ n->val.sval.type = T_String;
+ n->val.sval.sval = (state ? "true" : "false");
n->location = -1;
// typecast to agtype
@@ -3397,7 +3417,7 @@ static List *join_to_entity(cypher_parsestate *cpstate,
else if (entity->type == ENT_VLE_EDGE)
{
List *qualified_name, *args;
- Value *ag_catalog, *match_qual;
+ String *ag_catalog, *match_qual;
bool is_left_side;
FuncCall *fc;
@@ -3520,12 +3540,12 @@ static A_Expr *filter_vertices_on_label_id(cypher_parsestate *cpstate,
cpstate->graph_oid);
A_Const *n;
FuncCall *fc;
- Value *ag_catalog, *extract_label_id;
+ String *ag_catalog, *extract_label_id;
int32 label_id = lcd->id;
n = makeNode(A_Const);
- n->val.type = T_Integer;
- n->val.val.ival = label_id;
+ n->val.ival.type = T_Integer;
+ n->val.ival.ival = label_id;
n->location = -1;
ag_catalog = makeString("ag_catalog");
@@ -6775,10 +6795,16 @@ static void handle_prev_clause(cypher_parsestate *cpstate, Query *query,
if (first_rte)
{
Assert(rtindex == 1);
+ if (rtindex != 1)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("invalid value for rtindex")));
+ }
}
// add all the rte's attributes to the current queries targetlist
- query->targetList = expandNSItemAttrs(pstate, pnsi, 0, -1);
+ query->targetList = expandNSItemAttrs(pstate, pnsi, 0, true, -1);
}
ParseNamespaceItem *find_pnsi(cypher_parsestate *cpstate, char *varname)
diff --git a/src/backend/parser/cypher_expr.c b/src/backend/parser/cypher_expr.c
index a54652303..646ac9e2f 100644
--- a/src/backend/parser/cypher_expr.c
+++ b/src/backend/parser/cypher_expr.c
@@ -42,7 +42,6 @@
#include "parser/parse_relation.h"
#include "utils/builtins.h"
#include "utils/float.h"
-#include "utils/int8.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -211,23 +210,27 @@ static Node *transform_A_Const(cypher_parsestate *cpstate, A_Const *ac)
{
ParseState *pstate = (ParseState *)cpstate;
ParseCallbackState pcbstate;
- Value *v = &ac->val;
+
Datum d = (Datum)0;
bool is_null = false;
Const *c;
setup_parser_errposition_callback(&pcbstate, pstate, ac->location);
- switch (nodeTag(v))
+ switch (nodeTag(&ac->val))
{
case T_Integer:
- d = integer_to_agtype((int64)intVal(v));
+ d = integer_to_agtype((int64)intVal(&ac->val));
break;
case T_Float:
{
- char *n = strVal(v);
+ char *n = ac->val.sval.sval;
+ char *endptr;
int64 i;
+ errno = 0;
+
+ i = strtoi64(ac->val.fval.fval, &endptr, 10);
- if (scanint8(n, true, &i))
+ if (errno == 0 && *endptr == '\0')
{
d = integer_to_agtype(i);
}
@@ -240,15 +243,19 @@ static Node *transform_A_Const(cypher_parsestate *cpstate, A_Const *ac)
}
break;
case T_String:
- d = string_to_agtype(strVal(v));
+ d = string_to_agtype(strVal(&ac->val));
break;
- case T_Null:
- is_null = true;
+ case T_Boolean:
+ d = boolean_to_agtype(boolVal(&ac->val));
break;
default:
- ereport(ERROR,
- (errmsg_internal("unrecognized node type: %d", nodeTag(v))));
- return NULL;
+ if (ac->isnull) {
+ is_null = true;
+ } else {
+ ereport(ERROR,
+ (errmsg_internal("unrecognized node type: %d", nodeTag(&ac->val))));
+ return NULL;
+ }
}
cancel_parser_errposition_callback(&pcbstate);
@@ -865,7 +872,7 @@ static Node *transform_A_Indirection(cypher_parsestate *cpstate,
if (!indices->lidx)
{
A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
+ n->isnull = true;
n->location = -1;
node = transform_cypher_expr_recurse(cpstate, (Node *)n);
}
@@ -879,7 +886,7 @@ static Node *transform_A_Indirection(cypher_parsestate *cpstate,
if (!indices->uidx)
{
A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
+ n->isnull = true;
n->location = -1;
node = transform_cypher_expr_recurse(cpstate, (Node *)n);
}
@@ -1092,7 +1099,7 @@ static Node *transform_FuncCall(cypher_parsestate *cpstate, FuncCall *fn)
if (list_length(fn->funcname) == 1)
{
/* get the name, size, and the ag name allocated */
- char *name = ((Value*)linitial(fn->funcname))->val.str;
+ char *name = ((String*)linitial(fn->funcname))->sval;
int pnlen = strlen(name);
char *ag_name = palloc(pnlen + 5);
int i;
@@ -1286,7 +1293,7 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
{
A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
+ n->isnull = true;
n->location = -1;
defresult = (Node *) n;
}
diff --git a/src/backend/parser/cypher_gram.y b/src/backend/parser/cypher_gram.y
index 26908122c..846e02010 100644
--- a/src/backend/parser/cypher_gram.y
+++ b/src/backend/parser/cypher_gram.y
@@ -200,7 +200,7 @@ static Node *make_not_expr(Node *expr, int location);
// arithmetic operators
static Node *do_negate(Node *n, int location);
-static void do_negate_float(Value *v);
+static void do_negate_float(Float *v);
// indirection
static Node *append_indirection(Node *expr, Node *selector);
@@ -349,7 +349,7 @@ call_stmt:
FuncCall *fc = (FuncCall*)$4;
ColumnRef *cr = (ColumnRef*)$2;
List *fields = cr->fields;
- Value *string = linitial(fields);
+ String *string = linitial(fields);
/*
* A function can only be qualified with a single schema. So, we
@@ -396,7 +396,7 @@ call_stmt:
FuncCall *fc = (FuncCall*)$4;
ColumnRef *cr = (ColumnRef*)$2;
List *fields = cr->fields;
- Value *string = linitial(fields);
+ String *string = linitial(fields);
/*
* A function can only be qualified with a single schema. So, we
@@ -584,7 +584,7 @@ cypher_varlen_opt:
A_Const *lidx = (A_Const *) n->lidx;
A_Const *uidx = (A_Const *) n->uidx;
- if (lidx->val.val.ival > uidx->val.val.ival)
+ if (lidx->val.ival.ival > uidx->val.ival.ival)
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid range"),
ag_scanner_errposition(@2, scanner)));
@@ -1466,7 +1466,7 @@ expr:
{
ColumnRef *cr = (ColumnRef*)$3;
List *fields = cr->fields;
- Value *string = linitial(fields);
+ String *string = linitial(fields);
$$ = append_indirection($1, (Node*)string);
}
@@ -1481,7 +1481,7 @@ expr:
FuncCall *fc = (FuncCall*)$3;
ColumnRef *cr = (ColumnRef*)$1;
List *fields = cr->fields;
- Value *string = linitial(fields);
+ String *string = linitial(fields);
/*
* A function can only be qualified with a single schema. So, we
@@ -1505,7 +1505,7 @@ expr:
{
ColumnRef *cr = (ColumnRef*)$3;
List *fields = cr->fields;
- Value *string = linitial(fields);
+ String *string = linitial(fields);
$$ = append_indirection($1, (Node*)string);
}
@@ -2008,14 +2008,14 @@ static Node *do_negate(Node *n, int location)
// report the constant's location as that of the '-' sign
c->location = location;
- if (c->val.type == T_Integer)
+ if (c->val.ival.type == T_Integer)
{
- c->val.val.ival = -c->val.val.ival;
+ c->val.ival.ival = -c->val.ival.ival;
return n;
}
- else if (c->val.type == T_Float)
+ else if (c->val.fval.type == T_Float)
{
- do_negate_float(&c->val);
+ do_negate_float(&c->val.fval);
return n;
}
}
@@ -2023,14 +2023,16 @@ static Node *do_negate(Node *n, int location)
return (Node *)makeSimpleA_Expr(AEXPR_OP, "-", NULL, n, location);
}
-static void do_negate_float(Value *v)
+static void do_negate_float(Float *v)
{
- Assert(IsA(v, Float));
-
- if (v->val.str[0] == '-')
- v->val.str = v->val.str + 1; // just strip the '-'
- else
- v->val.str = psprintf("-%s", v->val.str);
+ char *oldval = v->fval;
+
+ if (*oldval == '+')
+ oldval++;
+ if (*oldval == '-')
+ v->fval = oldval+1; /* just strip the '-' */
+ else
+ v->fval = psprintf("-%s", oldval);
}
/*
@@ -2064,60 +2066,56 @@ static Node *append_indirection(Node *expr, Node *selector)
static Node *make_int_const(int i, int location)
{
- A_Const *n;
+ A_Const *n = makeNode(A_Const);
- n = makeNode(A_Const);
- n->val.type = T_Integer;
- n->val.val.ival = i;
+ n->val.ival.type = T_Integer;
+ n->val.ival.ival = i;
n->location = location;
- return (Node *)n;
+ return (Node *) n;
}
static Node *make_float_const(char *s, int location)
{
- A_Const *n;
+ A_Const *n = makeNode(A_Const);
- n = makeNode(A_Const);
- n->val.type = T_Float;
- n->val.val.str = s;
+ n->val.fval.type = T_Float;
+ n->val.fval.fval = s;
n->location = location;
- return (Node *)n;
+ return (Node *) n;
}
static Node *make_string_const(char *s, int location)
{
- A_Const *n;
+ A_Const *n = makeNode(A_Const);
- n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = s;
+ n->val.sval.type = T_String;
+ n->val.sval.sval = s;
n->location = location;
- return (Node *)n;
+ return (Node *) n;
}
static Node *make_bool_const(bool b, int location)
{
- cypher_bool_const *n;
+ A_Const *n = makeNode(A_Const);
- n = make_ag_node(cypher_bool_const);
- n->boolean = b;
+ n->val.boolval.type = T_Boolean;
+ n->val.boolval.boolval = b;
n->location = location;
- return (Node *)n;
+ return (Node *) n;
}
static Node *make_null_const(int location)
{
- A_Const *n;
-
- n = makeNode(A_Const);
- n->val.type = T_Null;
+ A_Const *n = makeNode(A_Const);
+
+ n->isnull = true;
n->location = location;
- return (Node *)n;
+ return (Node *) n;
}
/*
@@ -2149,7 +2147,7 @@ static Node *make_function_expr(List *func_name, List *exprs, int location)
char *name;
/* get the name of the function */
- name = ((Value*)linitial(func_name))->val.str;
+ name = ((String*)linitial(func_name))->sval;
/*
* Check for openCypher functions that are directly mapped to PG
@@ -2247,7 +2245,7 @@ static Node *make_set_op(SetOperation op, bool all_or_distinct, List *larg,
/* check if A_Expr is a comparison expression */
static bool is_A_Expr_a_comparison_operation(A_Expr *a)
{
- Value *v = NULL;
+ String *v = NULL;
char *opr_name = NULL;
/* we don't support qualified comparison operators */
@@ -2263,7 +2261,7 @@ static bool is_A_Expr_a_comparison_operation(A_Expr *a)
Assert(v->type == T_String);
/* get the string value */
- opr_name = v->val.str;
+ opr_name = v->sval;
/* verify it is a comparison operation */
if (strcmp(opr_name, "<") == 0)
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 376137aba..242a951e2 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -54,7 +54,6 @@
#include "utils/builtins.h"
#include "utils/float.h"
#include "utils/fmgroids.h"
-#include "utils/int8.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
@@ -182,7 +181,7 @@ static int extract_variadic_args_min(FunctionCallInfo fcinfo,
int variadic_start, bool convert_unknown,
Datum **args, Oid **types, bool **nulls,
int min_num_args);
-static agtype_value* agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo);
+static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo);
agtype_value *agtype_composite_to_agtype_value_binary(agtype *a);
/* global storage of OID for agtype and _agtype */
@@ -959,7 +958,7 @@ static void agtype_in_scalar(void *pstate, char *token,
case AGTYPE_TOKEN_INTEGER:
Assert(token != NULL);
v.type = AGTV_INTEGER;
- scanint8(token, false, &v.val.int_value);
+ v.val.int_value = pg_strtoint64(token);
break;
case AGTYPE_TOKEN_FLOAT:
Assert(token != NULL);
@@ -2364,7 +2363,7 @@ Datum make_edge(Datum id, Datum startid, Datum endid, Datum label,
properties);
}
-static agtype_value* agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo)
+static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo)
{
int nargs;
int i;
@@ -2377,7 +2376,9 @@ static agtype_value* agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo)
nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
if (nargs < 0)
- PG_RETURN_NULL();
+ {
+ return NULL;
+ }
if (nargs % 2 != 0)
{
@@ -2420,7 +2421,14 @@ PG_FUNCTION_INFO_V1(agtype_build_map);
*/
Datum agtype_build_map(PG_FUNCTION_ARGS)
{
- agtype_value *result= agtype_build_map_as_agtype_value(fcinfo);
+ agtype_value *result = NULL;
+
+ result = agtype_build_map_as_agtype_value(fcinfo);
+ if (result == NULL)
+ {
+ PG_RETURN_NULL();
+ }
+
PG_RETURN_POINTER(agtype_value_to_agtype(result));
}
@@ -2448,8 +2456,16 @@ PG_FUNCTION_INFO_V1(agtype_build_map_nonull);
*/
Datum agtype_build_map_nonull(PG_FUNCTION_ARGS)
{
- agtype_value *result= agtype_build_map_as_agtype_value(fcinfo);
+ agtype_value *result = NULL;
+
+ result = agtype_build_map_as_agtype_value(fcinfo);
+ if (result == NULL)
+ {
+ PG_RETURN_NULL();
+ }
+
remove_null_from_agtype_object(result);
+
PG_RETURN_POINTER(agtype_value_to_agtype(result));
}
@@ -5446,18 +5462,26 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
if (type != AGTYPEOID)
{
if (type == INT2OID)
+ {
result = (int64) DatumGetInt16(arg);
+ }
else if (type == INT4OID)
+ {
result = (int64) DatumGetInt32(arg);
+ }
else if (type == INT8OID)
+ {
result = (int64) DatumGetInt64(arg);
+ }
else if (type == FLOAT4OID)
{
float4 f = DatumGetFloat4(arg);
if (isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float4)PG_INT64_MIN || f > (float4)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
@@ -5466,8 +5490,10 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
float8 f = DatumGetFloat8(arg);
if (isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float8)PG_INT64_MIN || f > (float8)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
@@ -5479,25 +5505,36 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
numeric_float8_no_overflow, arg));
if (isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float8)PG_INT64_MIN || f > (float8)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
else if (type == CSTRINGOID || type == TEXTOID)
{
+ char *endptr;
if (type == CSTRINGOID)
+ {
string = DatumGetCString(arg);
+ }
else
+ {
string = text_to_cstring(DatumGetTextPP(arg));
+ }
/* convert it if it is a regular integer string */
- is_valid = scanint8(string, true, &result);
+ result = strtoi64(string, &endptr, 10);
+
/*
* If it isn't an integer string, try converting it as a float
* string.
*/
- if (!is_valid)
+ result = float8in_internal_null(string, NULL, "double precision",
+ string, &is_valid);
+
+ if (*endptr != '\0')
{
float f;
@@ -5508,16 +5545,18 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
* return null.
*/
if (!is_valid || isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < PG_INT64_MIN || f > (double)PG_INT64_MAX)
PG_RETURN_NULL();
result = (int64) f;
}
}
else
+ {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("toInteger() unsupported argument type %d",
type)));
+ }
}
else
{
@@ -5537,11 +5576,13 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
result = agtv_value->val.int_value;
else if (agtv_value->type == AGTV_FLOAT)
{
- float f = agtv_value->val.float_value;
+ float8 f = agtv_value->val.float_value;
if (isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float8)PG_INT64_MIN || f > (float8)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
@@ -5554,25 +5595,29 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
numeric_float8_no_overflow, num));
if (isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float8)PG_INT64_MIN || f > (float8)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
else if (agtv_value->type == AGTV_STRING)
{
+ char *endptr;
/* we need a null terminated cstring */
string = strndup(agtv_value->val.string.val,
agtv_value->val.string.len);
/* convert it if it is a regular integer string */
- is_valid = scanint8(string, true, &result);
+ result = strtoi64(string, &endptr, 10);
+
/*
* If it isn't an integer string, try converting it as a float
* string.
*/
- if (!is_valid)
+ if (*endptr != '\0')
{
- float f;
+ float8 f;
f = float8in_internal_null(string, NULL, "double precision",
string, &is_valid);
@@ -5582,18 +5627,24 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
* return null.
*/
if (!is_valid || isnan(f) || isinf(f) ||
- f < PG_INT64_MIN || f > PG_INT64_MAX)
+ f < (float8)PG_INT64_MIN || f > (float8)PG_INT64_MAX)
+ {
PG_RETURN_NULL();
+ }
result = (int64) f;
}
else
+ {
free(string);
+ }
}
else
+ {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("toInteger() unsupported argument agtype %d",
agtv_value->type)));
+ }
}
/* build the result */
diff --git a/src/backend/utils/graph_generation.c b/src/backend/utils/graph_generation.c
index 9b507e11a..0f58fbc36 100644
--- a/src/backend/utils/graph_generation.c
+++ b/src/backend/utils/graph_generation.c
@@ -83,7 +83,7 @@ Datum create_complete_graph(PG_FUNCTION_ARGS)
int64 no_vertices;
int64 i,j,vid = 1, eid, start_vid, end_vid;
- Name vtx_label_name;
+ Name vtx_label_name = NULL;
Name edge_label_name;
int32 vtx_label_id;
int32 edge_label_id;
diff --git a/src/include/nodes/cypher_nodes.h b/src/include/nodes/cypher_nodes.h
index 64318eb5d..0b2f65349 100644
--- a/src/include/nodes/cypher_nodes.h
+++ b/src/include/nodes/cypher_nodes.h
@@ -393,7 +393,7 @@ typedef struct cypher_delete_information
typedef struct cypher_delete_item
{
ExtensibleNode extensible;
- Value *entity_position;
+ Integer *entity_position;
char *var_name;
} cypher_delete_item;