diff --git a/.asf.yaml b/.asf.yaml
index 8a0149a0..be18a25c 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -50,6 +50,10 @@ github:
       required_pull_request_reviews:
         required_approving_review_count: 1
 
+    PG18:
+      required_pull_request_reviews:
+        required_approving_review_count: 1
+
     PG17:
       required_pull_request_reviews:
         required_approving_review_count: 1
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 6baa297c..f860c2b1 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -19,5 +19,8 @@ PG16:
 PG17:
 - base-branch: 'PG17'
 
+PG18:
+- base-branch: 'PG18'
+
 master:
 - base-branch: 'master'
diff --git a/.github/workflows/go-driver.yml b/.github/workflows/go-driver.yml
index 64044f91..1b0379c3 100644
--- a/.github/workflows/go-driver.yml
+++ b/.github/workflows/go-driver.yml
@@ -2,10 +2,10 @@ name: Go Driver Tests
 
 on:
   push:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
   pull_request:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
 jobs:
   build:
diff --git a/.github/workflows/installcheck.yaml b/.github/workflows/installcheck.yaml
index f2b69a02..3ee97296 100644
--- a/.github/workflows/installcheck.yaml
+++ b/.github/workflows/installcheck.yaml
@@ -2,62 +2,63 @@ name: Build / Regression
 
 on:
   push:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
+
   pull_request:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
 jobs:
   build:
     runs-on: ubuntu-latest
 
     steps:
-      - name: Get latest commit id of PostgreSQL 17
+      - name: Get latest commit id of PostgreSQL 18
         run: |
-          echo "PG_COMMIT_HASH=$(git ls-remote https://git.postgresql.org/git/postgresql.git refs/heads/REL_17_STABLE | awk '{print $1}')" >> $GITHUB_ENV
+          echo "PG_COMMIT_HASH=$(git ls-remote https://git.postgresql.org/git/postgresql.git refs/heads/REL_18_STABLE | awk '{print $1}')" >> $GITHUB_ENV
 
-      - name: Cache PostgreSQL 17
+      - name: Cache PostgreSQL 18
         uses: actions/cache@v3
-        id: pg17cache
+        id: pg18cache
         with:
-          path: ~/pg17
-          key: ${{ runner.os }}-v1-pg17-${{ env.PG_COMMIT_HASH }}
+          path: ~/pg18
+          key: ${{ runner.os }}-v1-pg18-${{ env.PG_COMMIT_HASH }}
 
-      - name: Install dependencies
+      - name: Install necessary dependencies
         run: |
           sudo apt-get update
           sudo apt-get install -y build-essential libreadline-dev zlib1g-dev flex bison
 
-      - name: Install PostgreSQL 17 and some extensions
-        if: steps.pg17cache.outputs.cache-hit != 'true'
+      - name: Install PostgreSQL 18 and some extensions
+        if: steps.pg18cache.outputs.cache-hit != 'true'
         run: |
-          git clone --depth 1 --branch REL_17_STABLE https://git.postgresql.org/git/postgresql.git ~/pg17source
-          cd ~/pg17source
-          ./configure --prefix=$HOME/pg17 CFLAGS="-std=gnu99 -ggdb -O0" --enable-cassert
+          git clone --depth 1 --branch REL_18_STABLE https://git.postgresql.org/git/postgresql.git ~/pg18source
+          cd ~/pg18source
+          ./configure --prefix=$HOME/pg18 CFLAGS="-std=gnu99 -ggdb -O0" --enable-cassert
           make install -j$(nproc) > /dev/null
           cd contrib
           cd fuzzystrmatch
-          make PG_CONFIG=$HOME/pg17/bin/pg_config install -j$(nproc) > /dev/null
+          make PG_CONFIG=$HOME/pg18/bin/pg_config install -j$(nproc) > /dev/null
           cd ../pg_trgm
-          make PG_CONFIG=$HOME/pg17/bin/pg_config install -j$(nproc) > /dev/null
+          make PG_CONFIG=$HOME/pg18/bin/pg_config install -j$(nproc) > /dev/null
 
       - uses: actions/checkout@v3
 
       - name: Build AGE
         id: build
         run: |
-          make PG_CONFIG=$HOME/pg17/bin/pg_config install -j$(nproc)
-        
+          make PG_CONFIG=$HOME/pg18/bin/pg_config install -j$(nproc)
+
       - name: Pull and build pgvector
         id: pgvector
         run: |
           git clone https://github.com/pgvector/pgvector.git
           cd pgvector
-          make PG_CONFIG=$HOME/pg17/bin/pg_config install -j$(nproc) > /dev/null
+          make PG_CONFIG=$HOME/pg18/bin/pg_config install -j$(nproc) > /dev/null
 
       - name: Regression tests
         id: regression_tests
         run: |
-          make PG_CONFIG=$HOME/pg17/bin/pg_config installcheck EXTRA_TESTS="pgvector fuzzystrmatch pg_trgm"
+          make PG_CONFIG=$HOME/pg18/bin/pg_config installcheck EXTRA_TESTS="pgvector fuzzystrmatch pg_trgm"
         continue-on-error: true
 
       - name: Dump regression test errors
diff --git a/.github/workflows/jdbc-driver.yaml b/.github/workflows/jdbc-driver.yaml
index 54ca612f..293db7b8 100644
--- a/.github/workflows/jdbc-driver.yaml
+++ b/.github/workflows/jdbc-driver.yaml
@@ -2,10 +2,10 @@ name: JDBC Driver Tests
 
 on:
   push:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
   pull_request:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
 jobs:
   build:
diff --git a/.github/workflows/nodejs-driver.yaml b/.github/workflows/nodejs-driver.yaml
index 156cb851..c2da7fe6 100644
--- a/.github/workflows/nodejs-driver.yaml
+++ b/.github/workflows/nodejs-driver.yaml
@@ -2,10 +2,10 @@ name: Nodejs Driver Tests
 
 on:
   push:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
   pull_request:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
 jobs:
   build:
diff --git a/.github/workflows/python-driver.yaml b/.github/workflows/python-driver.yaml
index 70488e73..860cbcf2 100644
--- a/.github/workflows/python-driver.yaml
+++ b/.github/workflows/python-driver.yaml
@@ -2,10 +2,10 @@ name: Python Driver Tests
 
 on:
   push:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
   pull_request:
-    branches: [ "PG17" ]
+    branches: [ "PG18" ]
 
 jobs:
   build:
@@ -24,7 +24,7 @@ jobs:
     - name: Set up python
       uses: actions/setup-python@v4
       with:
-        python-version: '3.10'
+        python-version: '3.12'
 
     - name: Install pre-requisites
       run: |
@@ -33,7 +33,7 @@ jobs:
 
     - name: Build
       run: |
-        python setup.py install
+        pip install .
 
     - name: Test
       run: |
diff --git a/.gitignore b/.gitignore
index a8e809dd..03923b03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,5 +11,7 @@ age--*.*.*.sql
 !age--*--*sql
 __pycache__
 **/__pycache__
+**/.venv
+**/apache_age_python.egg-info
 
 drivers/python/build
diff --git a/README.md b/README.md
index c886b63d..9f99f6dd 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
     <a href="https://age.apache.org/age-manual/master/_static/logo.png" target="_blank">
     </a>
      is a leading multi-model graph database </h3>
-
+     
 </h3>
 
 <h3 align="center">Graph Processing & Analytics for Relational Databases</h3>
@@ -24,7 +24,7 @@
 
 
 
-<p align="center">
+<p align="center">                                                                                                    
   <a href="https://github.com/apache/age/blob/master/LICENSE">
     <img src="https://img.shields.io/github/license/apache/age"/>
   </a>
@@ -154,16 +154,16 @@ Clone the <a href="https://github.com/apache/age">github repository</a> or downl
 </a>
 Run the pg_config utility and check the version of PostgreSQL. Currently, only PostgreSQL versions 11, 12, 13, 14, 15, 16 & 17 are supported. If you have any other version of Postgres, you will need to install PostgreSQL version 11, 12, 13, 14, 15, 16 & 17.
 <br>
-
+    
 ```bash
 pg_config
 ```
 Run the following command in the source code directory of Apache AGE to build and install the extension.  
-
+     
 ```bash
 make install
 ```
-
+     
 If the path to your Postgres installation is not in the PATH variable, add the path in the arguments:
 ```bash
 make PG_CONFIG=/path/to/postgres/bin/pg_config install
@@ -228,14 +228,14 @@ SELECT create_graph('graph_name');
 To create a single vertex with label and properties, use the CREATE clause.
 
 ```bash
-SELECT *
+SELECT * 
 FROM cypher('graph_name', $$
     CREATE (:label {property:"Node A"})
 $$) as (v agtype);
 ```
 
 ```bash
-SELECT *
+SELECT * 
 FROM cypher('graph_name', $$
     CREATE (:label {property:"Node B"})
 $$) as (v agtype);
@@ -244,7 +244,7 @@ $$) as (v agtype);
 To create an edge between two nodes and set its properties:
 
 ```bash
-SELECT *
+SELECT * 
 FROM cypher('graph_name', $$
     MATCH (a:label), (b:label)
     WHERE a.property = 'Node A' AND b.property = 'Node B'
diff --git a/RELEASE b/RELEASE
index 02c68dd4..4525eab2 100644
--- a/RELEASE
+++ b/RELEASE
@@ -15,12 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#
-# Please note that, as Apache AGE 1.6.0 for PostgreSQL 17 is
-# new, there isn't an upgrade script.
-#
-
-Release Notes for Apache AGE release 1.6.0 for PG17 branch
+Release Notes for Apache AGE release 1.6.0 for master branch (currently PG17)
 
 Apache AGE 1.6.0 - Release Notes
 
diff --git a/age--1.5.0--1.6.0.sql b/age--1.5.0--1.6.0.sql
new file mode 100644
index 00000000..ede715c1
--- /dev/null
+++ b/age--1.5.0--1.6.0.sql
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--* This is a TEMPLATE for upgrading from the previous version of Apache AGE
+--* Please adjust the below ALTER EXTENSION to reflect the -- correct version it
+--* is upgrading to.
+
+-- This will only work within a major version of PostgreSQL, not across
+-- major versions.
+
+--* Please add all additions, deletions, and modifications to the end of this
+--* file. We need to keep the order of these changes.
+--* REMOVE ALL LINES ABOVE, and this one, that start with --*
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "ALTER EXTENSION age UPDATE TO '1.6.0'" to load this file. \quit
+
+CREATE FUNCTION ag_catalog.agtype_contains_top_level(agtype, agtype)
+    RETURNS boolean
+    LANGUAGE c
+    IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR @>> (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_contains_top_level,
+  COMMUTATOR = '<<@',
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_contained_by_top_level(agtype, agtype)
+    RETURNS boolean
+    LANGUAGE c
+    IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR <<@ (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_contained_by_top_level,
+  COMMUTATOR = '@>>',
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+/*
+ * We have to drop and recreate the operators, because
+ * commutator is not modifiable using ALTER OPERATOR.
+ */
+ALTER EXTENSION age
+    DROP OPERATOR ? (agtype, agtype);
+ALTER EXTENSION age
+    DROP OPERATOR ? (agtype, text);
+ALTER EXTENSION age
+    DROP OPERATOR ?| (agtype, agtype);
+ALTER EXTENSION age
+    DROP OPERATOR ?| (agtype, text[]);
+ALTER EXTENSION age
+    DROP OPERATOR ?& (agtype, agtype);
+ALTER EXTENSION age
+    DROP OPERATOR ?& (agtype, text[]);
+ALTER EXTENSION age
+    DROP OPERATOR @> (agtype, agtype);
+ALTER EXTENSION age
+    DROP OPERATOR <@ (agtype, agtype);
+
+DROP OPERATOR ? (agtype, agtype), ? (agtype, text),
+              ?| (agtype, agtype), ?| (agtype, text[]),
+              ?& (agtype, agtype), ?& (agtype, text[]),
+              @> (agtype, agtype), <@ (agtype, agtype);
+
+CREATE OPERATOR ? (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_exists_agtype,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR ? (
+  LEFTARG = agtype,
+  RIGHTARG = text,
+  FUNCTION = ag_catalog.agtype_exists,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR ?| (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_exists_any_agtype,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR ?| (
+  LEFTARG = agtype,
+  RIGHTARG = text[],
+  FUNCTION = ag_catalog.agtype_exists_any,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR ?& (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_exists_all_agtype,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR ?& (
+  LEFTARG = agtype,
+  RIGHTARG = text[],
+  FUNCTION = ag_catalog.agtype_exists_all,
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR @> (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_contains,
+  COMMUTATOR = '<@',
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+CREATE OPERATOR <@ (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.agtype_contained_by,
+  COMMUTATOR = '@>',
+  RESTRICT = matchingsel,
+  JOIN = matchingjoinsel
+);
+
+/*
+ * Since there is no option to add or drop operator from class,
+ * we have to drop and recreate the whole operator class.
+ * Reference: https://www.postgresql.org/docs/current/sql-alteropclass.html
+ */
+
+ALTER EXTENSION age
+    DROP OPERATOR CLASS ag_catalog.gin_agtype_ops USING gin;
+
+DROP OPERATOR CLASS ag_catalog.gin_agtype_ops USING gin;
+DROP OPERATOR FAMILY ag_catalog.gin_agtype_ops USING gin;
+
+CREATE OPERATOR CLASS ag_catalog.gin_agtype_ops
+DEFAULT FOR TYPE agtype USING gin AS
+  OPERATOR 7 @>(agtype, agtype),
+  OPERATOR 8 <@(agtype, agtype),
+  OPERATOR 9 ?(agtype, agtype),
+  OPERATOR 10 ?|(agtype, agtype),
+  OPERATOR 11 ?&(agtype, agtype),
+  OPERATOR 12 @>>(agtype, agtype),
+  OPERATOR 13 <<@(agtype, agtype),
+  FUNCTION 1 ag_catalog.gin_compare_agtype(text,text),
+  FUNCTION 2 ag_catalog.gin_extract_agtype(agtype, internal),
+  FUNCTION 3 ag_catalog.gin_extract_agtype_query(agtype, internal, int2,
+                                                 internal, internal),
+  FUNCTION 4 ag_catalog.gin_consistent_agtype(internal, int2, agtype, int4,
+                                              internal, internal),
+  FUNCTION 6 ag_catalog.gin_triconsistent_agtype(internal, int2, agtype, int4,
+                                                 internal, internal, internal),
+STORAGE text;
+
+-- this function went from variadic "any" to just "any" type
+CREATE OR REPLACE FUNCTION ag_catalog.age_tostring("any")
+    RETURNS agtype
+    LANGUAGE c
+    IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+-- this is a new function for graph statistics
+CREATE FUNCTION ag_catalog.age_graph_stats(agtype)
+    RETURNS agtype
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog.graph_exists(graph_name name)
+    RETURNS agtype
+    LANGUAGE c
+    AS 'MODULE_PATHNAME', 'age_graph_exists';
+
+CREATE FUNCTION ag_catalog.age_is_valid_label_name(agtype)
+    RETURNS boolean
+    LANGUAGE c
+    IMMUTABLE
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OR REPLACE FUNCTION ag_catalog.create_vlabel(graph_name cstring, label_name cstring)
+    RETURNS void
+    LANGUAGE c
+    AS 'MODULE_PATHNAME';
+
+CREATE OR REPLACE FUNCTION ag_catalog.create_elabel(graph_name cstring, label_name cstring)
+    RETURNS void
+    LANGUAGE c
+    AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog.agtype_to_json(agtype)
+    RETURNS json
+    LANGUAGE c
+    IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE CAST (agtype AS json)
+    WITH FUNCTION ag_catalog.agtype_to_json(agtype);
+
+CREATE FUNCTION ag_catalog.agtype_array_to_agtype(agtype[])
+    RETURNS agtype
+    LANGUAGE c
+    IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE CAST (agtype[] AS agtype)
+    WITH FUNCTION ag_catalog.agtype_array_to_agtype(agtype[]);
+
+CREATE OPERATOR =~ (
+  LEFTARG = agtype,
+  RIGHTARG = agtype,
+  FUNCTION = ag_catalog.age_eq_tilde
+);
diff --git a/age--1.6.0--y.y.y.sql b/age--1.6.0--y.y.y.sql
index d781be98..2d693a43 100644
--- a/age--1.6.0--y.y.y.sql
+++ b/age--1.6.0--y.y.y.sql
@@ -31,3 +31,23 @@
 --* file. We need to keep the order of these changes.
 --* REMOVE ALL LINES ABOVE, and this one, that start with --*
 
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness2(graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness3(graphid, graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness4(graphid, graphid, graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0436dc8f..3eb17c79 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -17,14 +17,14 @@
 #
 
 # Build stage: Install necessary development tools for compilation and installation
-FROM postgres:17 AS build
+FROM postgres:18 AS build
 
 RUN apt-get update \
     && apt-get install -y --no-install-recommends --no-install-suggests \
        bison \
        build-essential \
        flex \
-       postgresql-server-dev-17
+       postgresql-server-dev-18
 
 COPY . /age
 
@@ -34,7 +34,7 @@ RUN make && make install
 
 
 # Final stage: Create a final image by copying the files created in the build stage
-FROM postgres:17
+FROM postgres:18
 
 RUN apt-get update \
     && apt-get install -y --no-install-recommends --no-install-suggests \
@@ -48,9 +48,9 @@ ENV LANG=en_US.UTF-8
 ENV LC_COLLATE=en_US.UTF-8
 ENV LC_CTYPE=en_US.UTF-8
 
-COPY --from=build /usr/lib/postgresql/17/lib/age.so /usr/lib/postgresql/17/lib/
-COPY --from=build /usr/share/postgresql/17/extension/age--1.6.0.sql /usr/share/postgresql/17/extension/
-COPY --from=build /usr/share/postgresql/17/extension/age.control /usr/share/postgresql/17/extension/
+COPY --from=build /usr/lib/postgresql/18/lib/age.so /usr/lib/postgresql/18/lib/
+COPY --from=build /usr/share/postgresql/18/extension/age--1.6.0.sql /usr/share/postgresql/18/extension/
+COPY --from=build /usr/share/postgresql/18/extension/age.control /usr/share/postgresql/18/extension/
 COPY docker/docker-entrypoint-initdb.d/00-create-extension-age.sql /docker-entrypoint-initdb.d/00-create-extension-age.sql
 
 CMD ["postgres", "-c", "shared_preload_libraries=age"]
diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev
index 48b2db3e..e02c21fc 100644
--- a/docker/Dockerfile.dev
+++ b/docker/Dockerfile.dev
@@ -17,14 +17,14 @@
 #
 
 
-FROM postgres:17
+FROM postgres:18
 
 RUN apt-get update
 RUN apt-get install --assume-yes --no-install-recommends --no-install-suggests \
   bison \
   build-essential \
   flex \
-  postgresql-server-dev-17 \
+  postgresql-server-dev-18 \
   locales
 
 ENV LANG=en_US.UTF-8
diff --git a/drivers/docker-compose.yml b/drivers/docker-compose.yml
index c83d26f4..5ae7b79a 100644
--- a/drivers/docker-compose.yml
+++ b/drivers/docker-compose.yml
@@ -1,7 +1,7 @@
 version: "3.3"
 services:
   db:
-    image: apache/age:dev_snapshot_PG17
+    image: apache/age:dev_snapshot_PG18
     environment:
       - POSTGRES_USER=postgres
       - POSTGRES_PASSWORD=agens
diff --git a/drivers/golang/go.mod b/drivers/golang/go.mod
index 95628d9f..e212c432 100644
--- a/drivers/golang/go.mod
+++ b/drivers/golang/go.mod
@@ -31,5 +31,5 @@ require (
 	github.com/davecgh/go-spew v1.1.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 // indirect
-	gopkg.in/yaml.v3 v3.0.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/drivers/golang/go.sum b/drivers/golang/go.sum
index 26bb0f3b..eba2fed1 100644
--- a/drivers/golang/go.sum
+++ b/drivers/golang/go.sum
@@ -2,8 +2,6 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 h
 github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
-github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -11,14 +9,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
 golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
 golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
-gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/drivers/jdbc/lib/src/test/java/org/apache/age/jdbc/BaseDockerizedTest.java b/drivers/jdbc/lib/src/test/java/org/apache/age/jdbc/BaseDockerizedTest.java
index 393175c3..d9caa4bb 100644
--- a/drivers/jdbc/lib/src/test/java/org/apache/age/jdbc/BaseDockerizedTest.java
+++ b/drivers/jdbc/lib/src/test/java/org/apache/age/jdbc/BaseDockerizedTest.java
@@ -52,7 +52,7 @@ public class BaseDockerizedTest {
         String CORRECT_DB_PASSWORDS = "postgres";
 
         agensGraphContainer = new GenericContainer<>(DockerImageName
-            .parse("apache/age:dev_snapshot_master"))
+            .parse("apache/age:dev_snapshot_PG18"))
             .withEnv("POSTGRES_PASSWORD", CORRECT_DB_PASSWORDS)
             .withExposedPorts(5432);
         agensGraphContainer.start();
diff --git a/drivers/python/README.md b/drivers/python/README.md
index 18465227..749b44bf 100644
--- a/drivers/python/README.md
+++ b/drivers/python/README.md
@@ -62,7 +62,7 @@ python -m unittest -v test_agtypes.py
 
 ### Build from source
 ```
-python setup.py install
+pip install .
 ```
 
 ### For more information about [Apache AGE](https://age.apache.org/)
diff --git a/drivers/python/age/age.py b/drivers/python/age/age.py
index 817cc6e5..b1aa8215 100644
--- a/drivers/python/age/age.py
+++ b/drivers/python/age/age.py
@@ -26,7 +26,7 @@ from .builder import parseAgeValue
 _EXCEPTION_NoConnection = NoConnection()
 _EXCEPTION_GraphNotSet = GraphNotSet()
 
-WHITESPACE = re.compile('\s')
+WHITESPACE = re.compile(r'\s')
 
 
 class AgeDumper(psycopg.adapt.Dumper):
@@ -233,3 +233,4 @@ class Age:
 
     # def queryCypher(self, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
     #     return queryCypher(self.connection, self.graphName, cypherStmt, columns, params)
+
diff --git a/drivers/python/pyproject.toml b/drivers/python/pyproject.toml
new file mode 100644
index 00000000..18112381
--- /dev/null
+++ b/drivers/python/pyproject.toml
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[build-system]
+requires = ["setuptools>=61.0", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "apache-age-python"
+version = "0.0.7"
+description = "Python driver support for Apache AGE"
+readme = "README.md"
+requires-python = ">=3.9"
+license = "Apache-2.0"
+keywords = ["Graph Database", "Apache AGE", "PostgreSQL"]
+authors = [
+    {name = "Ikchan Kwon, Apache AGE", email = "dev-subscribe@age.apache.org"}
+]
+classifiers = [
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3.12",
+    "Programming Language :: Python :: 3.13",
+    "Programming Language :: Python :: 3.14",
+]
+dependencies = [
+    "psycopg",
+    "antlr4-python3-runtime==4.11.1",
+]
+
+[project.urls]
+Homepage = "https://github.com/apache/age/tree/master/drivers/python"
+Download = "https://github.com/apache/age/releases"
+
+[tool.setuptools]
+packages = ["age", "age.gen", "age.networkx"]
diff --git a/drivers/python/setup.py b/drivers/python/setup.py
index 1da49d9c..d0eed26b 100644
--- a/drivers/python/setup.py
+++ b/drivers/python/setup.py
@@ -13,28 +13,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from setuptools import setup, find_packages
-from age import VERSION 
+# This setup.py is maintained for backward compatibility.
+# All package configuration is in pyproject.toml. For installation,
+# use: pip install .
 
-with open("README.md", "r", encoding='utf8') as fh:
-    long_description = fh.read()
+from setuptools import setup
 
-setup(
-    name             = 'apache-age-python',
-    version          = '0.0.7',
-    description      = 'Python driver support for Apache AGE',
-    long_description=long_description,
-    long_description_content_type="text/markdown",
-    author           = 'Ikchan Kwon, Apache AGE',
-    author_email     = 'dev-subscribe@age.apache.org',
-    url              = 'https://github.com/apache/age/tree/master/drivers/python',
-    download_url     = 'https://github.com/apache/age/releases' ,
-    license          = 'Apache2.0',
-    install_requires = [ 'psycopg', 'antlr4-python3-runtime==4.11.1'],
-    packages         = ['age', 'age.gen','age.networkx'],
-    keywords         = ['Graph Database', 'Apache AGE', 'PostgreSQL'],
-    python_requires  = '>=3.9',
-    classifiers      = [
-        'Programming Language :: Python :: 3.9'
-    ]
-)
+setup()
diff --git a/regress/expected/age_load.out b/regress/expected/age_load.out
index b638e636..55d1ff1d 100644
--- a/regress/expected/age_load.out
+++ b/regress/expected/age_load.out
@@ -16,7 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-\! cp -r regress/age_load/data regress/instance/data/age_load
+\! rm -rf /tmp/age/age_load
+\! mkdir -p /tmp/age
+\! cp -r regress/age_load/data /tmp/age/age_load
 LOAD 'age';
 SET search_path TO ag_catalog;
 -- Create a country using CREATE clause
@@ -43,13 +45,6 @@ SELECT load_labels_from_file('agload_test_graph', 'Country',
  
 (1 row)
 
--- A temporary table should have been created with 54 ids; 1 from CREATE and 53 from file
-SELECT COUNT(*)=54 FROM "_agload_test_graph_ag_vertex_ids";
- ?column? 
-----------
- t
-(1 row)
-
 -- Sequence should be equal to max entry id i.e. 248
 SELECT currval('agload_test_graph."Country_id_seq"')=248;
  ?column? 
@@ -74,13 +69,6 @@ NOTICE:  VLabel "City" has been created
  
 (1 row)
 
--- Temporary table should have 54+72485 rows now
-SELECT COUNT(*)=54+72485 FROM "_agload_test_graph_ag_vertex_ids";
- ?column? 
-----------
- t
-(1 row)
-
 -- Sequence should be equal to max entry id i.e. 146941
 SELECT currval('agload_test_graph."City_id_seq"')=146941;
  ?column? 
@@ -415,6 +403,43 @@ SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges2]->() RETURN prop
  {"bool": "false", "string": "nUll", "numeric": "3.14"}
 (6 rows)
 
+--
+-- Check sandbox
+--
+-- check null file name
+SELECT load_labels_from_file('agload_conversion', 'Person1', NULL, true, true);
+ERROR:  file path must not be NULL
+SELECT load_edges_from_file('agload_conversion', 'Edges1', NULL, true);
+ERROR:  file path must not be NULL
+-- check no file name
+SELECT load_labels_from_file('agload_conversion', 'Person1', '', true, true);
+ERROR:  file name cannot be zero length
+SELECT load_edges_from_file('agload_conversion', 'Edges1', '', true);
+ERROR:  file name cannot be zero length
+-- check for file/path does not exist
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load_xxx/conversion_vertices.csv', true, true);
+ERROR:  File or path does not exist [/tmp/age/age_load_xxx/conversion_vertices.csv]
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load_xxx/conversion_edges.csv', true);
+ERROR:  File or path does not exist [/tmp/age/age_load_xxx/conversion_edges.csv]
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
+ERROR:  File or path does not exist [/tmp/age/age_load/conversion_vertices.txt]
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
+ERROR:  File or path does not exist [/tmp/age/age_load/conversion_edges.txt]
+-- check wrong extension
+\! touch /tmp/age/age_load/conversion_vertices.txt
+\! touch /tmp/age/age_load/conversion_edges.txt
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
+ERROR:  You can only load files with extension [.csv].
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
+ERROR:  You can only load files with extension [.csv].
+-- check outside sandbox directory
+SELECT load_labels_from_file('agload_conversion', 'Person1', '../../etc/passwd', true, true);
+ERROR:  You can only load files located in [/tmp/age/].
+SELECT load_edges_from_file('agload_conversion', 'Edges1', '../../etc/passwd', true);
+ERROR:  You can only load files located in [/tmp/age/].
+--
+-- Cleanup
+--
 SELECT drop_graph('agload_conversion', true);
 NOTICE:  drop cascades to 6 other objects
 DETAIL:  drop cascades to table agload_conversion._ag_label_vertex
@@ -429,3 +454,6 @@ NOTICE:  graph "agload_conversion" has been dropped
  
 (1 row)
 
+--
+-- End
+--
diff --git a/regress/expected/agtype.out b/regress/expected/agtype.out
index d4a577c0..065f357f 100644
--- a/regress/expected/agtype.out
+++ b/regress/expected/agtype.out
@@ -3776,9 +3776,110 @@ SELECT agtype_build_map('1', '1', 2, 2, 3.14, 3.14, 'e', 2.71);
  {"1": "1", "2": 2, "e": 2.71::numeric, "3.14": 3.14::numeric}
 (1 row)
 
+--
+-- Bug found from issue 2043 - Regression in string concatenation using the + operator
+--
+-- This bug impacted specific numeric cases too.
+--
+SELECT * FROM create_graph('issue_2243');
+NOTICE:  graph "issue_2243" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+SELECT * FROM cypher('issue_2243', $$
+    CREATE (n30164502:Node {data_id: 30164502})
+    RETURN id(n30164502) + ':test_n' + n30164502.data_id
+  $$ ) as (result agtype);
+              result              
+----------------------------------
+ "844424930131969:test_n30164502"
+(1 row)
+
+-- concat / add
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer + ":test_n" + 9223372036854775807::integer
+  $$ ) as (result agtype);
+                     result                      
+-------------------------------------------------
+ "9223372036854775807:test_n9223372036854775807"
+(1 row)
+
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric + 9223372036854775807::integer
+  $$ ) as (result agtype);
+            result             
+-------------------------------
+ 18446744073709551614::numeric
+(1 row)
+
+-- sub
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric - 9223372036854775807::integer
+  $$ ) as (result agtype);
+   result   
+------------
+ 0::numeric
+(1 row)
+
+-- mul
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric * 9223372036854775807::integer
+  $$ ) as (result agtype);
+                     result                      
+-------------------------------------------------
+ 85070591730234615847396907784232501249::numeric
+(1 row)
+
+-- div
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric / 9223372036854775807::integer
+  $$ ) as (result agtype);
+             result              
+---------------------------------
+ 1.00000000000000000000::numeric
+(1 row)
+
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer / 9223372036854775807::numeric
+  $$ ) as (result agtype);
+             result              
+---------------------------------
+ 1.00000000000000000000::numeric
+(1 row)
+
+-- mod
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric % 9223372036854775807::integer
+  $$ ) as (result agtype);
+   result   
+------------
+ 0::numeric
+(1 row)
+
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer % 9223372036854775807::numeric
+  $$ ) as (result agtype);
+   result   
+------------
+ 0::numeric
+(1 row)
+
 --
 -- Cleanup
 --
+SELECT drop_graph('issue_2243', true);
+NOTICE:  drop cascades to 3 other objects
+DETAIL:  drop cascades to table issue_2243._ag_label_vertex
+drop cascades to table issue_2243._ag_label_edge
+drop cascades to table issue_2243."Node"
+NOTICE:  graph "issue_2243" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 SELECT drop_graph('agtype_build_map', true);
 NOTICE:  drop cascades to 2 other objects
 DETAIL:  drop cascades to table agtype_build_map._ag_label_vertex
diff --git a/regress/expected/catalog.out b/regress/expected/catalog.out
index d06a0ce6..a15fa469 100644
--- a/regress/expected/catalog.out
+++ b/regress/expected/catalog.out
@@ -457,7 +457,146 @@ NOTICE:  graph does not exist
 (1 row)
 
 DROP FUNCTION raise_notice(TEXT);
--- dropping the graph
+--
+-- Fix issue 2245 - Creating more than 41 vlabels causes drop_graph to fail with
+--  label (relation) cache corrupted
+--
+-- this result will change if another graph was created prior to this point.
+SELECT count(*) FROM ag_label;
+ count 
+-------
+     2
+(1 row)
+
+SELECT * FROM create_graph('issue_2245');
+NOTICE:  graph "issue_2245" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+SELECT * FROM cypher('issue_2245', $$
+  CREATE (a1:Part1 {part_num: '123'}), (a2:Part2 {part_num: '345'}), (a3:Part3 {part_num: '456'}),
+         (a4:Part4 {part_num: '789'}), (a5:Part5 {part_num: '123'}), (a6:Part6 {part_num: '345'}),
+         (a7:Part7 {part_num: '456'}), (a8:Part8 {part_num: '789'}), (a9:Part9 {part_num: '123'}),
+         (a10:Part10 {part_num: '345'}), (a11:Part11 {part_num: '456'}), (a12:Part12 {part_num: '789'}),
+         (a13:Part13 {part_num: '123'}), (a14:Part14 {part_num: '345'}), (a15:Part15 {part_num: '456'}),
+         (a16:Part16 {part_num: '789'}), (a17:Part17 {part_num: '123'}), (a18:Part18 {part_num: '345'}),
+         (a19:Part19 {part_num: '456'}), (a20:Part20 {part_num: '789'}), (a21:Part21 {part_num: '123'}),
+         (a22:Part22 {part_num: '345'}), (a23:Part23 {part_num: '456'}), (a24:Part24 {part_num: '789'}),
+         (a25:Part25 {part_num: '123'}), (a26:Part26 {part_num: '345'}), (a27:Part27 {part_num: '456'}),
+         (a28:Part28 {part_num: '789'}), (a29:Part29 {part_num: '789'}), (a30:Part30 {part_num: '123'}),
+         (a31:Part31 {part_num: '345'}), (a32:Part32 {part_num: '456'}), (a33:Part33 {part_num: '789'}),
+         (a34:Part34 {part_num: '123'}), (a35:Part35 {part_num: '345'}), (a36:Part36 {part_num: '456'}),
+         (a37:Part37 {part_num: '789'}), (a38:Part38 {part_num: '123'}), (a39:Part39 {part_num: '345'}),
+         (a40:Part40 {part_num: '456'}), (a41:Part41 {part_num: '789'}), (a42:Part42 {part_num: '345'}),
+         (a43:Part43 {part_num: '456'}), (a44:Part44 {part_num: '789'}), (a45:Part45 {part_num: '456'}),
+         (a46:Part46 {part_num: '789'}), (a47:Part47 {part_num: '456'}), (a48:Part48 {part_num: '789'}),
+         (a49:Part49 {part_num: '789'}), (a50:Part50 {part_num: '456'}), (a51:Part51 {part_num: '789'})
+  $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT count(*) FROM ag_label;
+ count 
+-------
+    55
+(1 row)
+
+SELECT drop_graph('issue_2245', true);
+NOTICE:  drop cascades to 53 other objects
+DETAIL:  drop cascades to table issue_2245._ag_label_vertex
+drop cascades to table issue_2245._ag_label_edge
+drop cascades to table issue_2245."Part1"
+drop cascades to table issue_2245."Part2"
+drop cascades to table issue_2245."Part3"
+drop cascades to table issue_2245."Part4"
+drop cascades to table issue_2245."Part5"
+drop cascades to table issue_2245."Part6"
+drop cascades to table issue_2245."Part7"
+drop cascades to table issue_2245."Part8"
+drop cascades to table issue_2245."Part9"
+drop cascades to table issue_2245."Part10"
+drop cascades to table issue_2245."Part11"
+drop cascades to table issue_2245."Part12"
+drop cascades to table issue_2245."Part13"
+drop cascades to table issue_2245."Part14"
+drop cascades to table issue_2245."Part15"
+drop cascades to table issue_2245."Part16"
+drop cascades to table issue_2245."Part17"
+drop cascades to table issue_2245."Part18"
+drop cascades to table issue_2245."Part19"
+drop cascades to table issue_2245."Part20"
+drop cascades to table issue_2245."Part21"
+drop cascades to table issue_2245."Part22"
+drop cascades to table issue_2245."Part23"
+drop cascades to table issue_2245."Part24"
+drop cascades to table issue_2245."Part25"
+drop cascades to table issue_2245."Part26"
+drop cascades to table issue_2245."Part27"
+drop cascades to table issue_2245."Part28"
+drop cascades to table issue_2245."Part29"
+drop cascades to table issue_2245."Part30"
+drop cascades to table issue_2245."Part31"
+drop cascades to table issue_2245."Part32"
+drop cascades to table issue_2245."Part33"
+drop cascades to table issue_2245."Part34"
+drop cascades to table issue_2245."Part35"
+drop cascades to table issue_2245."Part36"
+drop cascades to table issue_2245."Part37"
+drop cascades to table issue_2245."Part38"
+drop cascades to table issue_2245."Part39"
+drop cascades to table issue_2245."Part40"
+drop cascades to table issue_2245."Part41"
+drop cascades to table issue_2245."Part42"
+drop cascades to table issue_2245."Part43"
+drop cascades to table issue_2245."Part44"
+drop cascades to table issue_2245."Part45"
+drop cascades to table issue_2245."Part46"
+drop cascades to table issue_2245."Part47"
+drop cascades to table issue_2245."Part48"
+drop cascades to table issue_2245."Part49"
+drop cascades to table issue_2245."Part50"
+drop cascades to table issue_2245."Part51"
+NOTICE:  graph "issue_2245" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
+-- this result should be the same as the one before the create_graph
+SELECT count(*) FROM ag_label;
+ count 
+-------
+     2
+(1 row)
+
+-- create the graph again
+SELECT * FROM create_graph('issue_2245');
+NOTICE:  graph "issue_2245" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+SELECT count(*) FROM ag_label;
+ count 
+-------
+     4
+(1 row)
+
+-- dropping the graphs
+SELECT drop_graph('issue_2245', true);
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to table issue_2245._ag_label_vertex
+drop cascades to table issue_2245._ag_label_edge
+NOTICE:  graph "issue_2245" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 SELECT drop_graph('graph', true);
 NOTICE:  drop cascades to 2 other objects
 DETAIL:  drop cascades to table graph._ag_label_vertex
diff --git a/regress/expected/cypher.out b/regress/expected/cypher.out
index 31bafc6c..53ea9f0c 100644
--- a/regress/expected/cypher.out
+++ b/regress/expected/cypher.out
@@ -169,6 +169,22 @@ CREATE TABLE my_edges AS
 -- create a table of 4 columns, u, e, v, p. should be 5 rows
 CREATE TABLE my_detailed_paths AS
     (SELECT * FROM cypher('issue_1767', $$ MATCH p=(u)-[e]->(v) RETURN u,e,v,p $$) as (u agtype, e agtype, v agtype, p agtype));
+--
+-- Issue 2256: A segmentation fault occurs when calling the coalesce function
+--             This also occurs with the greatest function too.
+--
+SELECT * FROM coalesce(1, 0);
+ coalesce 
+----------
+        1
+(1 row)
+
+SELECT * FROM greatest(1, 0);
+ greatest 
+----------
+        1
+(1 row)
+
 -- dump out the tables
 SELECT * FROM my_vertices;
                                u                                
diff --git a/regress/expected/cypher_call.out b/regress/expected/cypher_call.out
index 6980abe4..08f97ba4 100644
--- a/regress/expected/cypher_call.out
+++ b/regress/expected/cypher_call.out
@@ -125,6 +125,7 @@ SELECT * FROM cypher('cypher_call', $$CALL sqrt(64) YIELD sqrt WHERE a = 8 RETUR
 ERROR:  could not find rte for a
 LINE 2: ...r('cypher_call', $$CALL sqrt(64) YIELD sqrt WHERE a = 8 RETU...
                                                              ^
+HINT:  variable a does not exist within scope of usage
 /* MATCH CALL RETURN, should fail */
 SELECT * FROM cypher('cypher_call', $$ MATCH (a) CALL sqrt(64) RETURN sqrt $$) as (sqrt agtype);
 ERROR:  Procedure call inside a query does not support naming results implicitly
@@ -171,6 +172,7 @@ SELECT * FROM cypher('cypher_call', $$ MATCH (a) CALL sqrt(64) YIELD sqrt WHERE
 ERROR:  could not find rte for b
 LINE 1: ...all', $$ MATCH (a) CALL sqrt(64) YIELD sqrt WHERE b = 8 RETU...
                                                              ^
+HINT:  variable b does not exist within scope of usage
 /* CALL MATCH YIELD WHERE UPDATE/RETURN */
 SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt WHERE sqrt > 1 CREATE ({n:'c'}) $$) as (a agtype);
  a 
@@ -240,6 +242,58 @@ SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt CALL agtype_sum(
 ERROR:  duplicate variable "sqrt"
 LINE 1: ...LL sqrt(64) YIELD sqrt CALL agtype_sum(2,2) YIELD agtype_sum...
                                                              ^
+-- Fix CALL/YIELD issues
+CREATE OR REPLACE FUNCTION myfunc(i agtype)
+RETURNS agtype
+LANGUAGE plpgsql
+AS $$
+DECLARE
+    result agtype;
+BEGIN
+    RETURN ag_catalog.age_sqrt(i);
+END;
+$$;
+-- should have no errors
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.age_sqrt(64) YIELD age_sqrt RETURN age_sqrt $$) as (sqrt agtype);
+ sqrt 
+------
+ 8.0
+(1 row)
+
+SELECT * FROM cypher('cypher_call', $$ CALL myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+ result 
+--------
+ 5.0
+(1 row)
+
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+ result 
+--------
+ 5.0
+(1 row)
+
+-- should error
+SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype);
+ERROR:  function myfunc does not exist
+LINE 1: SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD m...
+                                             ^
+HINT:  If the function is from an external extension, make sure the extension is installed and the function is in the search path.
+SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+ERROR:  function myfunz does not exist
+LINE 1: SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD...
+                                             ^
+HINT:  If the function is from an external extension, make sure the extension is installed and the function is in the search path.
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype);
+ERROR:  function ag_catalog.myfunc() does not exist
+LINE 1: ...T * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() Y...
+                                                             ^
+HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+ERROR:  function ag_catalog.myfunz(agtype) does not exist
+LINE 1: ...OM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD...
+                                                             ^
+HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+DROP FUNCTION myfunc;
 DROP SCHEMA call_stmt_test CASCADE;
 NOTICE:  drop cascades to function call_stmt_test.add_agtype(agtype,agtype)
 SELECT drop_graph('cypher_call', true);
diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out
index e83ba3b9..ea425e46 100644
--- a/regress/expected/cypher_match.out
+++ b/regress/expected/cypher_match.out
@@ -79,8 +79,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                                                                                                                                                                                                                        a                                                                                                                                                                                                                                                       
 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path
  [{"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex]::path
+ [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -88,8 +88,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                         a                                         
 ----------------------------------------------------------------------------------
- {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
  {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
+ {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -97,8 +97,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                         a                                         
 ----------------------------------------------------------------------------------
- {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
  {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
+ {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -115,8 +115,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -132,10 +132,10 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
 (4 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -143,10 +143,10 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
 (4 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -154,10 +154,10 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
 (4 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -165,8 +165,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -174,8 +174,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                         a                                         
 ----------------------------------------------------------------------------------
- {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
+ {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
 (2 rows)
 
 -- Right Path Test
@@ -250,8 +250,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
 (2 rows)
 
 --Left Path Test
@@ -308,8 +308,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (a agtype);
                                                              a                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
 (2 rows)
 
 --Divergent Path Tests
@@ -348,10 +348,10 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (i agtype);
                                         i                                         
 ----------------------------------------------------------------------------------
- {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
- {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex
+ {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
  {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex
+ {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex
 (4 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -412,8 +412,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (i agtype);
                                                              i                                                             
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge
  {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge
+ {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -537,18 +537,18 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (i agtype, b agtype, c agtype);
  i |     b     |     c     
 ---+-----------+-----------
-   | "end"     | "middle"
- 0 | "end"     | "middle"
- 1 | "end"     | "middle"
    | "middle"  | "end"
  0 | "middle"  | "end"
  1 | "middle"  | "end"
-   | "middle"  | "initial"
- 0 | "middle"  | "initial"
- 1 | "middle"  | "initial"
+   | "end"     | "middle"
+ 0 | "end"     | "middle"
+ 1 | "end"     | "middle"
    | "initial" | "middle"
  0 | "initial" | "middle"
  1 | "initial" | "middle"
+   | "middle"  | "initial"
+ 0 | "middle"  | "initial"
+ 1 | "middle"  | "initial"
 (12 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -558,18 +558,18 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (i agtype,  c agtype);
  i |     c     
 ---+-----------
-   | "middle"
- 0 | "middle"
- 1 | "middle"
    | "end"
  0 | "end"
  1 | "end"
-   | "initial"
- 0 | "initial"
- 1 | "initial"
    | "middle"
  0 | "middle"
  1 | "middle"
+   | "middle"
+ 0 | "middle"
+ 1 | "middle"
+   | "initial"
+ 0 | "initial"
+ 1 | "initial"
 (12 rows)
 
 --
@@ -712,8 +712,8 @@ $$) AS (r0 agtype);
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge
  {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge
- {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge
  {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge
+ {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge
 (6 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -775,8 +775,8 @@ $$) AS (r1 agtype);
  {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge
  {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge
  {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge
- {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge
  {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge
+ {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge
  {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge
 (12 rows)
 
@@ -1055,8 +1055,8 @@ SELECT * FROM cypher('cypher_match',
  {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex  | {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex  | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge | {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex  | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge | {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
- {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2251799813685251, "label": "v3", "properties": {"id": "end"}}::vertex     | {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
+ {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
 (6 rows)
 
 SELECT * FROM cypher('cypher_match',
@@ -1068,8 +1068,8 @@ AS (u agtype, e agtype, v agtype);
  {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex  | {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex  | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge | {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex  | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge | {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
- {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2251799813685251, "label": "v3", "properties": {"id": "end"}}::vertex     | {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
+ {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
 (6 rows)
 
 -- Property Constraint in EXISTS
@@ -1123,8 +1123,8 @@ AS (u agtype, e agtype, v agtype);
  {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex    | {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge   | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex    | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge   | {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex    | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge   | {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
- {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex   | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2251799813685251, "label": "v3", "properties": {"id": "end"}}::vertex       | {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
+ {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex   | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2814749767106561, "label": "loop", "properties": {"id": "initial"}}::vertex | {"id": 3096224743817217, "label": "self", "end_id": 2814749767106561, "start_id": 2814749767106561, "properties": {}}::edge | {"id": 2814749767106561, "label": "loop", "properties": {"id": "initial"}}::vertex
 (7 rows)
 
@@ -1156,8 +1156,8 @@ AS (u agtype, e agtype, v agtype);
  {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex    | {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge   | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex    | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge   | {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex
  {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex    | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge   | {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex
- {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex   | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2251799813685251, "label": "v3", "properties": {"id": "end"}}::vertex       | {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
+ {"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex   | {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge   | {"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex
  {"id": 2814749767106561, "label": "loop", "properties": {"id": "initial"}}::vertex | {"id": 3096224743817217, "label": "self", "end_id": 2814749767106561, "start_id": 2814749767106561, "properties": {}}::edge | {"id": 2814749767106561, "label": "loop", "properties": {"id": "initial"}}::vertex
 (7 rows)
 
@@ -1655,10 +1655,10 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (u agtype, m agtype, l agtype);
      u      |       m       |     l      
 ------------+---------------+------------
- "someone"  | "opt_match_e" | "somebody"
- "somebody" | "opt_match_e" | "someone"
  "anybody"  | "opt_match_e" | "nobody"
  "nobody"   | "opt_match_e" | "anybody"
+ "somebody" | "opt_match_e" | "someone"
+ "someone"  | "opt_match_e" | "somebody"
 (4 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -1670,8 +1670,8 @@ SELECT * FROM cypher('cypher_match', $$
 $$) AS (n agtype, r agtype, p agtype, m agtype, s agtype, q agtype);
      n     |       r       |     p      |     m     |       s       |     q      
 -----------+---------------+------------+-----------+---------------+------------
- "someone" | "opt_match_e" | "somebody" | "anybody" | "opt_match_e" | "nobody"
  "anybody" | "opt_match_e" | "nobody"   | "someone" | "opt_match_e" | "somebody"
+ "someone" | "opt_match_e" | "somebody" | "anybody" | "opt_match_e" | "nobody"
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$
@@ -1684,18 +1684,18 @@ SELECT * FROM cypher('cypher_match', $$
  $$) AS (n agtype, r agtype, p agtype, m agtype, s agtype, q agtype);
      n      |       r       |     p      |     m      |       s       |     q      
 ------------+---------------+------------+------------+---------------+------------
- "someone"  | "opt_match_e" | "somebody" | "anybody"  | "opt_match_e" | "nobody"
- "someone"  |               |            | "somebody" |               | 
- "someone"  |               |            | "nobody"   |               | 
- "somebody" |               |            | "someone"  |               | 
- "somebody" |               |            | "anybody"  |               | 
- "somebody" |               |            | "nobody"   |               | 
  "anybody"  | "opt_match_e" | "nobody"   | "someone"  | "opt_match_e" | "somebody"
- "anybody"  |               |            | "somebody" |               | 
  "anybody"  |               |            | "nobody"   |               | 
- "nobody"   |               |            | "someone"  |               | 
- "nobody"   |               |            | "somebody" |               | 
+ "anybody"  |               |            | "somebody" |               | 
  "nobody"   |               |            | "anybody"  |               | 
+ "nobody"   |               |            | "somebody" |               | 
+ "nobody"   |               |            | "someone"  |               | 
+ "somebody" |               |            | "anybody"  |               | 
+ "somebody" |               |            | "nobody"   |               | 
+ "somebody" |               |            | "someone"  |               | 
+ "someone"  | "opt_match_e" | "somebody" | "anybody"  | "opt_match_e" | "nobody"
+ "someone"  |               |            | "nobody"   |               | 
+ "someone"  |               |            | "somebody" |               | 
 (12 rows)
 
 -- Tests to catch match following optional match logic
@@ -2164,8 +2164,8 @@ SELECT * FROM cypher('cypher_match', $$ MATCH p=(u)-[]-()-[]-(u) RETURN p $$)as
                                                                                                                                                                                                                                                     p                                                                                                                                                                                                                                                     
 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  [{"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex]::path
- [{"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex]::path
  [{"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex]::path
+ [{"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex]::path
  [{"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id": 281474976710668, "label": "", "properties": {"name": "John"}}::vertex]::path
 (4 rows)
 
@@ -2407,22 +2407,22 @@ SELECT * FROM cypher('cypher_match', $$ MATCH (a {name:a.name}) MATCH (a {age:a.
 SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[u {relationship: u.relationship}]->(b) RETURN p $$) as (a agtype);
                                                                                                                                                                      a                                                                                                                                                                     
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
  [{"id": 281474976710661, "label": "", "properties": {"age": 4, "name": "T"}}::vertex, {"id": 4785074604081153, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710661, "properties": {"years": 3, "relationship": "friends"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
+ [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[u {relationship: u.relationship, years: u.years}]->(b) RETURN p $$) as (a agtype);
                                                                                                                                                                      a                                                                                                                                                                     
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
  [{"id": 281474976710661, "label": "", "properties": {"age": 4, "name": "T"}}::vertex, {"id": 4785074604081153, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710661, "properties": {"years": 3, "relationship": "friends"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
+ [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:a.name})-[u {relationship: u.relationship}]->(b {age:b.age}) RETURN p $$) as (a agtype);
                                                                                                                                                                      a                                                                                                                                                                     
 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
  [{"id": 281474976710661, "label": "", "properties": {"age": 4, "name": "T"}}::vertex, {"id": 4785074604081153, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710661, "properties": {"years": 3, "relationship": "friends"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
+ [{"id": 281474976710659, "label": "", "properties": {"age": 3, "name": "orphan"}}::vertex, {"id": 4785074604081154, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710659, "properties": {"years": 4, "relationship": "enemies"}}::edge, {"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex]::path
 (2 rows)
 
 SELECT * FROM cypher('cypher_match', $$ CREATE () WITH * MATCH (x{n0:x.n1}) RETURN 0 $$) as (a agtype);
@@ -3514,19 +3514,17 @@ SELECT count(*) FROM cypher('test_enable_containment', $$ MATCH p=(x:Customer)-[
 (1 row)
 
 SELECT * FROM cypher('test_enable_containment', $$ EXPLAIN (costs off) MATCH (x:Customer)-[:bought ={store: 'Amazon', addr:{city: 'Vancouver', street: 30}}]->(y:Product) RETURN 0 $$) as (a agtype);
-                                                                                                                         QUERY PLAN                                                                                                                          
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- Hash Join
-   Hash Cond: (y.id = _age_default_alias_0.end_id)
-   ->  Seq Scan on "Product" y
-   ->  Hash
-         ->  Hash Join
-               Hash Cond: (x.id = _age_default_alias_0.start_id)
-               ->  Seq Scan on "Customer" x
-               ->  Hash
-                     ->  Seq Scan on bought _age_default_alias_0
-                           Filter: ((agtype_access_operator(VARIADIC ARRAY[properties, '"store"'::agtype]) = '"Amazon"'::agtype) AND (agtype_access_operator(VARIADIC ARRAY[properties, '"addr"'::agtype]) = '{"city": "Vancouver", "street": 30}'::agtype))
-(10 rows)
+                                                                                                                   QUERY PLAN                                                                                                                    
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Nested Loop
+   ->  Nested Loop
+         ->  Seq Scan on bought _age_default_alias_0
+               Filter: ((agtype_access_operator(VARIADIC ARRAY[properties, '"store"'::agtype]) = '"Amazon"'::agtype) AND (agtype_access_operator(VARIADIC ARRAY[properties, '"addr"'::agtype]) = '{"city": "Vancouver", "street": 30}'::agtype))
+         ->  Index Only Scan using "Customer_pkey" on "Customer" x
+               Index Cond: (id = _age_default_alias_0.start_id)
+   ->  Index Only Scan using "Product_pkey" on "Product" y
+         Index Cond: (id = _age_default_alias_0.end_id)
+(8 rows)
 
 SELECT * FROM cypher('test_enable_containment', $$ EXPLAIN (costs off) MATCH (x:Customer ={school: { name: 'XYZ College',program: { major: 'Psyc', degree: 'BSc'} },phone: [ 123456789, 987654321, 456987123 ]}) RETURN 0 $$) as (a agtype);
                                                                                                                                             QUERY PLAN                                                                                                                                             
diff --git a/regress/expected/cypher_merge.out b/regress/expected/cypher_merge.out
index 238a4c47..56a23f51 100644
--- a/regress/expected/cypher_merge.out
+++ b/regress/expected/cypher_merge.out
@@ -655,8 +655,8 @@ $$) AS (name agtype, bornIn agtype, city agtype);
        name        |    bornin    |                                          city                                           
 -------------------+--------------+-----------------------------------------------------------------------------------------
  "Rob Reiner"      | "New York"   | {"id": 1970324836974593, "label": "City", "properties": {"name": "New York"}}::vertex
- "Martin Sheen"    | "Ohio"       | {"id": 1970324836974595, "label": "City", "properties": {"name": "Ohio"}}::vertex
  "Michael Douglas" | "New Jersey" | {"id": 1970324836974594, "label": "City", "properties": {"name": "New Jersey"}}::vertex
+ "Martin Sheen"    | "Ohio"       | {"id": 1970324836974595, "label": "City", "properties": {"name": "Ohio"}}::vertex
 (3 rows)
 
 --validate
diff --git a/regress/expected/cypher_subquery.out b/regress/expected/cypher_subquery.out
index ff5672bc..456b3a2c 100644
--- a/regress/expected/cypher_subquery.out
+++ b/regress/expected/cypher_subquery.out
@@ -135,6 +135,7 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 ERROR:  could not find rte for c
 LINE 5:               RETURN c
                              ^
+HINT:  variable c does not exist within scope of usage
 --union, no returns
 SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 									WHERE EXISTS {
@@ -341,6 +342,7 @@ SELECT * FROM cypher('subquery', $$ RETURN 1,
 ERROR:  could not find rte for a
 LINE 4:                RETURN a
                               ^
+HINT:  variable a does not exist within scope of usage
 --- COUNT
 --count pattern subquery in where
 SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -540,6 +542,7 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 ERROR:  could not find rte for b
 LINE 2:          RETURN a.name, COUNT{MATCH (a) RETURN b} $$)
                                                        ^
+HINT:  variable b does not exist within scope of usage
 --incorrect nested variable reference
 SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 									RETURN a.name, COUNT{MATCH (a)
@@ -549,6 +552,7 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 ERROR:  could not find rte for b
 LINE 4:                RETURN b} $$)
                               ^
+HINT:  variable b does not exist within scope of usage
 --count nested with exists
 SELECT * FROM cypher('subquery', $$ MATCH (a:person)
 									RETURN a.name,
@@ -668,8 +672,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)-[]->(b)
 									RETURN a $$) AS (result agtype);
                                              result                                              
 -------------------------------------------------------------------------------------------------
- {"id": 844424930131975, "label": "person", "properties": {"age": 6, "name": "Calvin"}}::vertex
  {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name": "Charlie"}}::vertex
+ {"id": 844424930131975, "label": "person", "properties": {"age": 6, "name": "Calvin"}}::vertex
  {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name": "Charlie"}}::vertex
 (3 rows)
 
diff --git a/regress/expected/cypher_union.out b/regress/expected/cypher_union.out
index 063354dd..14fa56e6 100644
--- a/regress/expected/cypher_union.out
+++ b/regress/expected/cypher_union.out
@@ -141,6 +141,7 @@ SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (m) RE
 ERROR:  could not find rte for n
 LINE 2: ..., $$MATCH (n) RETURN n UNION ALL MATCH (m) RETURN n$$) AS (r...
                                                              ^
+HINT:  variable n does not exist within scope of usage
 /*
  *UNION and UNION ALL, type casting
  */
diff --git a/regress/expected/cypher_vle.out b/regress/expected/cypher_vle.out
index 9cbb3420..57f930d9 100644
--- a/regress/expected/cypher_vle.out
+++ b/regress/expected/cypher_vle.out
@@ -508,37 +508,37 @@ SELECT * FROM cypher('cypher_vle', $$MATCH p=(u)-[e*0..0]->(v) RETURN id(u), p,
 SELECT * FROM cypher('cypher_vle', $$MATCH p=()-[*0..0]->()-[]->() RETURN p $$) AS (p agtype);
                                                                                                                                                                                                      p                                                                                                                                                                                                     
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 2251799813685249, "label": "alternate_edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "alternate edge", "number": 1, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395906, "label": "bypass_edge", "end_id": 844424930131969, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 2, "packages": [1, 3, 5, 7], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 844424930131969, "label": "begin", "properties": {}}::vertex]::path
  [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 1125899906842628, "label": "edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "main edge", "number": 1, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
- [{"id": 1407374883553281, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842627, "label": "edge", "end_id": 1407374883553282, "start_id": 1407374883553281, "properties": {"name": "main edge", "number": 2, "packages": [2, 4, 6], "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553281, "label": "middle", "properties": {}}::vertex, {"id": 1970324836974593, "label": "self_loop", "end_id": 1407374883553281, "start_id": 1407374883553281, "properties": {"name": "self loop", "number": 1, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 2251799813685249, "label": "alternate_edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "alternate edge", "number": 1, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685253, "label": "alternate_edge", "end_id": 1407374883553282, "start_id": 1407374883553283, "properties": {"name": "backup edge", "number": 2, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1407374883553281, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842627, "label": "edge", "end_id": 1407374883553282, "start_id": 1407374883553281, "properties": {"name": "main edge", "number": 2, "packages": [2, 4, 6], "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842626, "label": "edge", "end_id": 1407374883553283, "start_id": 1407374883553282, "properties": {"name": "main edge", "number": 3, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685250, "label": "alternate_edge", "end_id": 1407374883553283, "start_id": 1407374883553282, "properties": {"name": "alternate edge", "number": 2, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
- [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395905, "label": "bypass_edge", "end_id": 1688849860263937, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
- [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395906, "label": "bypass_edge", "end_id": 844424930131969, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 2, "packages": [1, 3, 5, 7], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 844424930131969, "label": "begin", "properties": {}}::vertex]::path
- [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842625, "label": "edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "main edge", "number": 4, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
- [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685253, "label": "alternate_edge", "end_id": 1407374883553282, "start_id": 1407374883553283, "properties": {"name": "backup edge", "number": 2, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
- [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685251, "label": "alternate_edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "alternate edge", "number": 3, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
  [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 2251799813685252, "label": "alternate_edge", "end_id": 1407374883553283, "start_id": 1688849860263937, "properties": {"name": "backup edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685251, "label": "alternate_edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "alternate edge", "number": 3, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
+ [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395905, "label": "bypass_edge", "end_id": 1688849860263937, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
  [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 1970324836974594, "label": "self_loop", "end_id": 1688849860263937, "start_id": 1688849860263937, "properties": {"name": "self loop", "number": 2, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
+ [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842625, "label": "edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "main edge", "number": 4, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
 (13 rows)
 
 SELECT * FROM cypher('cypher_vle', $$MATCH p=()-[]->()-[*0..0]->() RETURN p $$) AS (p agtype);
                                                                                                                                                                                                      p                                                                                                                                                                                                     
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395906, "label": "bypass_edge", "end_id": 844424930131969, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 2, "packages": [1, 3, 5, 7], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 844424930131969, "label": "begin", "properties": {}}::vertex]::path
- [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 2251799813685249, "label": "alternate_edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "alternate edge", "number": 1, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 1125899906842628, "label": "edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "main edge", "number": 1, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 844424930131969, "label": "begin", "properties": {}}::vertex, {"id": 2251799813685249, "label": "alternate_edge", "end_id": 1407374883553281, "start_id": 844424930131969, "properties": {"name": "alternate edge", "number": 1, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553281, "label": "middle", "properties": {}}::vertex, {"id": 1970324836974593, "label": "self_loop", "end_id": 1407374883553281, "start_id": 1407374883553281, "properties": {"name": "self loop", "number": 1, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553281, "label": "middle", "properties": {}}::vertex]::path
- [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685253, "label": "alternate_edge", "end_id": 1407374883553282, "start_id": 1407374883553283, "properties": {"name": "backup edge", "number": 2, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553281, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842627, "label": "edge", "end_id": 1407374883553282, "start_id": 1407374883553281, "properties": {"name": "main edge", "number": 2, "packages": [2, 4, 6], "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
- [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 2251799813685252, "label": "alternate_edge", "end_id": 1407374883553283, "start_id": 1688849860263937, "properties": {"name": "backup edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842626, "label": "edge", "end_id": 1407374883553283, "start_id": 1407374883553282, "properties": {"name": "main edge", "number": 3, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685250, "label": "alternate_edge", "end_id": 1407374883553283, "start_id": 1407374883553282, "properties": {"name": "alternate edge", "number": 2, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
  [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395905, "label": "bypass_edge", "end_id": 1688849860263937, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
- [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 1970324836974594, "label": "self_loop", "end_id": 1688849860263937, "start_id": 1688849860263937, "properties": {"name": "self loop", "number": 2, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
+ [{"id": 1407374883553282, "label": "middle", "properties": {}}::vertex, {"id": 2533274790395906, "label": "bypass_edge", "end_id": 844424930131969, "start_id": 1407374883553282, "properties": {"name": "bypass edge", "number": 2, "packages": [1, 3, 5, 7], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 844424930131969, "label": "begin", "properties": {}}::vertex]::path
  [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 1125899906842625, "label": "edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "main edge", "number": 4, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
  [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685251, "label": "alternate_edge", "end_id": 1688849860263937, "start_id": 1407374883553283, "properties": {"name": "alternate edge", "number": 3, "packages": [2, 4, 6], "dangerous": {"type": "poisons", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
+ [{"id": 1407374883553283, "label": "middle", "properties": {}}::vertex, {"id": 2251799813685253, "label": "alternate_edge", "end_id": 1407374883553282, "start_id": 1407374883553283, "properties": {"name": "backup edge", "number": 2, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553282, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 2251799813685252, "label": "alternate_edge", "end_id": 1407374883553283, "start_id": 1688849860263937, "properties": {"name": "backup edge", "number": 1, "packages": [1, 3, 5, 7]}}::edge, {"id": 1407374883553283, "label": "middle", "properties": {}}::vertex]::path
+ [{"id": 1688849860263937, "label": "end", "properties": {}}::vertex, {"id": 1970324836974594, "label": "self_loop", "end_id": 1688849860263937, "start_id": 1688849860263937, "properties": {"name": "self loop", "number": 2, "dangerous": {"type": "all", "level": "all"}}}::edge, {"id": 1688849860263937, "label": "end", "properties": {}}::vertex]::path
 (13 rows)
 
 --
diff --git a/regress/expected/cypher_with.out b/regress/expected/cypher_with.out
index e5f82aa2..99ea320a 100644
--- a/regress/expected/cypher_with.out
+++ b/regress/expected/cypher_with.out
@@ -267,6 +267,7 @@ $$) AS (a agtype, b agtype);
 ERROR:  could not find rte for b
 LINE 4:     RETURN m,b
                      ^
+HINT:  variable b does not exist within scope of usage
 SELECT * FROM cypher('cypher_with', $$
     MATCH (m)-[]->(b)
     WITH m AS start_node,b AS end_node
@@ -278,6 +279,7 @@ $$) AS (id agtype, node agtype);
 ERROR:  could not find rte for end_node
 LINE 7:     RETURN id(start_node),end_node.name
                                   ^
+HINT:  variable end_node does not exist within scope of usage
 -- Clean up
 SELECT drop_graph('cypher_with', true);
 NOTICE:  drop cascades to 4 other objects
@@ -320,6 +322,7 @@ $$) AS (n agtype, d agtype);
 ERROR:  could not find rte for d
 LINE 8:     RETURN c,d
                      ^
+HINT:  variable d does not exist within scope of usage
 -- Issue 396 (should error out)
 SELECT * FROM cypher('graph',$$
     CREATE (v),(u),(w),
@@ -338,6 +341,7 @@ $$) as (a agtype,b agtype);
 ERROR:  could not find rte for v
 LINE 4:     RETURN v,path_length
                    ^
+HINT:  variable v does not exist within scope of usage
 -- Clean up
 SELECT drop_graph('graph', true);
 NOTICE:  drop cascades to 6 other objects
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index 513ea142..926a958d 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -2644,10 +2644,10 @@ SELECT * FROM cypher('expr', $$ MATCH (v) RETURN v $$) AS (expression agtype);
 SELECT * FROM cypher('expr', $$ MATCH ()-[e]-() RETURN e $$) AS (expression agtype);
                                                         expression                                                         
 ---------------------------------------------------------------------------------------------------------------------------
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
- {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
 (4 rows)
 
 -- id()
@@ -2656,10 +2656,10 @@ SELECT * FROM cypher('expr', $$
 $$) AS (id agtype);
         id        
 ------------------
- 1407374883553281
- 1407374883553281
  1407374883553282
  1407374883553282
+ 1407374883553281
+ 1407374883553281
 (4 rows)
 
 SELECT * FROM cypher('expr', $$
@@ -2698,10 +2698,10 @@ SELECT * FROM cypher('expr', $$
 $$) AS (start_id agtype);
      start_id     
 ------------------
- 1125899906842626
- 1125899906842626
  1125899906842625
  1125899906842625
+ 1125899906842626
+ 1125899906842626
 (4 rows)
 
 -- should return null
@@ -2731,10 +2731,10 @@ SELECT * FROM cypher('expr', $$
 $$) AS (end_id agtype);
       end_id      
 ------------------
- 1125899906842627
- 1125899906842627
  1125899906842626
  1125899906842626
+ 1125899906842627
+ 1125899906842627
 (4 rows)
 
 -- should return null
@@ -2764,10 +2764,10 @@ SELECT * FROM cypher('expr', $$
 $$) AS (id agtype, start_id agtype, startNode agtype);
         id        |     start_id     |                                    startnode                                     
 ------------------+------------------+----------------------------------------------------------------------------------
- 1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
- 1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
  1407374883553282 | 1125899906842625 | {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
  1407374883553282 | 1125899906842625 | {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
+ 1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
+ 1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
 (4 rows)
 
 -- should return null
@@ -2797,10 +2797,10 @@ SELECT * FROM cypher('expr', $$
 $$) AS (id agtype, end_id agtype, endNode agtype);
         id        |      end_id      |                                     endnode                                     
 ------------------+------------------+---------------------------------------------------------------------------------
- 1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
- 1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  1407374883553282 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
  1407374883553282 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
+ 1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
+ 1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
 (4 rows)
 
 -- should return null
@@ -3370,6 +3370,7 @@ $$) AS (toBooleanList agtype);
 ERROR:  could not find rte for fail
 LINE 2:     RETURN toBooleanList(fail)
                                  ^
+HINT:  variable fail does not exist within scope of usage
 SELECT * FROM cypher('expr', $$
     RETURN toBooleanList("fail")
 $$) AS (toBooleanList agtype);
@@ -3513,6 +3514,7 @@ $$) AS (toFloatList agtype);
 ERROR:  could not find rte for failed
 LINE 2:     RETURN toFloatList([failed])
                                 ^
+HINT:  variable failed does not exist within scope of usage
 SELECT * FROM cypher('expr', $$
     RETURN toFloatList("failed")
 $$) AS (toFloatList agtype);
@@ -3892,12 +3894,14 @@ $$) AS (toStringList agtype);
 ERROR:  could not find rte for b
 LINE 2:     RETURN toStringList([['a', b]]) 
                                        ^
+HINT:  variable b does not exist within scope of usage
 SELECT * FROM cypher('expr', $$ 
     RETURN toStringList([test]) 
 $$) AS (toStringList agtype);
 ERROR:  could not find rte for test
 LINE 2:     RETURN toStringList([test]) 
                                  ^
+HINT:  variable test does not exist within scope of usage
 --
 -- reverse(string)
 --
@@ -6945,6 +6949,94 @@ $$) AS (i agtype);
  {"key": "value"}
 (9 rows)
 
+--
+-- Test ORDER BY with AS
+--
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'John', age: 38}) $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Jill', age: 23}) $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Ion', age: 34}) $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Mary', age: 57}) $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Jerry', age: 34}) $$) AS (result agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name
+$$) AS (name agtype, age agtype);
+  name   | age 
+---------+-----
+ "Ion"   | 34
+ "Jerry" | 34
+ "Jill"  | 23
+ "John"  | 38
+ "Mary"  | 57
+(5 rows)
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name ASC
+$$) AS (name agtype, age agtype);
+  name   | age 
+---------+-----
+ "Ion"   | 34
+ "Jerry" | 34
+ "Jill"  | 23
+ "John"  | 38
+ "Mary"  | 57
+(5 rows)
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name DESC
+$$) AS (name agtype, age agtype);
+  name   | age 
+---------+-----
+ "Mary"  | 57
+ "John"  | 38
+ "Jill"  | 23
+ "Jerry" | 34
+ "Ion"   | 34
+(5 rows)
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY age ASC, name DESCENDING 
+$$) AS (name agtype, age agtype);
+  name   | age 
+---------+-----
+ "Jill"  | 23
+ "Jerry" | 34
+ "Ion"   | 34
+ "John"  | 38
+ "Mary"  | 57
+(5 rows)
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY age DESC, name ASCENDING
+$$) AS (name agtype, age agtype);
+  name   | age 
+---------+-----
+ "Mary"  | 57
+ "John"  | 38
+ "Ion"   | 34
+ "Jerry" | 34
+ "Jill"  | 23
+(5 rows)
+
 --CASE
 SELECT create_graph('case_statement');
 NOTICE:  graph "case_statement" has been created
@@ -7496,10 +7588,10 @@ SELECT * FROM cypher('opt_forms', $$MATCH (u) RETURN *$$) AS (result agtype);
 SELECT * FROM cypher('opt_forms', $$MATCH (u)--(v) RETURN u.i, v.i$$) AS (u agtype, v agtype);
  u | v 
 ---+---
- 2 | 3
- 3 | 2
  1 | 2
  2 | 1
+ 2 | 3
+ 3 | 2
 (4 rows)
 
 SELECT * FROM cypher('opt_forms', $$MATCH (u)-->(v) RETURN u.i, v.i$$) AS (u agtype, v agtype);
@@ -7686,12 +7778,12 @@ SELECT * FROM cypher('keys', $$MATCH (v) RETURN keys(v)$$) AS (vertex_keys agtyp
 SELECT * FROM cypher('keys', $$MATCH ()-[e]-() RETURN keys(e)$$) AS (edge_keys agtype);
  edge_keys 
 -----------
- []
- []
  ["song"]
  ["song"]
+ []
  ["song"]
  ["song"]
+ []
 (6 rows)
 
 SELECT * FROM cypher('keys', $$RETURN keys({a:1,b:'two',c:[1,2,3]})$$) AS (keys agtype);
@@ -7923,6 +8015,7 @@ SELECT * FROM cypher('list', $$ RETURN tail(abc) $$) AS (tail agtype);
 ERROR:  could not find rte for abc
 LINE 1: SELECT * FROM cypher('list', $$ RETURN tail(abc) $$) AS (tai...
                                                     ^
+HINT:  variable abc does not exist within scope of usage
 SELECT * FROM cypher('list', $$ RETURN tail() $$) AS (tail agtype);
 ERROR:  function ag_catalog.age_tail() does not exist
 LINE 1: SELECT * FROM cypher('list', $$ RETURN tail() $$) AS (tail a...
@@ -9011,9 +9104,70 @@ SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]'));
       -505290721
 (1 row)
 
+--
+-- Issue 2263: AGE returns incorrect error message for EXISTS subquery outer variable reference
+--
+--       NOTE: There isn't really anything incorrect about the message. However,
+--             it could be more clear.
+--
+SELECT * FROM create_graph('issue_2263');
+NOTICE:  graph "issue_2263" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+SELECT * FROM cypher('issue_2263', $$
+    CREATE a=()-[:T]->(), p=({k:exists{return a}})-[:T]->()
+    RETURN 1
+$$) AS (one agtype);
+ERROR:  could not find rte for a
+LINE 2:     CREATE a=()-[:T]->(), p=({k:exists{return a}})-[:T]->()
+                                                      ^
+HINT:  variable a does not exist within scope of usage
+SELECT * FROM cypher('issue_2263', $$
+    CREATE p0=(n0), (n1{k:EXISTS{WITH p0}})
+    RETURN 1
+$$) AS (one agtype);
+ERROR:  could not find rte for p0
+LINE 2:     CREATE p0=(n0), (n1{k:EXISTS{WITH p0}})
+                                              ^
+HINT:  variable p0 does not exist within scope of usage
+SELECT * FROM cypher('issue_2263', $$
+    CREATE ()-[r4 :T6]->(), ({k2:COUNT{WITH r4.k AS a3 UNWIND [] AS a4 WITH DISTINCT NULL AS a5}})
+    RETURN 1
+$$) AS (one agtype);
+ERROR:  could not find rte for r4
+LINE 2:     CREATE ()-[r4 :T6]->(), ({k2:COUNT{WITH r4.k AS a3 UNWIN...
+                                                    ^
+HINT:  variable r4 does not exist within scope of usage
+SELECT * FROM cypher('issue_2263', $$
+    CREATE (x), ({a1:EXISTS { RETURN COUNT(0) AS a2, keys(x) AS a4 }})
+$$) AS (out agtype);
+ERROR:  could not find rte for x
+LINE 2: ...TE (x), ({a1:EXISTS { RETURN COUNT(0) AS a2, keys(x) AS a4 }...
+                                                             ^
+HINT:  variable x does not exist within scope of usage
+SELECT * FROM cypher('issue_2263', $$
+    CREATE x = (), ({ a0:COUNT { MATCH () WHERE CASE WHEN true THEN (x IS NULL) END RETURN 0 } })
+$$) AS (out agtype);
+ERROR:  could not find rte for x
+LINE 2: ...({ a0:COUNT { MATCH () WHERE CASE WHEN true THEN (x IS NULL)...
+                                                             ^
+HINT:  variable x does not exist within scope of usage
 --
 -- Cleanup
 --
+SELECT * FROM drop_graph('issue_2263', true);
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to table issue_2263._ag_label_vertex
+drop cascades to table issue_2263._ag_label_edge
+NOTICE:  graph "issue_2263" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 SELECT * FROM drop_graph('issue_1988', true);
 NOTICE:  drop cascades to 4 other objects
 DETAIL:  drop cascades to table issue_1988._ag_label_vertex
diff --git a/regress/expected/graph_generation.out b/regress/expected/graph_generation.out
index 235052a0..ca511eaf 100644
--- a/regress/expected/graph_generation.out
+++ b/regress/expected/graph_generation.out
@@ -43,15 +43,15 @@ SELECT * FROM cypher('gp1', $$MATCH (a)-[e]->(b) RETURN e$$) as (n agtype);
                                                              n                                                              
 ----------------------------------------------------------------------------------------------------------------------------
  {"id": 1125899906842625, "label": "edges", "end_id": 844424930131970, "start_id": 844424930131969, "properties": {}}::edge
- {"id": 1125899906842629, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842626, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131969, "properties": {}}::edge
- {"id": 1125899906842630, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131970, "properties": {}}::edge
+ {"id": 1125899906842629, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842627, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131969, "properties": {}}::edge
+ {"id": 1125899906842630, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842632, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131971, "properties": {}}::edge
+ {"id": 1125899906842628, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131969, "properties": {}}::edge
  {"id": 1125899906842631, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131970, "properties": {}}::edge
- {"id": 1125899906842634, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131972, "properties": {}}::edge
  {"id": 1125899906842633, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131971, "properties": {}}::edge
- {"id": 1125899906842628, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131969, "properties": {}}::edge
+ {"id": 1125899906842634, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131972, "properties": {}}::edge
 (10 rows)
 
 SELECT * FROM create_complete_graph('gp1',5,'edges','vertices');
@@ -140,25 +140,25 @@ SELECT * FROM cypher('gp1', $$MATCH (a)-[e]->(b) RETURN e$$) as (n agtype);
                                                              n                                                              
 ----------------------------------------------------------------------------------------------------------------------------
  {"id": 1125899906842625, "label": "edges", "end_id": 844424930131970, "start_id": 844424930131969, "properties": {}}::edge
- {"id": 1125899906842629, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842626, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131969, "properties": {}}::edge
+ {"id": 1125899906842629, "label": "edges", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842627, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131969, "properties": {}}::edge
- {"id": 1125899906842632, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131971, "properties": {}}::edge
  {"id": 1125899906842630, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131970, "properties": {}}::edge
- {"id": 1125899906842634, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131972, "properties": {}}::edge
+ {"id": 1125899906842632, "label": "edges", "end_id": 844424930131972, "start_id": 844424930131971, "properties": {}}::edge
  {"id": 1125899906842628, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131969, "properties": {}}::edge
  {"id": 1125899906842631, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131970, "properties": {}}::edge
  {"id": 1125899906842633, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131971, "properties": {}}::edge
+ {"id": 1125899906842634, "label": "edges", "end_id": 844424930131973, "start_id": 844424930131972, "properties": {}}::edge
  {"id": 1125899906842635, "label": "edges", "end_id": 844424930131975, "start_id": 844424930131974, "properties": {}}::edge
- {"id": 1125899906842639, "label": "edges", "end_id": 844424930131976, "start_id": 844424930131975, "properties": {}}::edge
  {"id": 1125899906842636, "label": "edges", "end_id": 844424930131976, "start_id": 844424930131974, "properties": {}}::edge
+ {"id": 1125899906842639, "label": "edges", "end_id": 844424930131976, "start_id": 844424930131975, "properties": {}}::edge
  {"id": 1125899906842637, "label": "edges", "end_id": 844424930131977, "start_id": 844424930131974, "properties": {}}::edge
- {"id": 1125899906842642, "label": "edges", "end_id": 844424930131977, "start_id": 844424930131976, "properties": {}}::edge
  {"id": 1125899906842640, "label": "edges", "end_id": 844424930131977, "start_id": 844424930131975, "properties": {}}::edge
- {"id": 1125899906842644, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131977, "properties": {}}::edge
+ {"id": 1125899906842642, "label": "edges", "end_id": 844424930131977, "start_id": 844424930131976, "properties": {}}::edge
  {"id": 1125899906842638, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131974, "properties": {}}::edge
  {"id": 1125899906842641, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131975, "properties": {}}::edge
  {"id": 1125899906842643, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131976, "properties": {}}::edge
+ {"id": 1125899906842644, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131977, "properties": {}}::edge
  {"id": 1125899906842645, "label": "edges", "end_id": 844424930131978, "start_id": 844424930131969, "properties": {}}::edge
 (21 rows)
 
diff --git a/regress/expected/index.out b/regress/expected/index.out
index f911900a..3ed7b1c3 100644
--- a/regress/expected/index.out
+++ b/regress/expected/index.out
@@ -264,18 +264,22 @@ $$) as (n agtype);
 ---
 (0 rows)
 
-ALTER TABLE cypher_index."Country" ADD PRIMARY KEY (id);
-CREATE UNIQUE INDEX CONCURRENTLY cntry_id_idx ON cypher_index."Country" (id);
-ALTER TABLE cypher_index."Country"  CLUSTER ON cntry_id_idx;
-ALTER TABLE cypher_index."City" ADD PRIMARY KEY (id);
-CREATE UNIQUE INDEX city_id_idx ON cypher_index."City" (id);
-ALTER TABLE cypher_index."City" CLUSTER ON city_id_idx;
-ALTER TABLE cypher_index.has_city
-ADD CONSTRAINT has_city_end_fk FOREIGN KEY (end_id)
-REFERENCES cypher_index."Country"(id) MATCH FULL;
-CREATE INDEX load_has_city_eid_idx ON cypher_index.has_city (end_id);
-CREATE INDEX load_has_city_sid_idx ON cypher_index.has_city (start_id);
-ALTER TABLE cypher_index."has_city" CLUSTER ON load_has_city_eid_idx;
+-- Verify that the incices are created on id columns
+SELECT indexname, indexdef FROM pg_indexes WHERE schemaname= 'cypher_index';
+          indexname          |                                            indexdef                                            
+-----------------------------+------------------------------------------------------------------------------------------------
+ _ag_label_edge_pkey         | CREATE UNIQUE INDEX _ag_label_edge_pkey ON cypher_index._ag_label_edge USING btree (id)
+ _ag_label_edge_start_id_idx | CREATE INDEX _ag_label_edge_start_id_idx ON cypher_index._ag_label_edge USING btree (start_id)
+ _ag_label_edge_end_id_idx   | CREATE INDEX _ag_label_edge_end_id_idx ON cypher_index._ag_label_edge USING btree (end_id)
+ _ag_label_vertex_pkey       | CREATE UNIQUE INDEX _ag_label_vertex_pkey ON cypher_index._ag_label_vertex USING btree (id)
+ idx_pkey                    | CREATE UNIQUE INDEX idx_pkey ON cypher_index.idx USING btree (id)
+ cypher_index_idx_props_uq   | CREATE UNIQUE INDEX cypher_index_idx_props_uq ON cypher_index.idx USING btree (properties)
+ Country_pkey                | CREATE UNIQUE INDEX "Country_pkey" ON cypher_index."Country" USING btree (id)
+ has_city_start_id_idx       | CREATE INDEX has_city_start_id_idx ON cypher_index.has_city USING btree (start_id)
+ has_city_end_id_idx         | CREATE INDEX has_city_end_id_idx ON cypher_index.has_city USING btree (end_id)
+ City_pkey                   | CREATE UNIQUE INDEX "City_pkey" ON cypher_index."City" USING btree (id)
+(10 rows)
+
 SET enable_mergejoin = ON;
 SET enable_hashjoin = OFF;
 SET enable_nestloop = OFF;
@@ -288,6 +292,29 @@ $$) as (n agtype);
     10
 (1 row)
 
+SELECT COUNT(*) FROM cypher('cypher_index', $$
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
+    RETURN e
+$$) as (n agtype);
+                                                QUERY PLAN                                                
+----------------------------------------------------------------------------------------------------------
+ Aggregate
+   ->  Merge Join
+         Merge Cond: (_age_default_alias_0.id = e.start_id)
+         ->  Merge Append
+               Sort Key: _age_default_alias_0.id
+               ->  Index Only Scan using _ag_label_vertex_pkey on _ag_label_vertex _age_default_alias_0_1
+               ->  Index Only Scan using idx_pkey on idx _age_default_alias_0_2
+               ->  Index Only Scan using "Country_pkey" on "Country" _age_default_alias_0_3
+               ->  Index Only Scan using "City_pkey" on "City" _age_default_alias_0_4
+         ->  Sort
+               Sort Key: e.start_id
+               ->  Merge Join
+                     Merge Cond: (a.id = e.end_id)
+                     ->  Index Only Scan using "Country_pkey" on "Country" a
+                     ->  Index Scan using has_city_end_id_idx on has_city e
+(15 rows)
+
 SET enable_mergejoin = OFF;
 SET enable_hashjoin = ON;
 SET enable_nestloop = OFF;
@@ -300,17 +327,53 @@ $$) as (n agtype);
     10
 (1 row)
 
+SELECT COUNT(*) FROM cypher('cypher_index', $$
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
+    RETURN e
+$$) as (n agtype);
+                                                QUERY PLAN                                                
+----------------------------------------------------------------------------------------------------------
+ Aggregate
+   ->  Hash Join
+         Hash Cond: (_age_default_alias_0.id = e.start_id)
+         ->  Append
+               ->  Index Only Scan using _ag_label_vertex_pkey on _ag_label_vertex _age_default_alias_0_1
+               ->  Index Only Scan using idx_pkey on idx _age_default_alias_0_2
+               ->  Index Only Scan using "Country_pkey" on "Country" _age_default_alias_0_3
+               ->  Index Only Scan using "City_pkey" on "City" _age_default_alias_0_4
+         ->  Hash
+               ->  Hash Join
+                     Hash Cond: (e.end_id = a.id)
+                     ->  Index Scan using has_city_end_id_idx on has_city e
+                     ->  Hash
+                           ->  Index Only Scan using "Country_pkey" on "Country" a
+(14 rows)
+
 SET enable_mergejoin = OFF;
 SET enable_hashjoin = OFF;
 SET enable_nestloop = ON;
 SELECT COUNT(*) FROM cypher('cypher_index', $$
-    MATCH (a:Country)<-[e:has_city]-()
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
     RETURN e
 $$) as (n agtype);
- count 
--------
-    10
-(1 row)
+                                                QUERY PLAN                                                
+----------------------------------------------------------------------------------------------------------
+ Aggregate
+   ->  Nested Loop
+         ->  Nested Loop
+               ->  Index Scan using has_city_start_id_idx on has_city e
+               ->  Index Only Scan using "Country_pkey" on "Country" a
+                     Index Cond: (id = e.end_id)
+         ->  Append
+               ->  Index Only Scan using _ag_label_vertex_pkey on _ag_label_vertex _age_default_alias_0_1
+                     Index Cond: (id = e.start_id)
+               ->  Index Only Scan using idx_pkey on idx _age_default_alias_0_2
+                     Index Cond: (id = e.start_id)
+               ->  Index Only Scan using "Country_pkey" on "Country" _age_default_alias_0_3
+                     Index Cond: (id = e.start_id)
+               ->  Index Only Scan using "City_pkey" on "City" _age_default_alias_0_4
+                     Index Cond: (id = e.start_id)
+(15 rows)
 
 SET enable_mergejoin = ON;
 SET enable_hashjoin = ON;
diff --git a/regress/expected/list_comprehension.out b/regress/expected/list_comprehension.out
index 07f77770..5a375642 100644
--- a/regress/expected/list_comprehension.out
+++ b/regress/expected/list_comprehension.out
@@ -569,10 +569,12 @@ SELECT * FROM cypher('list_comprehension', $$ RETURN [i IN range(0, 10, 2)],i $$
 ERROR:  could not find rte for i
 LINE 1: ..._comprehension', $$ RETURN [i IN range(0, 10, 2)],i $$) AS (...
                                                              ^
+HINT:  variable i does not exist within scope of usage
 SELECT * FROM cypher('list_comprehension', $$ RETURN [i IN range(0, 10, 2) WHERE i>5 | i^2], i $$) AS (result agtype, i agtype);
 ERROR:  could not find rte for i
 LINE 1: ...$$ RETURN [i IN range(0, 10, 2) WHERE i>5 | i^2], i $$) AS (...
                                                              ^
+HINT:  variable i does not exist within scope of usage
 -- Invalid list comprehension
 SELECT * FROM cypher('list_comprehension', $$ RETURN [1 IN range(0, 10, 2) WHERE 2>5] $$) AS (result agtype);
 ERROR:  Syntax error at or near IN
diff --git a/regress/expected/map_projection.out b/regress/expected/map_projection.out
index dcb7f0e7..f0c45c55 100644
--- a/regress/expected/map_projection.out
+++ b/regress/expected/map_projection.out
@@ -152,7 +152,7 @@ $$
 $$) as (a agtype);
                                                                                                       a                                                                                                       
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- [{"name": "Christian Bale", "movies": [{"title": "The Prestige"}, {"title": "The Dark Knight"}]}, {"name": "Tom Hanks", "movies": [{"title": "Forrest Gump"}, {"title": "Finch"}, {"title": "The Circle"}]}]
+ [{"name": "Tom Hanks", "movies": [{"title": "Forrest Gump"}, {"title": "Finch"}, {"title": "The Circle"}]}, {"name": "Christian Bale", "movies": [{"title": "The Prestige"}, {"title": "The Dark Knight"}]}]
 (1 row)
 
 -- drop
diff --git a/regress/expected/scan.out b/regress/expected/scan.out
index d8105a05..46d5676d 100644
--- a/regress/expected/scan.out
+++ b/regress/expected/scan.out
@@ -437,36 +437,42 @@ $$) AS t(id text);
 ERROR:  could not find rte for _$09A_z
 LINE 2: RETURN _$09A_z
                ^
+HINT:  variable _$09A_z does not exist within scope of usage
 SELECT * FROM cypher('scan', $$
 RETURN A
 $$) AS t(id text);
 ERROR:  could not find rte for A
 LINE 2: RETURN A
                ^
+HINT:  variable A does not exist within scope of usage
 SELECT * FROM cypher('scan', $$
 RETURN z
 $$) AS t(id text);
 ERROR:  could not find rte for z
 LINE 2: RETURN z
                ^
+HINT:  variable z does not exist within scope of usage
 SELECT * FROM cypher('scan', $$
 RETURN `$`
 $$) AS t(id text);
 ERROR:  could not find rte for $
 LINE 2: RETURN `$`
                ^
+HINT:  variable $ does not exist within scope of usage
 SELECT * FROM cypher('scan', $$
 RETURN `0`
 $$) AS t(id text);
 ERROR:  could not find rte for 0
 LINE 2: RETURN `0`
                ^
+HINT:  variable 0 does not exist within scope of usage
 SELECT * FROM cypher('scan', $$
 RETURN ````
 $$) AS t(id text);
 ERROR:  could not find rte for `
 LINE 2: RETURN ````
                ^
+HINT:  variable ` does not exist within scope of usage
 -- zero-length quoted identifier
 SELECT * FROM cypher('scan', $$
 RETURN ``
diff --git a/regress/sql/age_load.sql b/regress/sql/age_load.sql
index 425ca541..cefcfb4c 100644
--- a/regress/sql/age_load.sql
+++ b/regress/sql/age_load.sql
@@ -17,7 +17,9 @@
  * under the License.
  */
 
-\! cp -r regress/age_load/data regress/instance/data/age_load
+\! rm -rf /tmp/age/age_load
+\! mkdir -p /tmp/age
+\! cp -r regress/age_load/data /tmp/age/age_load
 
 LOAD 'age';
 
@@ -34,9 +36,6 @@ SELECT * FROM cypher('agload_test_graph', $$CREATE (n:Country {__id__:1}) RETURN
 SELECT load_labels_from_file('agload_test_graph', 'Country',
     'age_load/countries.csv', true);
 
--- A temporary table should have been created with 54 ids; 1 from CREATE and 53 from file
-SELECT COUNT(*)=54 FROM "_agload_test_graph_ag_vertex_ids";
-
 -- Sequence should be equal to max entry id i.e. 248
 SELECT currval('agload_test_graph."Country_id_seq"')=248;
 
@@ -52,9 +51,6 @@ SELECT load_labels_from_file('agload_test_graph', 'Country',
 SELECT load_labels_from_file('agload_test_graph', 'City',
     'age_load/cities.csv', true);
 
--- Temporary table should have 54+72485 rows now
-SELECT COUNT(*)=54+72485 FROM "_agload_test_graph_ag_vertex_ids";
-
 -- Sequence should be equal to max entry id i.e. 146941
 SELECT currval('agload_test_graph."City_id_seq"')=146941;
 
@@ -166,4 +162,38 @@ SELECT create_elabel('agload_conversion','Edges2');
 SELECT load_edges_from_file('agload_conversion', 'Edges2', 'age_load/conversion_edges.csv', false);
 SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges2]->() RETURN properties(e) $$) as (a agtype);
 
+--
+-- Check sandbox
+--
+-- check null file name
+SELECT load_labels_from_file('agload_conversion', 'Person1', NULL, true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', NULL, true);
+
+-- check no file name
+SELECT load_labels_from_file('agload_conversion', 'Person1', '', true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', '', true);
+
+-- check for file/path does not exist
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load_xxx/conversion_vertices.csv', true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load_xxx/conversion_edges.csv', true);
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
+
+-- check wrong extension
+\! touch /tmp/age/age_load/conversion_vertices.txt
+\! touch /tmp/age/age_load/conversion_edges.txt
+SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
+
+-- check outside sandbox directory
+SELECT load_labels_from_file('agload_conversion', 'Person1', '../../etc/passwd', true, true);
+SELECT load_edges_from_file('agload_conversion', 'Edges1', '../../etc/passwd', true);
+
+--
+-- Cleanup
+--
 SELECT drop_graph('agload_conversion', true);
+
+--
+-- End
+--
diff --git a/regress/sql/agtype.sql b/regress/sql/agtype.sql
index 016f457f..6dab6bc3 100644
--- a/regress/sql/agtype.sql
+++ b/regress/sql/agtype.sql
@@ -1075,9 +1075,56 @@ SELECT * FROM cypher('agtype_build_map', $$ RETURN ag_catalog.agtype_build_map('
                                          $$) AS (results agtype);
 SELECT agtype_build_map('1', '1', 2, 2, 3.14, 3.14, 'e', 2.71);
 
+--
+-- Bug found from issue 2043 - Regression in string concatenation using the + operator
+--
+-- This bug impacted specific numeric cases too.
+--
+SELECT * FROM create_graph('issue_2243');
+SELECT * FROM cypher('issue_2243', $$
+    CREATE (n30164502:Node {data_id: 30164502})
+    RETURN id(n30164502) + ':test_n' + n30164502.data_id
+  $$ ) as (result agtype);
+
+-- concat / add
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer + ":test_n" + 9223372036854775807::integer
+  $$ ) as (result agtype);
+
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric + 9223372036854775807::integer
+  $$ ) as (result agtype);
+
+-- sub
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric - 9223372036854775807::integer
+  $$ ) as (result agtype);
+
+-- mul
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric * 9223372036854775807::integer
+  $$ ) as (result agtype);
+
+-- div
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric / 9223372036854775807::integer
+  $$ ) as (result agtype);
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer / 9223372036854775807::numeric
+  $$ ) as (result agtype);
+
+-- mod
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::numeric % 9223372036854775807::integer
+  $$ ) as (result agtype);
+SELECT * FROM cypher('issue_2243', $$
+    RETURN 9223372036854775807::integer % 9223372036854775807::numeric
+  $$ ) as (result agtype);
+
 --
 -- Cleanup
 --
+SELECT drop_graph('issue_2243', true);
 SELECT drop_graph('agtype_build_map', true);
 
 DROP TABLE agtype_table;
diff --git a/regress/sql/catalog.sql b/regress/sql/catalog.sql
index 85fc4e8a..bb72c349 100644
--- a/regress/sql/catalog.sql
+++ b/regress/sql/catalog.sql
@@ -193,5 +193,45 @@ SELECT raise_notice('graph1');
 
 DROP FUNCTION raise_notice(TEXT);
 
--- dropping the graph
+--
+-- Fix issue 2245 - Creating more than 41 vlabels causes drop_graph to fail with
+--  label (relation) cache corrupted
+--
+
+-- this result will change if another graph was created prior to this point.
+SELECT count(*) FROM ag_label;
+
+SELECT * FROM create_graph('issue_2245');
+SELECT * FROM cypher('issue_2245', $$
+  CREATE (a1:Part1 {part_num: '123'}), (a2:Part2 {part_num: '345'}), (a3:Part3 {part_num: '456'}),
+         (a4:Part4 {part_num: '789'}), (a5:Part5 {part_num: '123'}), (a6:Part6 {part_num: '345'}),
+         (a7:Part7 {part_num: '456'}), (a8:Part8 {part_num: '789'}), (a9:Part9 {part_num: '123'}),
+         (a10:Part10 {part_num: '345'}), (a11:Part11 {part_num: '456'}), (a12:Part12 {part_num: '789'}),
+         (a13:Part13 {part_num: '123'}), (a14:Part14 {part_num: '345'}), (a15:Part15 {part_num: '456'}),
+         (a16:Part16 {part_num: '789'}), (a17:Part17 {part_num: '123'}), (a18:Part18 {part_num: '345'}),
+         (a19:Part19 {part_num: '456'}), (a20:Part20 {part_num: '789'}), (a21:Part21 {part_num: '123'}),
+         (a22:Part22 {part_num: '345'}), (a23:Part23 {part_num: '456'}), (a24:Part24 {part_num: '789'}),
+         (a25:Part25 {part_num: '123'}), (a26:Part26 {part_num: '345'}), (a27:Part27 {part_num: '456'}),
+         (a28:Part28 {part_num: '789'}), (a29:Part29 {part_num: '789'}), (a30:Part30 {part_num: '123'}),
+         (a31:Part31 {part_num: '345'}), (a32:Part32 {part_num: '456'}), (a33:Part33 {part_num: '789'}),
+         (a34:Part34 {part_num: '123'}), (a35:Part35 {part_num: '345'}), (a36:Part36 {part_num: '456'}),
+         (a37:Part37 {part_num: '789'}), (a38:Part38 {part_num: '123'}), (a39:Part39 {part_num: '345'}),
+         (a40:Part40 {part_num: '456'}), (a41:Part41 {part_num: '789'}), (a42:Part42 {part_num: '345'}),
+         (a43:Part43 {part_num: '456'}), (a44:Part44 {part_num: '789'}), (a45:Part45 {part_num: '456'}),
+         (a46:Part46 {part_num: '789'}), (a47:Part47 {part_num: '456'}), (a48:Part48 {part_num: '789'}),
+         (a49:Part49 {part_num: '789'}), (a50:Part50 {part_num: '456'}), (a51:Part51 {part_num: '789'})
+  $$) AS (result agtype);
+
+SELECT count(*) FROM ag_label;
+SELECT drop_graph('issue_2245', true);
+
+-- this result should be the same as the one before the create_graph
+SELECT count(*) FROM ag_label;
+
+-- create the graph again
+SELECT * FROM create_graph('issue_2245');
+SELECT count(*) FROM ag_label;
+
+-- dropping the graphs
+SELECT drop_graph('issue_2245', true);
 SELECT drop_graph('graph', true);
diff --git a/regress/sql/cypher.sql b/regress/sql/cypher.sql
index 7ded61ee..090c7e70 100644
--- a/regress/sql/cypher.sql
+++ b/regress/sql/cypher.sql
@@ -94,6 +94,13 @@ CREATE TABLE my_edges AS
 CREATE TABLE my_detailed_paths AS
     (SELECT * FROM cypher('issue_1767', $$ MATCH p=(u)-[e]->(v) RETURN u,e,v,p $$) as (u agtype, e agtype, v agtype, p agtype));
 
+--
+-- Issue 2256: A segmentation fault occurs when calling the coalesce function
+--             This also occurs with the greatest function too.
+--
+SELECT * FROM coalesce(1, 0);
+SELECT * FROM greatest(1, 0);
+
 -- dump out the tables
 SELECT * FROM my_vertices;
 SELECT * FROM my_edges;
diff --git a/regress/sql/cypher_call.sql b/regress/sql/cypher_call.sql
index 91727680..ee146875 100644
--- a/regress/sql/cypher_call.sql
+++ b/regress/sql/cypher_call.sql
@@ -104,5 +104,30 @@ SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt AS sqrt1 CALL sq
 SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt AS sqrt1 CALL sqrt(81) YIELD sqrt AS sqrt1 RETURN sqrt1, sqrt1 $$) as (a agtype, b agtype);
 SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt CALL agtype_sum(2,2) YIELD agtype_sum AS sqrt RETURN sqrt, sqrt $$) as (a agtype, b agtype);
 
+-- Fix CALL/YIELD issues
+CREATE OR REPLACE FUNCTION myfunc(i agtype)
+RETURNS agtype
+LANGUAGE plpgsql
+AS $$
+DECLARE
+    result agtype;
+BEGIN
+    RETURN ag_catalog.age_sqrt(i);
+END;
+$$;
+
+-- should have no errors
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.age_sqrt(64) YIELD age_sqrt RETURN age_sqrt $$) as (sqrt agtype);
+SELECT * FROM cypher('cypher_call', $$ CALL myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+
+-- should error
+SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype);
+SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype);
+SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype);
+
+DROP FUNCTION myfunc;
+
 DROP SCHEMA call_stmt_test CASCADE;
 SELECT drop_graph('cypher_call', true);
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index 83f21856..7bf1f26b 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -2823,6 +2823,7 @@ SELECT * FROM cypher('order_by', $$CREATE ({i: false})$$) AS (result agtype);
 SELECT * FROM cypher('order_by', $$CREATE ({i: {key: 'value'}})$$) AS (result agtype);
 SELECT * FROM cypher('order_by', $$CREATE ({i: [1]})$$) AS (result agtype);
 
+
 SELECT * FROM cypher('order_by', $$
 	MATCH (u)
 	RETURN u.i
@@ -2835,6 +2836,35 @@ SELECT * FROM cypher('order_by', $$
 	ORDER BY u.i DESC
 $$) AS (i agtype);
 
+--
+-- Test ORDER BY with AS
+--
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'John', age: 38}) $$) AS (result agtype);
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Jill', age: 23}) $$) AS (result agtype);
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Ion', age: 34}) $$) AS (result agtype);
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Mary', age: 57}) $$) AS (result agtype);
+SELECT * FROM cypher('order_by', $$ CREATE ({name: 'Jerry', age: 34}) $$) AS (result agtype);
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name
+$$) AS (name agtype, age agtype);
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name ASC
+$$) AS (name agtype, age agtype);
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY name DESC
+$$) AS (name agtype, age agtype);
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY age ASC, name DESCENDING 
+$$) AS (name agtype, age agtype);
+
+SELECT * FROM cypher('order_by', $$
+        MATCH (u) WHERE EXISTS(u.name) RETURN u.name AS name, u.age AS age ORDER BY age DESC, name ASCENDING
+$$) AS (name agtype, age agtype);
+
 --CASE
 SELECT create_graph('case_statement');
 SELECT * FROM cypher('case_statement', $$CREATE ({id: 1, i: 1, j: null})-[:connected_to {id: 1, k:0}]->({id: 2, i: 'a', j: 'b'})$$) AS (result agtype);
@@ -3634,9 +3664,36 @@ SELECT * FROM cypher('issue_1988', $$
 SELECT agtype_access_operator(agtype_in('[null, null]'));
 SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]'));
 
+--
+-- Issue 2263: AGE returns incorrect error message for EXISTS subquery outer variable reference
+--
+--       NOTE: There isn't really anything incorrect about the message. However,
+--             it could be more clear.
+--
+SELECT * FROM create_graph('issue_2263');
+SELECT * FROM cypher('issue_2263', $$
+    CREATE a=()-[:T]->(), p=({k:exists{return a}})-[:T]->()
+    RETURN 1
+$$) AS (one agtype);
+SELECT * FROM cypher('issue_2263', $$
+    CREATE p0=(n0), (n1{k:EXISTS{WITH p0}})
+    RETURN 1
+$$) AS (one agtype);
+SELECT * FROM cypher('issue_2263', $$
+    CREATE ()-[r4 :T6]->(), ({k2:COUNT{WITH r4.k AS a3 UNWIND [] AS a4 WITH DISTINCT NULL AS a5}})
+    RETURN 1
+$$) AS (one agtype);
+SELECT * FROM cypher('issue_2263', $$
+    CREATE (x), ({a1:EXISTS { RETURN COUNT(0) AS a2, keys(x) AS a4 }})
+$$) AS (out agtype);
+SELECT * FROM cypher('issue_2263', $$
+    CREATE x = (), ({ a0:COUNT { MATCH () WHERE CASE WHEN true THEN (x IS NULL) END RETURN 0 } })
+$$) AS (out agtype);
+
 --
 -- Cleanup
 --
+SELECT * FROM drop_graph('issue_2263', true);
 SELECT * FROM drop_graph('issue_1988', true);
 SELECT * FROM drop_graph('issue_1953', true);
 SELECT * FROM drop_graph('expanded_map', true);
diff --git a/regress/sql/index.sql b/regress/sql/index.sql
index aac1dc40..d9a4331a 100644
--- a/regress/sql/index.sql
+++ b/regress/sql/index.sql
@@ -166,26 +166,8 @@ SELECT * FROM cypher('cypher_index', $$
         (mx)<-[:has_city]-(:City {city_id: 10, name:"Tijuana", west_coast: false, country_code:"MX"})
 $$) as (n agtype);
 
-ALTER TABLE cypher_index."Country" ADD PRIMARY KEY (id);
-
-CREATE UNIQUE INDEX CONCURRENTLY cntry_id_idx ON cypher_index."Country" (id);
-ALTER TABLE cypher_index."Country"  CLUSTER ON cntry_id_idx;
-
-ALTER TABLE cypher_index."City" ADD PRIMARY KEY (id);
-
-CREATE UNIQUE INDEX city_id_idx ON cypher_index."City" (id);
-
-ALTER TABLE cypher_index."City" CLUSTER ON city_id_idx;
-
-ALTER TABLE cypher_index.has_city
-ADD CONSTRAINT has_city_end_fk FOREIGN KEY (end_id)
-REFERENCES cypher_index."Country"(id) MATCH FULL;
-
-CREATE INDEX load_has_city_eid_idx ON cypher_index.has_city (end_id);
-
-CREATE INDEX load_has_city_sid_idx ON cypher_index.has_city (start_id);
-
-ALTER TABLE cypher_index."has_city" CLUSTER ON load_has_city_eid_idx;
+-- Verify that the incices are created on id columns
+SELECT indexname, indexdef FROM pg_indexes WHERE schemaname= 'cypher_index';
 
 SET enable_mergejoin = ON;
 SET enable_hashjoin = OFF;
@@ -196,6 +178,11 @@ SELECT COUNT(*) FROM cypher('cypher_index', $$
     RETURN e
 $$) as (n agtype);
 
+SELECT COUNT(*) FROM cypher('cypher_index', $$
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
+    RETURN e
+$$) as (n agtype);
+
 SET enable_mergejoin = OFF;
 SET enable_hashjoin = ON;
 SET enable_nestloop = OFF;
@@ -205,12 +192,17 @@ SELECT COUNT(*) FROM cypher('cypher_index', $$
     RETURN e
 $$) as (n agtype);
 
+SELECT COUNT(*) FROM cypher('cypher_index', $$
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
+    RETURN e
+$$) as (n agtype);
+
 SET enable_mergejoin = OFF;
 SET enable_hashjoin = OFF;
 SET enable_nestloop = ON;
 
 SELECT COUNT(*) FROM cypher('cypher_index', $$
-    MATCH (a:Country)<-[e:has_city]-()
+    EXPLAIN (costs off) MATCH (a:Country)<-[e:has_city]-()
     RETURN e
 $$) as (n agtype);
 
diff --git a/sql/agtype_graphid.sql b/sql/agtype_graphid.sql
index 4e05943a..0887db8a 100644
--- a/sql/agtype_graphid.sql
+++ b/sql/agtype_graphid.sql
@@ -77,6 +77,27 @@ CALLED ON NULL INPUT
 PARALLEL SAFE
 AS 'MODULE_PATHNAME';
 
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness2(graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness3(graphid, graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
+
+CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness4(graphid, graphid, graphid, graphid)
+    RETURNS bool
+    LANGUAGE c
+    STABLE
+PARALLEL SAFE
+as 'MODULE_PATHNAME';
+
 CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness(VARIADIC "any")
     RETURNS bool
     LANGUAGE c
diff --git a/src/backend/catalog/ag_label.c b/src/backend/catalog/ag_label.c
index b6dcf77a..54c31ef3 100644
--- a/src/backend/catalog/ag_label.c
+++ b/src/backend/catalog/ag_label.c
@@ -21,6 +21,7 @@
 
 #include "access/genam.h"
 #include "catalog/indexing.h"
+#include "executor/executor.h"
 #include "nodes/makefuncs.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
diff --git a/src/backend/commands/label_commands.c b/src/backend/commands/label_commands.c
index f603ec97..c9fdfad8 100644
--- a/src/backend/commands/label_commands.c
+++ b/src/backend/commands/label_commands.c
@@ -79,6 +79,10 @@ static void range_var_callback_for_remove_relation(const RangeVar *rel,
                                                    Oid rel_oid,
                                                    Oid odl_rel_oid,
                                                    void *arg);
+static void create_index_on_column(char *schema_name,
+                                   char *rel_name,
+                                   char *colname,
+                                   bool unique);
 
 PG_FUNCTION_INFO_V1(age_is_valid_label_name);
 
@@ -379,16 +383,24 @@ static void create_table_for_label(char *graph_name, char *label_name,
      * inheritance system.
      */
     if (list_length(parents) != 0)
+    {
         create_stmt->tableElts = NIL;
+    }
     else if (label_type == LABEL_TYPE_EDGE)
+    {
         create_stmt->tableElts = create_edge_table_elements(
             graph_name, label_name, schema_name, rel_name, seq_name);
+    }
     else if (label_type == LABEL_TYPE_VERTEX)
+    {
         create_stmt->tableElts = create_vertex_table_elements(
             graph_name, label_name, schema_name, rel_name, seq_name);
+    }
     else
+    {
         ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
                         errmsg("undefined label type \'%c\'", label_type)));
+    }
 
     create_stmt->inhRelations = parents;
     create_stmt->partbound = NULL;
@@ -409,7 +421,69 @@ static void create_table_for_label(char *graph_name, char *label_name,
     ProcessUtility(wrapper, "(generated CREATE TABLE command)", false,
                    PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, None_Receiver,
                    NULL);
-    /* CommandCounterIncrement() is called in ProcessUtility() */
+    
+    /* Create index on id columns */
+    if (label_type == LABEL_TYPE_VERTEX)
+    {
+        create_index_on_column(schema_name, rel_name, "id", true);
+    }
+    else if (label_type == LABEL_TYPE_EDGE)
+    {
+        create_index_on_column(schema_name, rel_name, "start_id", false);
+        create_index_on_column(schema_name, rel_name, "end_id", false);
+    }
+}
+
+static void create_index_on_column(char *schema_name,
+                                   char *rel_name,
+                                   char *colname,
+                                   bool unique)
+{
+    IndexStmt *index_stmt;
+    IndexElem *index_col;
+    PlannedStmt *index_wrapper;
+
+    index_stmt = makeNode(IndexStmt);
+    index_col = makeNode(IndexElem);
+    index_col->name = colname;
+    index_col->expr = NULL;
+    index_col->indexcolname = NULL;
+    index_col->collation = InvalidOid;
+    index_col->opclass = list_make1(makeString("graphid_ops"));
+    index_col->opclassopts = NIL;
+    index_col->ordering = SORTBY_DEFAULT;
+    index_col->nulls_ordering = SORTBY_NULLS_DEFAULT;
+
+    index_stmt->relation = makeRangeVar(schema_name, rel_name, -1);
+    index_stmt->accessMethod = "btree";
+    index_stmt->tableSpace = NULL;
+    index_stmt->indexParams = list_make1(index_col);
+    index_stmt->options = NIL;
+    index_stmt->whereClause = NULL;
+    index_stmt->excludeOpNames = NIL;
+    index_stmt->idxcomment = NULL;
+    index_stmt->indexOid = InvalidOid;
+    index_stmt->unique = unique;
+    index_stmt->nulls_not_distinct = false;
+    index_stmt->primary = unique;
+    index_stmt->isconstraint = unique;
+    index_stmt->deferrable = false;
+    index_stmt->initdeferred = false;
+    index_stmt->transformed = false;
+    index_stmt->concurrent = false;
+    index_stmt->if_not_exists = false;
+    index_stmt->reset_default_tblspc = false;
+
+    index_wrapper = makeNode(PlannedStmt);
+    index_wrapper->commandType = CMD_UTILITY;
+    index_wrapper->canSetTag = false;
+    index_wrapper->utilityStmt = (Node *)index_stmt;
+    index_wrapper->stmt_location = -1;
+    index_wrapper->stmt_len = 0;
+
+    ProcessUtility(index_wrapper, "(generated CREATE INDEX command)", false,
+                   PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, None_Receiver,
+                   NULL);
 }
 
 /* 
@@ -468,7 +542,7 @@ static List *create_vertex_table_elements(char *graph_name, char *label_name,
 
     /* "id" graphid PRIMARY KEY DEFAULT "ag_catalog"."_graphid"(...) */
     id = makeColumnDef(AG_VERTEX_COLNAME_ID, GRAPHIDOID, -1, InvalidOid);
-    id->constraints = list_make2(build_pk_constraint(),
+    id->constraints = list_make2(build_not_null_constraint(),
                                  build_id_default(graph_name, label_name,
                                                   schema_name, seq_name));
 
diff --git a/src/backend/executor/cypher_create.c b/src/backend/executor/cypher_create.c
index 2091ea29..2031fe8d 100644
--- a/src/backend/executor/cypher_create.c
+++ b/src/backend/executor/cypher_create.c
@@ -19,6 +19,8 @@
 
 #include "postgres.h"
 
+#include "executor/executor.h"
+
 #include "catalog/ag_label.h"
 #include "executor/cypher_executor.h"
 #include "executor/cypher_utils.h"
diff --git a/src/backend/executor/cypher_delete.c b/src/backend/executor/cypher_delete.c
index 6bb86983..f86c6126 100644
--- a/src/backend/executor/cypher_delete.c
+++ b/src/backend/executor/cypher_delete.c
@@ -19,6 +19,7 @@
 
 #include "postgres.h"
 
+#include "executor/executor.h"
 #include "storage/bufmgr.h"
 #include "common/hashfn.h"
 
@@ -257,7 +258,7 @@ static agtype_value *extract_entity(CustomScanState *node,
     tupleDescriptor = scanTupleSlot->tts_tupleDescriptor;
 
     /* type checking, make sure the entity is an agtype vertex or edge */
-    if (tupleDescriptor->attrs[entity_position -1].atttypid != AGTYPEOID)
+    if (TupleDescAttr(tupleDescriptor, entity_position -1)->atttypid != AGTYPEOID)
         ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("DELETE clause can only delete agtype")));
 
@@ -340,6 +341,10 @@ static void delete_entity(EState *estate, ResultRelInfo *resultRelInfo,
         }
         /* increment the command counter */
         CommandCounterIncrement();
+
+        /* Update command id in estate */
+        estate->es_snapshot->curcid = GetCurrentCommandId(false);
+        estate->es_output_cid = GetCurrentCommandId(false);
     }
     else if (lock_result != TM_Invisible && lock_result != TM_SelfModified)
     {
diff --git a/src/backend/executor/cypher_merge.c b/src/backend/executor/cypher_merge.c
index 9136825a..6cfa70d4 100644
--- a/src/backend/executor/cypher_merge.c
+++ b/src/backend/executor/cypher_merge.c
@@ -19,6 +19,8 @@
 
 #include "postgres.h"
 
+#include "executor/executor.h"
+
 #include "catalog/ag_label.h"
 #include "executor/cypher_executor.h"
 #include "executor/cypher_utils.h"
diff --git a/src/backend/executor/cypher_set.c b/src/backend/executor/cypher_set.c
index d1837fb1..9fd599ee 100644
--- a/src/backend/executor/cypher_set.c
+++ b/src/backend/executor/cypher_set.c
@@ -19,6 +19,7 @@
 
 #include "postgres.h"
 
+#include "executor/executor.h"
 #include "storage/bufmgr.h"
 
 #include "executor/cypher_executor.h"
@@ -102,6 +103,7 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
     TM_Result   result;
     CommandId cid = GetCurrentCommandId(true);
     ResultRelInfo **saved_resultRels = estate->es_result_relations;
+    bool close_indices = false;
 
     estate->es_result_relations = &resultRelInfo;
 
@@ -113,7 +115,16 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
 
     if (lock_result == TM_Ok)
     {
-        ExecOpenIndices(resultRelInfo, false);
+        /*
+         * Open indices if not already open. The resultRelInfo may already
+         * have indices opened by the caller (e.g., create_entity_result_rel_info),
+         * so only open if needed and track that we did so for cleanup.
+         */
+        if (resultRelInfo->ri_IndexRelationDescs == NULL)
+        {
+            ExecOpenIndices(resultRelInfo, false);
+            close_indices = true;
+        }
         ExecStoreVirtualTuple(elemTupleSlot);
         tuple = ExecFetchSlotHeapTuple(elemTupleSlot, true, NULL);
         tuple->t_self = old_tuple->t_self;
@@ -141,7 +152,10 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
                          errmsg("tuple to be updated was already modified")));
             }
 
-            ExecCloseIndices(resultRelInfo);
+            if (close_indices)
+            {
+                ExecCloseIndices(resultRelInfo);
+            }
             estate->es_result_relations = saved_resultRels;
 
             return tuple;
@@ -160,7 +174,10 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
                                 (update_indexes == TU_Summarizing));
         }
 
-        ExecCloseIndices(resultRelInfo);
+        if (close_indices)
+        {
+            ExecCloseIndices(resultRelInfo);
+        }
     }
     else if (lock_result == TM_SelfModified)
     {
@@ -310,7 +327,7 @@ static void update_all_paths(CustomScanState *node, graphid id,
         agtype_value *original_entity_value;
 
         /* skip nulls */
-        if (scanTupleSlot->tts_tupleDescriptor->attrs[i].atttypid != AGTYPEOID)
+        if (TupleDescAttr(scanTupleSlot->tts_tupleDescriptor, i)->atttypid != AGTYPEOID)
         {
             continue;
         }
@@ -414,7 +431,7 @@ static void process_update_list(CustomScanState *node)
             continue;
         }
 
-        if (scanTupleSlot->tts_tupleDescriptor->attrs[update_item->entity_position -1].atttypid != AGTYPEOID)
+        if (TupleDescAttr(scanTupleSlot->tts_tupleDescriptor, update_item->entity_position -1)->atttypid != AGTYPEOID)
         {
             ereport(ERROR,
                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -588,7 +605,7 @@ static void process_update_list(CustomScanState *node)
         }
 
         estate->es_snapshot->curcid = cid;
-        /* close relation */
+        /* close relation */        
         ExecCloseIndices(resultRelInfo);
         table_close(resultRelInfo->ri_RelationDesc, RowExclusiveLock);
 
diff --git a/src/backend/executor/cypher_utils.c b/src/backend/executor/cypher_utils.c
index c8d56883..d7a55f70 100644
--- a/src/backend/executor/cypher_utils.c
+++ b/src/backend/executor/cypher_utils.c
@@ -24,6 +24,7 @@
 
 #include "postgres.h"
 
+#include "executor/executor.h"
 #include "nodes/makefuncs.h"
 #include "parser/parse_relation.h"
 
diff --git a/src/backend/parser/cypher_analyze.c b/src/backend/parser/cypher_analyze.c
index af3e83c8..a408eea6 100644
--- a/src/backend/parser/cypher_analyze.c
+++ b/src/backend/parser/cypher_analyze.c
@@ -171,14 +171,20 @@ static bool convert_cypher_walker(Node *node, ParseState *pstate)
          * JsonConstructorExpr - wrapper over FuncExpr/Aggref/WindowFunc for
          *                       SQL/JSON constructors
          *
-         * These are a special case that needs to be ignored.
+         * Added the following, although only the first 2 caused crashes in tests -
+         * CoalesceExpr, MinMaxExpr, CaseExpr, XmlExpr, ArrayExpr, RowExpr
+         *
+         * These are all special case that needs to be ignored.
          *
          */
         if (IsA(funcexpr, SQLValueFunction)
-                || IsA(funcexpr, CoerceViaIO)
-                || IsA(funcexpr, Var)   || IsA(funcexpr, OpExpr)
-                || IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr)
-                || IsA(funcexpr, JsonConstructorExpr))
+            || IsA(funcexpr, CoerceViaIO)
+            || IsA(funcexpr, Var)   || IsA(funcexpr, OpExpr)
+            || IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr)
+            || IsA(funcexpr, JsonConstructorExpr)
+            || IsA(funcexpr, CoalesceExpr) || IsA(funcexpr, MinMaxExpr)
+            || IsA(funcexpr, CaseExpr) || IsA(funcexpr, XmlExpr)
+            || IsA(funcexpr, ArrayExpr) || IsA(funcexpr, RowExpr))
         {
             return false;
         }
@@ -346,14 +352,20 @@ static bool is_func_cypher(FuncExpr *funcexpr)
      * JsonConstructorExpr - wrapper over FuncExpr/Aggref/WindowFunc for
      *                       SQL/JSON constructors
      *
-     * These are a special case that needs to be ignored.
+     * Added the following, although only the first 2 caused crashes in tests -
+     * CoalesceExpr, MinMaxExpr, CaseExpr, XmlExpr, ArrayExpr, RowExpr
+     *
+     * These are all special case that needs to be ignored.
      *
      */
     if (IsA(funcexpr, SQLValueFunction)
             || IsA(funcexpr, CoerceViaIO)
             || IsA(funcexpr, Var)   || IsA(funcexpr, OpExpr)
             || IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr)
-            || IsA(funcexpr, JsonConstructorExpr))
+            || IsA(funcexpr, JsonConstructorExpr)
+            || IsA(funcexpr, CoalesceExpr) || IsA(funcexpr, MinMaxExpr)
+            || IsA(funcexpr, CaseExpr) || IsA(funcexpr, XmlExpr)
+            || IsA(funcexpr, ArrayExpr) || IsA(funcexpr, RowExpr))
     {
         return false;
     }
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index 172e6305..acc52349 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -1153,7 +1153,7 @@ static Query *transform_cypher_call_subquery(cypher_parsestate *cpstate,
                                                      EXPR_KIND_FROM_FUNCTION));
 
     /* retrieve the column name from funccall */
-    colName = strVal(linitial(self->funccall->funcname));
+    colName = strVal(llast(self->funccall->funcname));
 
     /* make a targetentry from the funcexpr node */
     tle = makeTargetEntry((Expr *) node,
@@ -2296,6 +2296,32 @@ static TargetEntry *find_target_list_entry(cypher_parsestate *cpstate,
     ListCell *lt;
     TargetEntry *te;
 
+    /*
+     * If the ORDER BY item is a simple identifier, check if it matches
+     * an alias in the target list. This implements SQL99-compliant
+     * alias matching for ORDER BY clauses.
+     */
+    if (IsA(node, ColumnRef))
+    {
+        ColumnRef *cref = (ColumnRef *)node;
+
+        if (list_length(cref->fields) == 1)
+        {
+            char *name = strVal(linitial(cref->fields));
+
+            /* Try to match an alias in the target list */
+            foreach (lt, *target_list)
+            {
+                te = lfirst(lt);
+
+                if (te->resname != NULL && strcmp(te->resname, name) == 0)
+                {
+                    return te;
+                }
+            }
+        }
+    }
+
     expr = transform_cypher_expr(cpstate, node, expr_kind);
 
     foreach (lt, *target_list)
@@ -2585,9 +2611,9 @@ static void get_res_cols(ParseState *pstate, ParseNamespaceItem *l_pnsi,
     List *colnames = NIL;
     List *colvars = NIL;
 
-    expandRTE(l_pnsi->p_rte, l_pnsi->p_rtindex, 0, -1, false,
+    expandRTE(l_pnsi->p_rte, l_pnsi->p_rtindex, 0, VAR_RETURNING_DEFAULT, -1, false,
               &l_colnames, &l_colvars);
-    expandRTE(r_pnsi->p_rte, r_pnsi->p_rtindex, 0, -1, false,
+    expandRTE(r_pnsi->p_rte, r_pnsi->p_rtindex, 0, VAR_RETURNING_DEFAULT, -1, false,
               &r_colnames, &r_colvars);
 
     /* add in all colnames and colvars from the l_rte. */
@@ -3276,13 +3302,13 @@ static FuncCall *prevent_duplicate_edges(cypher_parsestate *cpstate,
 {
     List *edges = NIL;
     ListCell *lc;
-    List *qualified_function_name;
-    String *ag_catalog, *edge_fn;
+    List *qualified_function_name = NULL;
+    String *ag_catalog;
+    String *edge_fn = NULL;
+    bool is_vle_edge = false;
+    int nentities = list_length(entities);
 
     ag_catalog = makeString("ag_catalog");
-    edge_fn = makeString("_ag_enforce_edge_uniqueness");
-
-    qualified_function_name = list_make2(ag_catalog, edge_fn);
 
     /* iterate through each entity, collecting the access node for each edge */
     foreach (lc, entities)
@@ -3298,10 +3324,33 @@ static FuncCall *prevent_duplicate_edges(cypher_parsestate *cpstate,
         }
         else if (entity->type == ENT_VLE_EDGE)
         {
+            is_vle_edge = true;
             edges = lappend(edges, entity->expr);
         }
     }
 
+    if (!is_vle_edge && (nentities >= 5 && nentities <= 9))
+    {
+        if (nentities == 5)
+        {
+            edge_fn = makeString("_ag_enforce_edge_uniqueness2");
+        }
+        else if (nentities == 7)
+        {
+            edge_fn = makeString("_ag_enforce_edge_uniqueness3");
+        }
+        else
+        {
+            edge_fn = makeString("_ag_enforce_edge_uniqueness4");
+        }
+    }
+    else
+    {
+        edge_fn = makeString("_ag_enforce_edge_uniqueness");
+    }
+
+    qualified_function_name = list_make2(ag_catalog, edge_fn);
+
     return makeFuncCall(qualified_function_name, edges, COERCE_SQL_SYNTAX, -1);
 }
 
@@ -3957,7 +4006,7 @@ static List *transform_map_to_ind_recursive(cypher_parsestate *cpstate,
  *
  * Transforms the map to a list of equality irrespective of
  * value type. For example,
- * 
+ *
  * x.name = 'xyz'
  * x.map = {"city": "abc", "street": {"name": "pqr", "number": 123}}
  * x.list = [9, 8, 7]
@@ -4011,7 +4060,7 @@ static List *transform_map_to_ind_top_level(cypher_parsestate *cpstate,
         qual = (Node *)make_op(pstate, op, lhs, rhs, last_srf, -1);
         quals = lappend(quals, qual);
     }
-    
+
     return quals;
 }
 
@@ -6292,6 +6341,7 @@ transform_cypher_clause_as_subquery(cypher_parsestate *cpstate,
            pstate->p_expr_kind == EXPR_KIND_OTHER ||
            pstate->p_expr_kind == EXPR_KIND_WHERE ||
            pstate->p_expr_kind == EXPR_KIND_SELECT_TARGET ||
+           pstate->p_expr_kind == EXPR_KIND_INSERT_TARGET ||
            pstate->p_expr_kind == EXPR_KIND_FROM_SUBSELECT);
 
     /*
diff --git a/src/backend/parser/cypher_expr.c b/src/backend/parser/cypher_expr.c
index 390bfb39..5f4de86b 100644
--- a/src/backend/parser/cypher_expr.c
+++ b/src/backend/parser/cypher_expr.c
@@ -423,9 +423,11 @@ static Node *transform_ColumnRef(cypher_parsestate *cpstate, ColumnRef *cref)
                 else
                 {
                     ereport(ERROR,
-                                (errcode(ERRCODE_UNDEFINED_COLUMN),
-                                 errmsg("could not find rte for %s", colname),
-                                 parser_errposition(pstate, cref->location)));
+                            (errcode(ERRCODE_UNDEFINED_COLUMN),
+                             errmsg("could not find rte for %s", colname),
+                             errhint("variable %s does not exist within scope of usage",
+                                     colname),
+                             parser_errposition(pstate, cref->location)));
                 }
 
                 if (node == NULL)
@@ -2036,7 +2038,7 @@ static Node *transform_FuncCall(cypher_parsestate *cpstate, FuncCall *fn)
                 targs = lcons(c, targs);
             }
         }
-        /* 
+        /*
          * If it's not in age, check if it's a potential call to some function
          * in another installed extension.
          */
@@ -2055,14 +2057,13 @@ static Node *transform_FuncCall(cypher_parsestate *cpstate, FuncCall *fn)
                                                          procform, extension);
                 return retval;
             }
+            /*
+             * Else we have a function that is in the search_path, and not
+             * qualified, but is not in an extension. Pass it through.
+             */
             else
             {
-                ereport(ERROR,
-                        (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                        errmsg("function %s does not exist", name),
-                        errhint("If the function is from an external extension, "
-                                "make sure the extension is installed and the "
-                                "function is in the search path.")));
+                fname = fn->funcname;
             }
         }
         /* no function found */
diff --git a/src/backend/parser/cypher_gram.y b/src/backend/parser/cypher_gram.y
index 0bafefe1..5ba1e635 100644
--- a/src/backend/parser/cypher_gram.y
+++ b/src/backend/parser/cypher_gram.y
@@ -41,6 +41,9 @@
 
 #define YYMALLOC palloc
 #define YYFREE pfree
+
+/* Helper macro for keyword string duplication */
+#define KEYWORD_STRDUP(kw) pnstrdup((kw), strlen(kw))
 %}
 
 %locations
@@ -276,6 +279,11 @@ static Node *build_list_comprehension_node(Node *var, Node *expr,
                                            Node *where, Node *mapping_expr,
                                            int location);
 
+/* helper functions */
+static ExplainStmt *make_explain_stmt(List *options);
+static void validate_return_item_aliases(List *items, ag_scanner_t scanner);
+static cypher_return *make_default_return_node(int location);
+
 %}
 %%
 
@@ -300,81 +308,59 @@ stmt:
              * Throw syntax error in this case.
              */
             if (yychar != YYEOF)
+            {
                 yyerror(&yylloc, scanner, extra, "syntax error");
+            }
 
             extra->result = $1;
             extra->extra = NULL;
         }
     | EXPLAIN cypher_stmt semicolon_opt
         {
-            ExplainStmt *estmt = NULL;
-
             if (yychar != YYEOF)
+            {
                 yyerror(&yylloc, scanner, extra, "syntax error");
-
+            }
             extra->result = $2;
-
-            estmt = makeNode(ExplainStmt);
-            estmt->query = NULL;
-            estmt->options = NIL;
-            extra->extra = (Node *)estmt;
+            extra->extra = (Node *)make_explain_stmt(NIL);
         }
     | EXPLAIN VERBOSE cypher_stmt semicolon_opt
         {
-            ExplainStmt *estmt = NULL;
-
             if (yychar != YYEOF)
+            {
                 yyerror(&yylloc, scanner, extra, "syntax error");
-
+            }
             extra->result = $3;
-
-            estmt = makeNode(ExplainStmt);
-            estmt->query = NULL;
-            estmt->options = list_make1(makeDefElem("verbose", NULL, @2));;
-            extra->extra = (Node *)estmt;
+            extra->extra = (Node *)make_explain_stmt(
+                list_make1(makeDefElem("verbose", NULL, @2)));
         }
     | EXPLAIN ANALYZE cypher_stmt semicolon_opt
         {
-            ExplainStmt *estmt = NULL;
-
             if (yychar != YYEOF)
+            {
                 yyerror(&yylloc, scanner, extra, "syntax error");
-
+            }
             extra->result = $3;
-
-            estmt = makeNode(ExplainStmt);
-            estmt->query = NULL;
-            estmt->options = list_make1(makeDefElem("analyze", NULL, @2));;
-            extra->extra = (Node *)estmt;
+            extra->extra = (Node *)make_explain_stmt(
+                list_make1(makeDefElem("analyze", NULL, @2)));
         }
     | EXPLAIN ANALYZE VERBOSE cypher_stmt semicolon_opt
         {
-            ExplainStmt *estmt = NULL;
-
             if (yychar != YYEOF)
                 yyerror(&yylloc, scanner, extra, "syntax error");
-
             extra->result = $4;
-
-            estmt = makeNode(ExplainStmt);
-            estmt->query = NULL;
-            estmt->options = list_make2(makeDefElem("analyze", NULL, @2),
-                                        makeDefElem("verbose", NULL, @3));;
-            extra->extra = (Node *)estmt;
+            extra->extra = (Node *)make_explain_stmt(
+                list_make2(makeDefElem("analyze", NULL, @2),
+                          makeDefElem("verbose", NULL, @3)));
         }
     | EXPLAIN '(' utility_option_list ')' cypher_stmt semicolon_opt
         {
-            ExplainStmt *estmt = NULL;
-
             if (yychar != YYEOF)
+            {
                 yyerror(&yylloc, scanner, extra, "syntax error");
-
+            }
             extra->result = $5;
-
-            estmt = makeNode(ExplainStmt);
-            estmt->query = NULL;
-            estmt->options = $3;
-            extra->extra = (Node *)estmt;
+            extra->extra = (Node *)make_explain_stmt($3);
         }
     ;
 
@@ -652,57 +638,20 @@ single_subquery:
 single_subquery_no_return:
     subquery_part_init reading_clause_list
         {
-            ColumnRef *cr;
-            ResTarget *rt;
             cypher_return *n;
 
             /*
              * since subqueries allow return-less clauses, we add a
              * return node manually to reflect that syntax
              */
-            cr = makeNode(ColumnRef);
-            cr->fields = list_make1(makeNode(A_Star));
-            cr->location = @1;
-
-            rt = makeNode(ResTarget);
-            rt->name = NULL;
-            rt->indirection = NIL;
-            rt->val = (Node *)cr;
-            rt->location = @1;
-
-            n = make_ag_node(cypher_return);
-            n->distinct = false;
-            n->items = list_make1((Node *)rt);
-            n->order_by = NULL;
-            n->skip = NULL;
-            n->limit = NULL;
-
+            n = make_default_return_node(@1);
             $$ = list_concat($1, lappend($2, n));
-
         }
-        | subquery_pattern
+    | subquery_pattern
         {
-            ColumnRef *cr;
-            ResTarget *rt;
             cypher_return *n;
 
-            cr = makeNode(ColumnRef);
-            cr->fields = list_make1(makeNode(A_Star));
-            cr->location = @1;
-
-            rt = makeNode(ResTarget);
-            rt->name = NULL;
-            rt->indirection = NIL;
-            rt->val = (Node *)cr;
-            rt->location = @1;
-
-            n = make_ag_node(cypher_return);
-            n->distinct = false;
-            n->items = list_make1((Node *)rt);
-            n->order_by = NULL;
-            n->skip = NULL;
-            n->limit = NULL;
-
+            n = make_default_return_node(@1);
             $$ = lappend(list_make1($1), n);
         }
     ;
@@ -958,24 +907,10 @@ limit_opt:
 with:
     WITH DISTINCT return_item_list order_by_opt skip_opt limit_opt where_opt
         {
-            ListCell *li;
             cypher_with *n;
 
             /* check expressions are aliased */
-            foreach(li, $3)
-            {
-                ResTarget *item = lfirst(li);
-
-                /* variable does not have to be aliased */
-                if (IsA(item->val, ColumnRef) || item->name)
-                    continue;
-
-                ereport(ERROR,
-                        (errcode(ERRCODE_SYNTAX_ERROR),
-                         errmsg("expression item must be aliased"),
-                         errhint("Items can be aliased by using AS."),
-                         ag_scanner_errposition(item->location, scanner)));
-            }
+            validate_return_item_aliases($3, scanner);
 
             n = make_ag_node(cypher_with);
             n->distinct = true;
@@ -987,27 +922,12 @@ with:
 
             $$ = (Node *)n;
         }
-    | WITH return_item_list order_by_opt skip_opt limit_opt
-    where_opt
+    | WITH return_item_list order_by_opt skip_opt limit_opt where_opt
         {
-            ListCell *li;
             cypher_with *n;
 
             /* check expressions are aliased */
-            foreach (li, $2)
-            {
-                ResTarget *item = lfirst(li);
-
-                /* variable does not have to be aliased */
-                if (IsA(item->val, ColumnRef) || item->name)
-                    continue;
-
-                ereport(ERROR,
-                        (errcode(ERRCODE_SYNTAX_ERROR),
-                         errmsg("expression item must be aliased"),
-                         errhint("Items can be aliased by using AS."),
-                         ag_scanner_errposition(item->location, scanner)));
-            }
+            validate_return_item_aliases($2, scanner);
 
             n = make_ag_node(cypher_with);
             n->distinct = false;
@@ -2449,58 +2369,58 @@ qual_op:
  */
 
 safe_keywords:
-    ALL          { $$ = pnstrdup($1, 3); }
-    | ANALYZE    { $$ = pnstrdup($1, 7); }
-    | AND        { $$ = pnstrdup($1, 3); }
-    | AS         { $$ = pnstrdup($1, 2); }
-    | ASC        { $$ = pnstrdup($1, 3); }
-    | ASCENDING  { $$ = pnstrdup($1, 9); }
-    | BY         { $$ = pnstrdup($1, 2); }
-    | CALL       { $$ = pnstrdup($1, 4); }
-    | CASE       { $$ = pnstrdup($1, 4); }
-    | COALESCE   { $$ = pnstrdup($1, 8); }
-    | CONTAINS   { $$ = pnstrdup($1, 8); }
-    | COUNT      { $$ = pnstrdup($1 ,5); }
-    | CREATE     { $$ = pnstrdup($1, 6); }
-    | DELETE     { $$ = pnstrdup($1, 6); }
-    | DESC       { $$ = pnstrdup($1, 4); }
-    | DESCENDING { $$ = pnstrdup($1, 10); }
-    | DETACH     { $$ = pnstrdup($1, 6); }
-    | DISTINCT   { $$ = pnstrdup($1, 8); }
-    | ELSE       { $$ = pnstrdup($1, 4); }
-    | ENDS       { $$ = pnstrdup($1, 4); }
-    | EXISTS     { $$ = pnstrdup($1, 6); }
-    | EXPLAIN    { $$ = pnstrdup($1, 7); }
-    | IN         { $$ = pnstrdup($1, 2); }
-    | IS         { $$ = pnstrdup($1, 2); }
-    | LIMIT      { $$ = pnstrdup($1, 6); }
-    | MATCH      { $$ = pnstrdup($1, 6); }
-    | MERGE      { $$ = pnstrdup($1, 6); }
-    | NOT        { $$ = pnstrdup($1, 3); }
-    | OPERATOR   { $$ = pnstrdup($1, 8); }
-    | OPTIONAL   { $$ = pnstrdup($1, 8); }
-    | OR         { $$ = pnstrdup($1, 2); }
-    | ORDER      { $$ = pnstrdup($1, 5); }
-    | REMOVE     { $$ = pnstrdup($1, 6); }
-    | RETURN     { $$ = pnstrdup($1, 6); }
-    | SET        { $$ = pnstrdup($1, 3); }
-    | SKIP       { $$ = pnstrdup($1, 4); }
-    | STARTS     { $$ = pnstrdup($1, 6); }
-    | THEN       { $$ = pnstrdup($1, 4); }
-    | UNION      { $$ = pnstrdup($1, 5); }
-    | WHEN       { $$ = pnstrdup($1, 4); }
-    | VERBOSE    { $$ = pnstrdup($1, 7); }
-    | WHERE      { $$ = pnstrdup($1, 5); }
-    | WITH       { $$ = pnstrdup($1, 4); }
-    | XOR        { $$ = pnstrdup($1, 3); }
-    | YIELD      { $$ = pnstrdup($1, 5); }
+    ALL          { $$ = KEYWORD_STRDUP($1); }
+    | ANALYZE    { $$ = KEYWORD_STRDUP($1); }
+    | AND        { $$ = KEYWORD_STRDUP($1); }
+    | AS         { $$ = KEYWORD_STRDUP($1); }
+    | ASC        { $$ = KEYWORD_STRDUP($1); }
+    | ASCENDING  { $$ = KEYWORD_STRDUP($1); }
+    | BY         { $$ = KEYWORD_STRDUP($1); }
+    | CALL       { $$ = KEYWORD_STRDUP($1); }
+    | CASE       { $$ = KEYWORD_STRDUP($1); }
+    | COALESCE   { $$ = KEYWORD_STRDUP($1); }
+    | CONTAINS   { $$ = KEYWORD_STRDUP($1); }
+    | COUNT      { $$ = KEYWORD_STRDUP($1); }
+    | CREATE     { $$ = KEYWORD_STRDUP($1); }
+    | DELETE     { $$ = KEYWORD_STRDUP($1); }
+    | DESC       { $$ = KEYWORD_STRDUP($1); }
+    | DESCENDING { $$ = KEYWORD_STRDUP($1); }
+    | DETACH     { $$ = KEYWORD_STRDUP($1); }
+    | DISTINCT   { $$ = KEYWORD_STRDUP($1); }
+    | ELSE       { $$ = KEYWORD_STRDUP($1); }
+    | ENDS       { $$ = KEYWORD_STRDUP($1); }
+    | EXISTS     { $$ = KEYWORD_STRDUP($1); }
+    | EXPLAIN    { $$ = KEYWORD_STRDUP($1); }
+    | IN         { $$ = KEYWORD_STRDUP($1); }
+    | IS         { $$ = KEYWORD_STRDUP($1); }
+    | LIMIT      { $$ = KEYWORD_STRDUP($1); }
+    | MATCH      { $$ = KEYWORD_STRDUP($1); }
+    | MERGE      { $$ = KEYWORD_STRDUP($1); }
+    | NOT        { $$ = KEYWORD_STRDUP($1); }
+    | OPERATOR   { $$ = KEYWORD_STRDUP($1); }
+    | OPTIONAL   { $$ = KEYWORD_STRDUP($1); }
+    | OR         { $$ = KEYWORD_STRDUP($1); }
+    | ORDER      { $$ = KEYWORD_STRDUP($1); }
+    | REMOVE     { $$ = KEYWORD_STRDUP($1); }
+    | RETURN     { $$ = KEYWORD_STRDUP($1); }
+    | SET        { $$ = KEYWORD_STRDUP($1); }
+    | SKIP       { $$ = KEYWORD_STRDUP($1); }
+    | STARTS     { $$ = KEYWORD_STRDUP($1); }
+    | THEN       { $$ = KEYWORD_STRDUP($1); }
+    | UNION      { $$ = KEYWORD_STRDUP($1); }
+    | WHEN       { $$ = KEYWORD_STRDUP($1); }
+    | VERBOSE    { $$ = KEYWORD_STRDUP($1); }
+    | WHERE      { $$ = KEYWORD_STRDUP($1); }
+    | WITH       { $$ = KEYWORD_STRDUP($1); }
+    | XOR        { $$ = KEYWORD_STRDUP($1); }
+    | YIELD      { $$ = KEYWORD_STRDUP($1); }
     ;
 
 conflicted_keywords:
-    END_P     { $$ = pnstrdup($1, 5); }
-    | FALSE_P { $$ = pnstrdup($1, 7); }
-    | NULL_P  { $$ = pnstrdup($1, 6); }
-    | TRUE_P  { $$ = pnstrdup($1, 6); }
+    END_P     { $$ = KEYWORD_STRDUP($1); }
+    | FALSE_P { $$ = KEYWORD_STRDUP($1); }
+    | NULL_P  { $$ = KEYWORD_STRDUP($1); }
+    | TRUE_P  { $$ = KEYWORD_STRDUP($1); }
     ;
 
 %%
@@ -3384,7 +3304,7 @@ static Node *build_list_comprehension_node(Node *var, Node *expr,
 
     /*
      * Build an ARRAY sublink and attach list_comp as sub-select,
-     * it will be transformed in to query tree by us and reattached for 
+     * it will be transformed in to query tree by us and reattached for
      * pg to process.
      */
     sub = makeNode(SubLink);
@@ -3396,3 +3316,60 @@ static Node *build_list_comprehension_node(Node *var, Node *expr,
 
     return (Node *) node_to_agtype((Node *)sub, "agtype[]", location);
 }
+
+/* Helper function to create an ExplainStmt node */
+static ExplainStmt *make_explain_stmt(List *options)
+{
+    ExplainStmt *estmt = makeNode(ExplainStmt);
+    estmt->query = NULL;
+    estmt->options = options;
+    return estmt;
+}
+
+/* Helper function to validate that return items are properly aliased */
+static void validate_return_item_aliases(List *items, ag_scanner_t scanner)
+{
+    ListCell *li;
+
+    foreach(li, items)
+    {
+        ResTarget *item = lfirst(li);
+
+        /* variable does not have to be aliased */
+        if (IsA(item->val, ColumnRef) || item->name)
+            continue;
+
+        ereport(ERROR,
+                (errcode(ERRCODE_SYNTAX_ERROR),
+                 errmsg("expression item must be aliased"),
+                 errhint("Items can be aliased by using AS."),
+                 ag_scanner_errposition(item->location, scanner)));
+    }
+}
+
+/* Helper function to create a default return node (RETURN *) */
+static cypher_return *make_default_return_node(int location)
+{
+    ColumnRef *cr;
+    ResTarget *rt;
+    cypher_return *n;
+
+    cr = makeNode(ColumnRef);
+    cr->fields = list_make1(makeNode(A_Star));
+    cr->location = location;
+
+    rt = makeNode(ResTarget);
+    rt->name = NULL;
+    rt->indirection = NIL;
+    rt->val = (Node *)cr;
+    rt->location = location;
+
+    n = make_ag_node(cypher_return);
+    n->distinct = false;
+    n->items = list_make1((Node *)rt);
+    n->order_by = NULL;
+    n->skip = NULL;
+    n->limit = NULL;
+
+    return n;
+}
diff --git a/src/backend/utils/adt/age_global_graph.c b/src/backend/utils/adt/age_global_graph.c
index 6f30060a..c34e51ee 100644
--- a/src/backend/utils/adt/age_global_graph.c
+++ b/src/backend/utils/adt/age_global_graph.c
@@ -1237,12 +1237,10 @@ Datum age_delete_global_graphs(PG_FUNCTION_ARGS)
     {
         char *graph_name = NULL;
 
-        graph_name = strndup(agtv_temp->val.string.val,
-                             agtv_temp->val.string.len);
+        graph_name = pnstrdup(agtv_temp->val.string.val,
+                              agtv_temp->val.string.len);
 
         success = delete_specific_GRAPH_global_contexts(graph_name);
-
-        free(graph_name);
     }
     else
     {
diff --git a/src/backend/utils/adt/age_vle.c b/src/backend/utils/adt/age_vle.c
index f0adab2e..f9e4c70b 100644
--- a/src/backend/utils/adt/age_vle.c
+++ b/src/backend/utils/adt/age_vle.c
@@ -2427,6 +2427,55 @@ Datum age_build_vle_match_edge(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
 }
 
+PG_FUNCTION_INFO_V1(_ag_enforce_edge_uniqueness2);
+
+Datum _ag_enforce_edge_uniqueness2(PG_FUNCTION_ARGS)
+{
+    graphid gid1 = AG_GETARG_GRAPHID(0);
+    graphid gid2 = AG_GETARG_GRAPHID(1);
+
+    if (gid1 == gid2)
+    {
+        PG_RETURN_BOOL(false);
+    }
+
+    PG_RETURN_BOOL(true);
+}
+
+PG_FUNCTION_INFO_V1(_ag_enforce_edge_uniqueness3);
+
+Datum _ag_enforce_edge_uniqueness3(PG_FUNCTION_ARGS)
+{
+    graphid gid1 = AG_GETARG_GRAPHID(0);
+    graphid gid2 = AG_GETARG_GRAPHID(1);
+    graphid gid3 = AG_GETARG_GRAPHID(2);
+
+    if (gid1 == gid2 || gid1 == gid3 || gid2 == gid3)
+    {
+        PG_RETURN_BOOL(false);
+    }
+
+    PG_RETURN_BOOL(true);
+}
+
+PG_FUNCTION_INFO_V1(_ag_enforce_edge_uniqueness4);
+
+Datum _ag_enforce_edge_uniqueness4(PG_FUNCTION_ARGS)
+{
+    graphid gid1 = AG_GETARG_GRAPHID(0);
+    graphid gid2 = AG_GETARG_GRAPHID(1);
+    graphid gid3 = AG_GETARG_GRAPHID(2);
+    graphid gid4 = AG_GETARG_GRAPHID(3);
+
+    if (gid1 == gid2 || gid1 == gid3 || gid1 == gid4 ||
+        gid2 == gid3 || gid2 == gid4 || gid3 == gid4)
+    {
+        PG_RETURN_BOOL(false);
+    }
+
+    PG_RETURN_BOOL(true);
+}
+
 /*
  * This function checks the edges in a MATCH clause to see if they are unique or
  * not. Filters out all the paths where the edge uniques rules are not met.
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index be838cbd..02fc3221 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -181,6 +181,17 @@ static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo);
 agtype_value *agtype_composite_to_agtype_value_binary(agtype *a);
 static agtype_value *tostring_helper(Datum arg, Oid type, char *msghdr);
 
+
+void *repalloc_check(void *ptr, size_t len)
+{
+   if (ptr != NULL)
+   {
+       return repalloc(ptr, len);
+   }
+
+   return palloc(len);
+}
+
 /*
  * Due to how pfree can be implemented, it may not check for a passed NULL. This
  * wrapper does just that, it will only call pfree is the pointer passed is not
@@ -5580,7 +5591,7 @@ static char *get_label_name(const char *graph_name, graphid element_graphid)
     result = NameStr(*DatumGetName(heap_getattr(tuple, Anum_ag_label_name,
                                                 tupdesc, &column_is_null)));
     /* duplicate it */
-    result = strdup(result);
+    result = pstrdup(result);
 
     /* end the scan and close the relation */
     systable_endscan(scan_desc);
@@ -5673,8 +5684,8 @@ Datum age_startnode(PG_FUNCTION_ARGS)
     Assert(AGT_ROOT_IS_SCALAR(agt_arg));
     agtv_object = get_ith_agtype_value_from_container(&agt_arg->root, 0);
     Assert(agtv_object->type == AGTV_STRING);
-    graph_name = strndup(agtv_object->val.string.val,
-                         agtv_object->val.string.len);
+    graph_name = pnstrdup(agtv_object->val.string.val,
+                          agtv_object->val.string.len);
 
     /* get the edge */
     agt_arg = AG_GET_ARG_AGTYPE_P(1);
@@ -5708,8 +5719,6 @@ Datum age_startnode(PG_FUNCTION_ARGS)
 
     result = get_vertex(graph_name, label_name, start_id);
 
-    free(label_name);
-
     return result;
 }
 
@@ -5738,8 +5747,8 @@ Datum age_endnode(PG_FUNCTION_ARGS)
     Assert(AGT_ROOT_IS_SCALAR(agt_arg));
     agtv_object = get_ith_agtype_value_from_container(&agt_arg->root, 0);
     Assert(agtv_object->type == AGTV_STRING);
-    graph_name = strndup(agtv_object->val.string.val,
-                         agtv_object->val.string.len);
+    graph_name = pnstrdup(agtv_object->val.string.val,
+                          agtv_object->val.string.len);
 
     /* get the edge */
     agt_arg = AG_GET_ARG_AGTYPE_P(1);
@@ -5773,8 +5782,6 @@ Datum age_endnode(PG_FUNCTION_ARGS)
 
     result = get_vertex(graph_name, label_name, end_id);
 
-    free(label_name);
-
     return result;
 }
 
@@ -6401,11 +6408,10 @@ Datum age_tofloat(PG_FUNCTION_ARGS)
                 NumericGetDatum(agtv_value->val.numeric)));
         else if (agtv_value->type == AGTV_STRING)
         {
-            string = strndup(agtv_value->val.string.val,
-                             agtv_value->val.string.len);
+            string = pnstrdup(agtv_value->val.string.val,
+                              agtv_value->val.string.len);
             result = float8in_internal_null(string, NULL, "double precision",
                                             string, &is_valid);
-            free(string);
             if (!is_valid)
                 PG_RETURN_NULL();
         }
@@ -6703,8 +6709,8 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
         {
             char *endptr;
             /* we need a null terminated cstring */
-            string = strndup(agtv_value->val.string.val,
-                             agtv_value->val.string.len);
+            string = pnstrdup(agtv_value->val.string.val,
+                              agtv_value->val.string.len);
             /* convert it if it is a regular integer string */
             result = strtoi64(string, &endptr, 10);
 
@@ -6718,7 +6724,6 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
 
                 f = float8in_internal_null(string, NULL, "double precision",
                                            string, &is_valid);
-                free(string);
                 /*
                  * If the conversions failed or it's a special float value,
                  * return null.
@@ -6731,10 +6736,6 @@ Datum age_tointeger(PG_FUNCTION_ARGS)
 
                 result = (int64) f;
             }
-            else
-            {
-                free(string);
-            }
         }
         else
         {
diff --git a/src/backend/utils/adt/agtype_ops.c b/src/backend/utils/adt/agtype_ops.c
index c6c13aad..d831447b 100644
--- a/src/backend/utils/adt/agtype_ops.c
+++ b/src/backend/utils/adt/agtype_ops.c
@@ -68,7 +68,7 @@ static char *get_string_from_agtype_value(agtype_value *agtv, int *length)
     {
     case AGTV_INTEGER:
         number = DirectFunctionCall1(int8out,
-                                     Int8GetDatum(agtv->val.int_value));
+                                     Int64GetDatum(agtv->val.int_value));
         string = DatumGetCString(number);
         *length = strlen(string);
         return string;
@@ -115,7 +115,7 @@ Datum get_numeric_datum_from_agtype_value(agtype_value *agtv)
     {
     case AGTV_INTEGER:
         return DirectFunctionCall1(int8_numeric,
-                                   Int8GetDatum(agtv->val.int_value));
+                                   Int64GetDatum(agtv->val.int_value));
     case AGTV_FLOAT:
         return DirectFunctionCall1(float8_numeric,
                                    Float8GetDatum(agtv->val.float_value));
diff --git a/src/backend/utils/adt/agtype_parser.c b/src/backend/utils/adt/agtype_parser.c
index c485cb92..40fc8d8c 100644
--- a/src/backend/utils/adt/agtype_parser.c
+++ b/src/backend/utils/adt/agtype_parser.c
@@ -74,11 +74,9 @@ static void parse_object(agtype_lex_context *lex, agtype_sem_action *sem);
 static void parse_array_element(agtype_lex_context *lex,
                                 agtype_sem_action *sem);
 static void parse_array(agtype_lex_context *lex, agtype_sem_action *sem);
-static void report_parse_error(agtype_parse_context ctx,
-                               agtype_lex_context *lex)
-    pg_attribute_noreturn();
-static void report_invalid_token(agtype_lex_context *lex)
-    pg_attribute_noreturn();
+static pg_noreturn void report_parse_error(agtype_parse_context ctx,
+                               agtype_lex_context *lex);
+static pg_noreturn void report_invalid_token(agtype_lex_context *lex);
 static int report_agtype_context(agtype_lex_context *lex);
 static char *extract_mb_char(char *s);
 
diff --git a/src/backend/utils/cache/ag_cache.c b/src/backend/utils/cache/ag_cache.c
index e3c4d079..493ffcfa 100644
--- a/src/backend/utils/cache/ag_cache.c
+++ b/src/backend/utils/cache/ag_cache.c
@@ -286,52 +286,34 @@ static void invalidate_graph_caches(Datum arg, int cache_id, uint32 hash_value)
 
 static void flush_graph_name_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, graph_name_cache_hash);
-    for (;;)
+    /*
+     * If the graph_name_cache exists, destroy it. This will avoid any
+     * potential corruption issues.
+     */
+    if (graph_name_cache_hash)
     {
-        graph_name_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-        removed = hash_search(graph_name_cache_hash, &entry->name, HASH_REMOVE,
-                              NULL);
-        if (!removed)
-        {
-            ereport(ERROR, (errmsg_internal("graph (name) cache corrupted")));
-        }
+        hash_destroy(graph_name_cache_hash);
+        graph_name_cache_hash = NULL;
     }
+
+    /* recreate the graph_name_cache */
+    create_graph_name_cache();
 }
 
 static void flush_graph_namespace_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, graph_namespace_cache_hash);
-    for (;;)
+    /*
+     * If the graph_namespace_cache exists, destroy it. This will avoid any
+     * potential corruption issues.
+     */
+    if (graph_namespace_cache_hash)
     {
-        graph_namespace_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-
-        removed = hash_search(graph_namespace_cache_hash, &entry->namespace,
-                              HASH_REMOVE, NULL);
-        if (!removed)
-        {
-            ereport(ERROR,
-                    (errmsg_internal("graph (namespace) cache corrupted")));
-        }
+        hash_destroy(graph_namespace_cache_hash);
+        graph_namespace_cache_hash = NULL;
     }
+
+    /* recreate the graph_namespace_cache */
+    create_graph_namespace_cache();
 }
 
 graph_cache_data *search_graph_name_cache(const char *name)
@@ -664,27 +646,18 @@ static void invalidate_label_name_graph_cache(Oid relid)
 
 static void flush_label_name_graph_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, label_name_graph_cache_hash);
-    for (;;)
+    /*
+     * If the label_name_graph_cache exists, destroy it. This will avoid any
+     * potential corruption issues.
+     */
+    if (label_name_graph_cache_hash)
     {
-        label_name_graph_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-        removed = hash_search(label_name_graph_cache_hash, &entry->key,
-                              HASH_REMOVE, NULL);
-        if (!removed)
-        {
-            ereport(ERROR,
-                    (errmsg_internal("label (name, graph) cache corrupted")));
-        }
+        hash_destroy(label_name_graph_cache_hash);
+        label_name_graph_cache_hash = NULL;
     }
+
+    /* recreate the label_name_graph_cache */
+    create_label_name_graph_cache();
 }
 
 static void invalidate_label_graph_oid_cache(Oid relid)
@@ -722,27 +695,18 @@ static void invalidate_label_graph_oid_cache(Oid relid)
 
 static void flush_label_graph_oid_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, label_graph_oid_cache_hash);
-    for (;;)
+    /*
+     * If the label_graph_oid_cache exists, destroy it. This will avoid any
+     * potential corruption issues.
+     */
+    if (label_graph_oid_cache_hash)
     {
-        label_graph_oid_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-        removed = hash_search(label_graph_oid_cache_hash, &entry->key,
-                              HASH_REMOVE, NULL);
-        if (!removed)
-        {
-            ereport(ERROR,
-                    (errmsg_internal("label (graph, id) cache corrupted")));
-        }
+        hash_destroy(label_graph_oid_cache_hash);
+        label_graph_oid_cache_hash = NULL;
     }
+
+    /* recreate the label_graph_oid_cache */
+    create_label_graph_oid_cache();
 }
 
 static void invalidate_label_relation_cache(Oid relid)
@@ -765,27 +729,18 @@ static void invalidate_label_relation_cache(Oid relid)
 
 static void flush_label_relation_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, label_relation_cache_hash);
-    for (;;)
+    /*
+     * If the label_relation_cache exists, destroy it. This will avoid any
+     * potential corruption issues.
+     */
+    if (label_relation_cache_hash)
     {
-        label_relation_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-        removed = hash_search(label_relation_cache_hash, &entry->relation,
-                              HASH_REMOVE, NULL);
-        if (!removed)
-        {
-            ereport(ERROR,
-                    (errmsg_internal("label (relation) cache corrupted")));
-        }
+        hash_destroy(label_relation_cache_hash);
+        label_relation_cache_hash = NULL;
     }
+
+    /* recreate the label_relation_cache */
+    create_label_relation_cache();
 }
 
 static void invalidate_label_seq_name_graph_cache(Oid relid)
@@ -823,27 +778,18 @@ static void invalidate_label_seq_name_graph_cache(Oid relid)
 
 static void flush_label_seq_name_graph_cache(void)
 {
-    HASH_SEQ_STATUS hash_seq;
-
-    hash_seq_init(&hash_seq, label_seq_name_graph_cache_hash);
-    for (;;)
+    /*
+     * If the label_seq_name_graph_cache exists, destroy it. This will
+     * avoid any potential corruption issues by deleting entries.
+     */
+    if (label_seq_name_graph_cache_hash)
     {
-        label_seq_name_graph_cache_entry *entry;
-        void *removed;
-
-        entry = hash_seq_search(&hash_seq);
-        if (!entry)
-        {
-            break;
-        }
-        removed = hash_search(label_seq_name_graph_cache_hash, &entry->key,
-                              HASH_REMOVE, NULL);
-        if (!removed)
-        {
-            ereport(ERROR,
-                    (errmsg_internal("label (seq_name, graph) cache corrupted")));
-        }
+        hash_destroy(label_seq_name_graph_cache_hash);
+        label_seq_name_graph_cache_hash = NULL;
     }
+
+    /* recreate the label_seq_name_graph_cache */
+    create_label_seq_name_graph_cache();
 }
 
 label_cache_data *search_label_name_graph_cache(const char *name, Oid graph)
diff --git a/src/backend/utils/load/ag_load_edges.c b/src/backend/utils/load/ag_load_edges.c
index 30dc4761..931c6e0d 100644
--- a/src/backend/utils/load/ag_load_edges.c
+++ b/src/backend/utils/load/ag_load_edges.c
@@ -22,11 +22,6 @@
 #include "utils/load/ag_load_edges.h"
 #include "utils/load/csv.h"
 
-void init_edge_batch_insert(batch_insert_state **batch_state,
-                            char *label_name, Oid graph_oid);
-void finish_edge_batch_insert(batch_insert_state **batch_state,
-                              char *label_name, Oid graph_oid);
-
 void edge_field_cb(void *field, size_t field_len, void *data)
 {
 
@@ -41,8 +36,8 @@ void edge_field_cb(void *field, size_t field_len, void *data)
     if (cr->cur_field == cr->alloc)
     {
         cr->alloc *= 2;
-        cr->fields = realloc(cr->fields, sizeof(char *) * cr->alloc);
-        cr->fields_len = realloc(cr->header, sizeof(size_t *) * cr->alloc);
+        cr->fields = repalloc_check(cr->fields, sizeof(char *) * cr->alloc);
+        cr->fields_len = repalloc_check(cr->header, sizeof(size_t *) * cr->alloc);
         if (cr->fields == NULL)
         {
             cr->error = 1;
@@ -53,7 +48,7 @@ void edge_field_cb(void *field, size_t field_len, void *data)
     }
     cr->fields_len[cr->cur_field] = field_len;
     cr->curr_row_length += field_len;
-    cr->fields[cr->cur_field] = strndup((char*)field, field_len);
+    cr->fields[cr->cur_field] = pnstrdup((char*)field, field_len);
     cr->cur_field += 1;
 }
 
@@ -83,13 +78,13 @@ void edge_row_cb(int delim __attribute__((unused)), void *data)
     {
         cr->header_num = cr->cur_field;
         cr->header_row_length = cr->curr_row_length;
-        cr->header_len = (size_t* )malloc(sizeof(size_t *) * cr->cur_field);
-        cr->header = malloc((sizeof (char*) * cr->cur_field));
+        cr->header_len = (size_t* )palloc(sizeof(size_t *) * cr->cur_field);
+        cr->header = palloc((sizeof (char*) * cr->cur_field));
 
         for (i = 0; i<cr->cur_field; i++)
         {
             cr->header_len[i] = cr->fields_len[i];
-            cr->header[i] = strndup(cr->fields[i], cr->header_len[i]);
+            cr->header[i] = pnstrdup(cr->fields[i], cr->header_len[i]);
         }
     }
     else
@@ -131,14 +126,14 @@ void edge_row_cb(int delim __attribute__((unused)), void *data)
         if (batch_state->num_tuples >= batch_state->max_tuples)
         {
             /* Insert the batch when it is full (i.e. BATCH_SIZE) */
-            insert_batch(batch_state, cr->label_name, cr->graph_oid);
+            insert_batch(batch_state);
             batch_state->num_tuples = 0;
         }
     }
 
     for (i = 0; i < n_fields; ++i)
     {
-        free(cr->fields[i]);
+        pfree_if_not_null(cr->fields[i]);
     }
 
     if (cr->error)
@@ -197,6 +192,10 @@ int create_edges_from_csv_file(char *file_path,
                 (errmsg("Failed to initialize csv parser\n")));
     }
 
+    p.malloc_func = palloc;
+    p.realloc_func = repalloc_check;
+    p.free_func = pfree_if_not_null;
+
     csv_set_space_func(&p, is_space);
     csv_set_term_func(&p, is_term);
 
@@ -207,109 +206,52 @@ int create_edges_from_csv_file(char *file_path,
                 (errmsg("Failed to open %s\n", file_path)));
     }
 
-    label_seq_name = get_label_seq_relation_name(label_name);
-
-    memset((void*)&cr, 0, sizeof(csv_edge_reader));
-    cr.alloc = 128;
-    cr.fields = malloc(sizeof(char *) * cr.alloc);
-    cr.fields_len = malloc(sizeof(size_t *) * cr.alloc);
-    cr.header_row_length = 0;
-    cr.curr_row_length = 0;
-    cr.graph_name = graph_name;
-    cr.graph_oid = graph_oid;
-    cr.label_name = label_name;
-    cr.label_id = label_id;
-    cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid);
-    cr.load_as_agtype = load_as_agtype;
-
-    /* Initialize the batch insert state */
-    init_edge_batch_insert(&cr.batch_state, label_name, graph_oid);
-
-    while ((bytes_read=fread(buf, 1, 1024, fp)) > 0)
+    PG_TRY();
     {
-        if (csv_parse(&p, buf, bytes_read, edge_field_cb,
-                      edge_row_cb, &cr) != bytes_read)
+        label_seq_name = get_label_seq_relation_name(label_name);
+
+        memset((void*)&cr, 0, sizeof(csv_edge_reader));
+        cr.alloc = 128;
+        cr.fields = palloc(sizeof(char *) * cr.alloc);
+        cr.fields_len = palloc(sizeof(size_t *) * cr.alloc);
+        cr.header_row_length = 0;
+        cr.curr_row_length = 0;
+        cr.graph_name = graph_name;
+        cr.graph_oid = graph_oid;
+        cr.label_name = label_name;
+        cr.label_id = label_id;
+        cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid);
+        cr.load_as_agtype = load_as_agtype;
+
+        /* Initialize the batch insert state */
+        init_batch_insert(&cr.batch_state, label_name, graph_oid);
+
+        while ((bytes_read=fread(buf, 1, 1024, fp)) > 0)
         {
-            ereport(ERROR, (errmsg("Error while parsing file: %s\n",
-                                   csv_strerror(csv_error(&p)))));
+            if (csv_parse(&p, buf, bytes_read, edge_field_cb,
+                        edge_row_cb, &cr) != bytes_read)
+            {
+                ereport(ERROR, (errmsg("Error while parsing file: %s\n",
+                                    csv_strerror(csv_error(&p)))));
+            }
         }
-    }
-
-    csv_fini(&p, edge_field_cb, edge_row_cb, &cr);
-
-    /* Finish any remaining batch inserts */
-    finish_edge_batch_insert(&cr.batch_state, label_name, graph_oid);
-
-    if (ferror(fp))
-    {
-        ereport(ERROR, (errmsg("Error while reading file %s\n", file_path)));
-    }
-
-    fclose(fp);
-
-    free(cr.fields);
-    csv_free(&p);
-    return EXIT_SUCCESS;
-}
-
-/*
- * Initialize the batch insert state for edges.
- */
-void init_edge_batch_insert(batch_insert_state **batch_state,
-                            char *label_name, Oid graph_oid)
-{
-    Relation relation;
-    int i;
 
-    // Open a temporary relation to get the tuple descriptor
-    relation = table_open(get_label_relation(label_name, graph_oid), AccessShareLock);
+        csv_fini(&p, edge_field_cb, edge_row_cb, &cr);
 
-    // Initialize the batch insert state
-    *batch_state = (batch_insert_state *) palloc0(sizeof(batch_insert_state));
-    (*batch_state)->max_tuples = BATCH_SIZE;
-    (*batch_state)->slots = palloc(sizeof(TupleTableSlot *) * BATCH_SIZE);
-    (*batch_state)->num_tuples = 0;
+        /* Finish any remaining batch inserts */
+        finish_batch_insert(&cr.batch_state);
 
-    // Create slots
-    for (i = 0; i < BATCH_SIZE; i++)
-    {
-        (*batch_state)->slots[i] = MakeSingleTupleTableSlot(
-                                            RelationGetDescr(relation),
-                                            &TTSOpsHeapTuple);
-    }
-
-    table_close(relation, AccessShareLock);
-}
-
-/*
- * Finish the batch insert for edges. Insert the
- * remaining tuples in the batch state and clean up.
- */
-void finish_edge_batch_insert(batch_insert_state **batch_state,
-                              char *label_name, Oid graph_oid)
-{
-    int i;
-    Relation relation;
-
-    if ((*batch_state)->num_tuples > 0)
-    {
-        insert_batch(*batch_state, label_name, graph_oid);
-        (*batch_state)->num_tuples = 0;
+        if (ferror(fp))
+        {
+            ereport(ERROR, (errmsg("Error while reading file %s\n", file_path)));
+        }
     }
-
-    // Open a temporary relation to ensure resources are properly cleaned up
-    relation = table_open(get_label_relation(label_name, graph_oid), AccessShareLock);
-
-    // Free slots
-    for (i = 0; i < BATCH_SIZE; i++)
+    PG_FINALLY();
     {
-        ExecDropSingleTupleTableSlot((*batch_state)->slots[i]);
+        fclose(fp);
+        csv_free(&p);
     }
+    PG_END_TRY();
 
-    // Clean up batch state
-    pfree_if_not_null((*batch_state)->slots);
-    pfree_if_not_null(*batch_state);
-    *batch_state = NULL;
-
-    table_close(relation, AccessShareLock);
+    return EXIT_SUCCESS;
 }
diff --git a/src/backend/utils/load/ag_load_labels.c b/src/backend/utils/load/ag_load_labels.c
index 2ab22334..1e86bbda 100644
--- a/src/backend/utils/load/ag_load_labels.c
+++ b/src/backend/utils/load/ag_load_labels.c
@@ -24,18 +24,6 @@
 #include "utils/load/ag_load_labels.h"
 #include "utils/load/csv.h"
 
-static void setup_temp_table_for_vertex_ids(char *graph_name);
-static void insert_batch_in_temp_table(batch_insert_state *batch_state,
-                                       Oid graph_oid, Oid relid);
-static void init_vertex_batch_insert(batch_insert_state **batch_state,
-                                     char *label_name, Oid graph_oid,
-                                     Oid temp_table_relid);
-static void finish_vertex_batch_insert(batch_insert_state **batch_state,
-                                       char *label_name, Oid graph_oid,
-                                       Oid temp_table_relid);
-static void insert_vertex_batch(batch_insert_state *batch_state, char *label_name,
-                                Oid graph_oid, Oid temp_table_relid);
-
 void vertex_field_cb(void *field, size_t field_len, void *data)
 {
 
@@ -51,8 +39,8 @@ void vertex_field_cb(void *field, size_t field_len, void *data)
     if (cr->cur_field == cr->alloc)
     {
         cr->alloc *= 2;
-        cr->fields = realloc(cr->fields, sizeof(char *) * cr->alloc);
-        cr->fields_len = realloc(cr->header, sizeof(size_t *) * cr->alloc);
+        cr->fields = repalloc_check(cr->fields, sizeof(char *) * cr->alloc);
+        cr->fields_len = repalloc_check(cr->header, sizeof(size_t *) * cr->alloc);
         if (cr->fields == NULL)
         {
             cr->error = 1;
@@ -63,7 +51,7 @@ void vertex_field_cb(void *field, size_t field_len, void *data)
     }
     cr->fields_len[cr->cur_field] = field_len;
     cr->curr_row_length += field_len;
-    cr->fields[cr->cur_field] = strndup((char *) field, field_len);
+    cr->fields[cr->cur_field] = pnstrdup((char *) field, field_len);
     cr->cur_field += 1;
 }
 
@@ -75,7 +63,6 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
     graphid vertex_id;
     int64 entry_id;
     TupleTableSlot *slot;
-    TupleTableSlot *temp_id_slot;
 
     n_fields = cr->cur_field;
 
@@ -83,13 +70,13 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
     {
         cr->header_num = cr->cur_field;
         cr->header_row_length = cr->curr_row_length;
-        cr->header_len = (size_t* )malloc(sizeof(size_t *) * cr->cur_field);
-        cr->header = malloc((sizeof (char*) * cr->cur_field));
+        cr->header_len = (size_t* )palloc(sizeof(size_t *) * cr->cur_field);
+        cr->header = palloc((sizeof (char*) * cr->cur_field));
 
         for (i = 0; i<cr->cur_field; i++)
         {
             cr->header_len[i] = cr->fields_len[i];
-            cr->header[i] = strndup(cr->fields[i], cr->header_len[i]);
+            cr->header[i] = pnstrdup(cr->fields[i], cr->header_len[i]);
         }
     }
     else
@@ -114,11 +101,9 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
 
         /* Get the appropriate slot from the batch state */
         slot = batch_state->slots[batch_state->num_tuples];
-        temp_id_slot = batch_state->temp_id_slots[batch_state->num_tuples];
 
         /* Clear the slots contents */
         ExecClearTuple(slot);
-        ExecClearTuple(temp_id_slot);
 
         /* Fill the values in the slot */
         slot->tts_values[0] = GRAPHID_GET_DATUM(vertex_id);
@@ -129,27 +114,22 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
         slot->tts_isnull[0] = false;
         slot->tts_isnull[1] = false;
 
-        temp_id_slot->tts_values[0] = GRAPHID_GET_DATUM(vertex_id);
-        temp_id_slot->tts_isnull[0] = false;
-
         /* Make the slot as containing virtual tuple */
         ExecStoreVirtualTuple(slot);
-        ExecStoreVirtualTuple(temp_id_slot);
 
         batch_state->num_tuples++;
 
         if (batch_state->num_tuples >= batch_state->max_tuples)
         {
             /* Insert the batch when it is full (i.e. BATCH_SIZE) */
-            insert_vertex_batch(batch_state, cr->label_name, cr->graph_oid,
-                                cr->temp_table_relid);
+            insert_batch(batch_state);
             batch_state->num_tuples = 0;
         }
     }
 
     for (i = 0; i < n_fields; ++i)
     {
-        free(cr->fields[i]);
+        pfree_if_not_null(cr->fields[i]);
     }
 
     if (cr->error)
@@ -202,7 +182,6 @@ int create_labels_from_csv_file(char *file_path,
     unsigned char options = 0;
     csv_vertex_reader cr;
     char *label_seq_name;
-    Oid temp_table_relid;
 
     if (csv_init(&p, options) != 0)
     {
@@ -210,12 +189,9 @@ int create_labels_from_csv_file(char *file_path,
                 (errmsg("Failed to initialize csv parser\n")));
     }
 
-    temp_table_relid = RelnameGetRelid(GET_TEMP_VERTEX_ID_TABLE(graph_name));
-    if (!OidIsValid(temp_table_relid))
-    {
-        setup_temp_table_for_vertex_ids(graph_name);
-        temp_table_relid = RelnameGetRelid(GET_TEMP_VERTEX_ID_TABLE(graph_name));
-    }
+    p.malloc_func = palloc;
+    p.realloc_func = repalloc_check;
+    p.free_func = pfree_if_not_null;
 
     csv_set_space_func(&p, is_space);
     csv_set_term_func(&p, is_term);
@@ -227,241 +203,67 @@ int create_labels_from_csv_file(char *file_path,
                 (errmsg("Failed to open %s\n", file_path)));
     }
 
-    label_seq_name = get_label_seq_relation_name(label_name);
-
-    memset((void*)&cr, 0, sizeof(csv_vertex_reader));
-
-    cr.alloc = 2048;
-    cr.fields = malloc(sizeof(char *) * cr.alloc);
-    cr.fields_len = malloc(sizeof(size_t *) * cr.alloc);
-    cr.header_row_length = 0;
-    cr.curr_row_length = 0;
-    cr.graph_name = graph_name;
-    cr.graph_oid = graph_oid;
-    cr.label_name = label_name;
-    cr.label_id = label_id;
-    cr.id_field_exists = id_field_exists;
-    cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid);
-    cr.load_as_agtype = load_as_agtype;
-    cr.temp_table_relid = temp_table_relid;
-    
-    if (cr.id_field_exists)
+    PG_TRY();
     {
-        /*
-         * Set the curr_seq_num since we will need it to compare with
-         * incoming entry_id.
-         * 
-         * We cant use currval because it will error out if nextval was
-         * not called before in the session.
-         */
-        cr.curr_seq_num = nextval_internal(cr.label_seq_relid, true);
-    }
-
-    /* Initialize the batch insert state */
-    init_vertex_batch_insert(&cr.batch_state, label_name, graph_oid,
-                             cr.temp_table_relid);
-
-    while ((bytes_read=fread(buf, 1, 1024, fp)) > 0)
-    {
-        if (csv_parse(&p, buf, bytes_read, vertex_field_cb,
-                      vertex_row_cb, &cr) != bytes_read)
+        label_seq_name = get_label_seq_relation_name(label_name);
+
+        memset((void*)&cr, 0, sizeof(csv_vertex_reader));
+
+        cr.alloc = 2048;
+        cr.fields = palloc(sizeof(char *) * cr.alloc);
+        cr.fields_len = palloc(sizeof(size_t *) * cr.alloc);
+        cr.header_row_length = 0;
+        cr.curr_row_length = 0;
+        cr.graph_name = graph_name;
+        cr.graph_oid = graph_oid;
+        cr.label_name = label_name;
+        cr.label_id = label_id;
+        cr.id_field_exists = id_field_exists;
+        cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid);
+        cr.load_as_agtype = load_as_agtype;
+            
+        if (cr.id_field_exists)
         {
-            ereport(ERROR, (errmsg("Error while parsing file: %s\n",
-                                   csv_strerror(csv_error(&p)))));
+            /*
+            * Set the curr_seq_num since we will need it to compare with
+            * incoming entry_id.
+            * 
+            * We cant use currval because it will error out if nextval was
+            * not called before in the session.
+            */
+            cr.curr_seq_num = nextval_internal(cr.label_seq_relid, true);
         }
-    }
-
-    csv_fini(&p, vertex_field_cb, vertex_row_cb, &cr);
-
-    /* Finish any remaining batch inserts */
-    finish_vertex_batch_insert(&cr.batch_state, label_name, graph_oid,
-                               cr.temp_table_relid);
-
-    if (ferror(fp))
-    {
-        ereport(ERROR, (errmsg("Error while reading file %s\n",
-                               file_path)));
-    }
-
-    fclose(fp);
-
-    free(cr.fields);
-    csv_free(&p);
-    return EXIT_SUCCESS;
-}
-
-static void insert_vertex_batch(batch_insert_state *batch_state, char *label_name,
-                                Oid graph_oid, Oid temp_table_relid)
-{
-    insert_batch_in_temp_table(batch_state, graph_oid, temp_table_relid);
-    insert_batch(batch_state, label_name, graph_oid);
-}
-
-/*
- * Create and populate a temporary table with vertex ids that are already
- * present in the graph. This table will be used to check if the new vertex
- * id generated by loader is a duplicate.
- * Unique index is created to enforce uniqueness of the ids.
- * 
- * We dont need this for loading edges since the ids are generated using
- * sequence and are unique.
- */ 
-static void setup_temp_table_for_vertex_ids(char *graph_name)
-{
-    char *create_as_query;
-    char *index_query;
-
-    create_as_query = psprintf("CREATE TEMP TABLE IF NOT EXISTS %s AS "
-                               "SELECT DISTINCT id FROM \"%s\".%s",
-                                GET_TEMP_VERTEX_ID_TABLE(graph_name), graph_name,
-                                AG_DEFAULT_LABEL_VERTEX);
-
-    index_query = psprintf("CREATE UNIQUE INDEX ON %s (id)",
-                           GET_TEMP_VERTEX_ID_TABLE(graph_name));
-    SPI_connect();
-    SPI_execute(create_as_query, false, 0);
-    SPI_execute(index_query, false, 0);
-
-    SPI_finish();
-}
-
-/*
- * Inserts batch of tuples into the temporary table.
- * This function also updates the index to check for
- * uniqueness of the ids.
- */
-static void insert_batch_in_temp_table(batch_insert_state *batch_state,
-                                       Oid graph_oid, Oid relid)
-{
-    int i;
-    EState *estate;
-    ResultRelInfo *resultRelInfo;
-    Relation rel;
-    List *result;
-
-    rel = table_open(relid, RowExclusiveLock);
-
-    /* Initialize executor state */
-    estate = CreateExecutorState();
 
-    /* Initialize result relation information */
-    resultRelInfo = makeNode(ResultRelInfo);
-    InitResultRelInfo(resultRelInfo, rel, 1, NULL, estate->es_instrument);
-    estate->es_result_relations = &resultRelInfo;
+        /* Initialize the batch insert state */
+        init_batch_insert(&cr.batch_state, label_name, graph_oid);
 
-    /* Open the indices */
-    ExecOpenIndices(resultRelInfo, false);
-
-    /* Insert the batch into the temporary table */
-    heap_multi_insert(rel, batch_state->temp_id_slots, batch_state->num_tuples,
-                      GetCurrentCommandId(true), 0, NULL);
-
-    for (i = 0; i < batch_state->num_tuples; i++)
-    {
-        result = ExecInsertIndexTuples(resultRelInfo, batch_state->temp_id_slots[i],
-                                       estate, false, true, NULL, NIL, false);
-        /* Check if the unique cnstraint is violated */
-        if (list_length(result) != 0)
+        while ((bytes_read=fread(buf, 1, 1024, fp)) > 0)
         {
-            Datum id;
-            bool isnull;
-
-            id = slot_getattr(batch_state->temp_id_slots[i], 1, &isnull);
-            ereport(ERROR, (errmsg("Cannot insert duplicate vertex id: %ld",
-                                    DATUM_GET_GRAPHID(id)),
-                            errhint("Entry id %ld is already used",
-                                    get_graphid_entry_id(id))));
+            if (csv_parse(&p, buf, bytes_read, vertex_field_cb,
+                        vertex_row_cb, &cr) != bytes_read)
+            {
+                ereport(ERROR, (errmsg("Error while parsing file: %s\n",
+                                    csv_strerror(csv_error(&p)))));
+            }
         }
-    }
-    /* Clean up and close the indices */
-    ExecCloseIndices(resultRelInfo);
-
-    FreeExecutorState(estate);
-    table_close(rel, RowExclusiveLock);
-
-    CommandCounterIncrement();
-}
-
-/*
- * Initialize the batch insert state for vertices.
- */
-static void init_vertex_batch_insert(batch_insert_state **batch_state,
-                                     char *label_name, Oid graph_oid,
-                                     Oid temp_table_relid)
-{
-    Relation relation;
-    Oid relid;
-
-    Relation temp_table_relation;
-    int i;
-
-    /* Open a temporary relation to get the tuple descriptor */
-    relid = get_label_relation(label_name, graph_oid);
-    relation = table_open(relid, AccessShareLock);
-
-    temp_table_relation = table_open(temp_table_relid, AccessShareLock);
-
-    /* Initialize the batch insert state */
-    *batch_state = (batch_insert_state *) palloc0(sizeof(batch_insert_state));
-    (*batch_state)->max_tuples = BATCH_SIZE;
-    (*batch_state)->slots = palloc(sizeof(TupleTableSlot *) * BATCH_SIZE);
-    (*batch_state)->temp_id_slots = palloc(sizeof(TupleTableSlot *) * BATCH_SIZE);
-    (*batch_state)->num_tuples = 0;
 
-    /* Create slots */
-    for (i = 0; i < BATCH_SIZE; i++)
-    {
-        (*batch_state)->slots[i] = MakeSingleTupleTableSlot(
-                                            RelationGetDescr(relation),
-                                            &TTSOpsHeapTuple);
-        (*batch_state)->temp_id_slots[i] = MakeSingleTupleTableSlot(
-                                        RelationGetDescr(temp_table_relation),
-                                        &TTSOpsHeapTuple);
-    }
+        csv_fini(&p, vertex_field_cb, vertex_row_cb, &cr);
 
-    table_close(relation, AccessShareLock);
-    table_close(temp_table_relation, AccessShareLock);
-}
+        /* Finish any remaining batch inserts */
+        finish_batch_insert(&cr.batch_state);
 
-/*
- * Finish the batch insert for vertices. Insert the
- * remaining tuples in the batch state and clean up.
- */
-static void finish_vertex_batch_insert(batch_insert_state **batch_state,
-                                       char *label_name, Oid graph_oid,
-                                       Oid temp_table_relid)
-{
-    Relation relation;
-    Oid relid;
-
-    Relation temp_table_relation;
-    int i;
-
-    if ((*batch_state)->num_tuples > 0)
-    {
-        insert_vertex_batch(*batch_state, label_name, graph_oid, temp_table_relid);
-        (*batch_state)->num_tuples = 0;
+        if (ferror(fp))
+        {
+            ereport(ERROR, (errmsg("Error while reading file %s\n",
+                                file_path)));
+        }
     }
-
-    /* Open a temporary relation to ensure resources are properly cleaned up */
-    relid = get_label_relation(label_name, graph_oid);
-    relation = table_open(relid, AccessShareLock);
-
-    temp_table_relation = table_open(temp_table_relid, AccessShareLock);
-
-    /* Free slots */
-    for (i = 0; i < BATCH_SIZE; i++)
+    PG_FINALLY();
     {
-        ExecDropSingleTupleTableSlot((*batch_state)->slots[i]);
-        ExecDropSingleTupleTableSlot((*batch_state)->temp_id_slots[i]);
+        fclose(fp);
+        csv_free(&p);
     }
+    PG_END_TRY();
 
-    /* Clean up batch state */
-    pfree_if_not_null((*batch_state)->slots);
-    pfree_if_not_null((*batch_state)->temp_id_slots);
-    pfree_if_not_null(*batch_state);
-    *batch_state = NULL;
-
-    table_close(relation, AccessShareLock);
-    table_close(temp_table_relation, AccessShareLock);
-}
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/src/backend/utils/load/age_load.c b/src/backend/utils/load/age_load.c
index 41233ff1..c7cf0677 100644
--- a/src/backend/utils/load/age_load.c
+++ b/src/backend/utils/load/age_load.c
@@ -18,16 +18,75 @@
  */
 
 #include "postgres.h"
+#include "catalog/indexing.h"
+#include "executor/executor.h"
 #include "utils/json.h"
 
 #include "utils/load/ag_load_edges.h"
 #include "utils/load/ag_load_labels.h"
 #include "utils/load/age_load.h"
+#include "utils/rel.h"
 
 static agtype_value *csv_value_to_agtype_value(char *csv_val);
 static Oid get_or_create_graph(const Name graph_name);
 static int32 get_or_create_label(Oid graph_oid, char *graph_name,
                                  char *label_name, char label_kind);
+static char *build_safe_filename(char *name);
+
+#define AGE_BASE_CSV_DIRECTORY "/tmp/age/"
+#define AGE_CSV_FILE_EXTENSION ".csv"
+
+static char *build_safe_filename(char *name)
+{
+    int length;
+    char path[PATH_MAX];
+    char *resolved;
+
+    if (name == NULL)
+    {
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("file name cannot be NULL")));
+
+    }
+
+    length = strlen(name);
+
+    if (length == 0)
+    {
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("file name cannot be zero length")));
+
+    }
+
+    snprintf(path, sizeof(path), "%s%s", AGE_BASE_CSV_DIRECTORY, name);
+
+    resolved = realpath(path, NULL);
+
+    if (resolved == NULL)
+    {
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("File or path does not exist [%s]", path)));
+    }
+
+    if (strncmp(resolved, AGE_BASE_CSV_DIRECTORY,
+                strlen(AGE_BASE_CSV_DIRECTORY)) != 0)
+    {
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("You can only load files located in [%s].",
+                               AGE_BASE_CSV_DIRECTORY)));
+    }
+
+    length = strlen(resolved) - 4;
+    if (strncmp(resolved+length, AGE_CSV_FILE_EXTENSION,
+                strlen(AGE_CSV_FILE_EXTENSION)) != 0)
+    {
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("You can only load files with extension [%s].",
+                               AGE_CSV_FILE_EXTENSION)));
+    }
+
+    return resolved;
+}
 
 agtype *create_empty_agtype(void)
 {
@@ -217,18 +276,35 @@ void insert_edge_simple(Oid graph_oid, char *label_name, graphid edge_id,
                         errmsg("label %s already exists as vertex label", label_name)));
     }
 
+    /* Open the relation */
+    label_relation = table_open(get_label_relation(label_name, graph_oid),
+                                RowExclusiveLock);
+
+    /* Form the tuple */
     values[0] = GRAPHID_GET_DATUM(edge_id);
     values[1] = GRAPHID_GET_DATUM(start_id);
     values[2] = GRAPHID_GET_DATUM(end_id);
     values[3] = AGTYPE_P_GET_DATUM((edge_properties));
-
-    label_relation = table_open(get_label_relation(label_name, graph_oid),
-                                RowExclusiveLock);
-
     tuple = heap_form_tuple(RelationGetDescr(label_relation),
                             values, nulls);
-    heap_insert(label_relation, tuple,
-                GetCurrentCommandId(true), 0, NULL);
+
+    if (RelationGetForm(label_relation)->relhasindex)
+    {
+        /*
+         * CatalogTupleInsertWithInfo() is originally for PostgreSQL's
+         * catalog. However, it is used here for convenience.
+         */
+        CatalogIndexState indstate = CatalogOpenIndexes(label_relation);
+        CatalogTupleInsertWithInfo(label_relation, tuple, indstate);
+        CatalogCloseIndexes(indstate);
+    }
+    else
+    {
+        heap_insert(label_relation, tuple, GetCurrentCommandId(true),
+                    0, NULL);
+    }
+
+    /* Close the relation */
     table_close(label_relation, RowExclusiveLock);
     CommandCounterIncrement();
 }
@@ -246,46 +322,75 @@ void insert_vertex_simple(Oid graph_oid, char *label_name, graphid vertex_id,
     if (get_label_kind(label_name, graph_oid) == LABEL_KIND_EDGE)
     {
         ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                        errmsg("label %s already exists as edge label", label_name)));
+                        errmsg("label %s already exists as edge label",
+                                label_name)));
     }
 
-    values[0] = GRAPHID_GET_DATUM(vertex_id);
-    values[1] = AGTYPE_P_GET_DATUM((vertex_properties));
-
+    /* Open the relation */
     label_relation = table_open(get_label_relation(label_name, graph_oid),
                                 RowExclusiveLock);
+
+    /* Form the tuple */
+    values[0] = GRAPHID_GET_DATUM(vertex_id);
+    values[1] = AGTYPE_P_GET_DATUM((vertex_properties));
     tuple = heap_form_tuple(RelationGetDescr(label_relation),
                             values, nulls);
-    heap_insert(label_relation, tuple,
-                GetCurrentCommandId(true), 0, NULL);
+
+    if (RelationGetForm(label_relation)->relhasindex)
+    {
+        /*
+         * CatalogTupleInsertWithInfo() is originally for PostgreSQL's
+         * catalog. However, it is used here for convenience.
+         */
+        CatalogIndexState indstate = CatalogOpenIndexes(label_relation);
+        CatalogTupleInsertWithInfo(label_relation, tuple, indstate);
+        CatalogCloseIndexes(indstate);
+    }
+    else
+    {
+        heap_insert(label_relation, tuple, GetCurrentCommandId(true),
+                    0, NULL);
+    }
+
+    /* Close the relation */
     table_close(label_relation, RowExclusiveLock);
     CommandCounterIncrement();
 }
 
-void insert_batch(batch_insert_state *batch_state, char *label_name,
-                  Oid graph_oid)
+void insert_batch(batch_insert_state *batch_state)
 {
-    Relation label_relation;
-    BulkInsertState bistate;
-    Oid relid;
-
-    // Get the relation OID
-    relid = get_label_relation(label_name, graph_oid);
-
-    // Open the relation
-    label_relation = table_open(relid, RowExclusiveLock);
-
-    // Prepare the BulkInsertState
-    bistate = GetBulkInsertState();
-
-    // Perform the bulk insert
-    heap_multi_insert(label_relation, batch_state->slots,
-                      batch_state->num_tuples, GetCurrentCommandId(true),
-                      0, bistate);
+    List *result;
+    int i;
 
-    // Clean up
-    FreeBulkInsertState(bistate);
-    table_close(label_relation, RowExclusiveLock);
+    /* Insert the tuples */
+    heap_multi_insert(batch_state->resultRelInfo->ri_RelationDesc,
+                      batch_state->slots, batch_state->num_tuples,
+                      GetCurrentCommandId(true), 0, NULL);
+    
+    /* Insert index entries for the tuples */
+    if (batch_state->resultRelInfo->ri_NumIndices > 0)
+    {
+        for (i = 0; i < batch_state->num_tuples; i++)
+        {
+            result = ExecInsertIndexTuples(batch_state->resultRelInfo,
+                                           batch_state->slots[i],
+                                           batch_state->estate, false,
+                                           true, NULL, NIL, false);
+
+            /* Check if the unique constraint is violated */
+            if (list_length(result) != 0)
+            {
+                Datum id;
+                bool isnull;
+
+                id = slot_getattr(batch_state->slots[i], 1, &isnull);
+                ereport(ERROR, (errmsg("Cannot insert duplicate vertex id: %ld",
+                                        DATUM_GET_GRAPHID(id)),
+                                errhint("Entry id %ld is already used",
+                                        get_graphid_entry_id(id))));
+            }
+        }
+    }
 
     CommandCounterIncrement();
 }
@@ -295,7 +400,7 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
 {
     Name graph_name;
     Name label_name;
-    text* file_path;
+    text* file_name;
     char* graph_name_str;
     char* label_name_str;
     char* file_path_str;
@@ -324,7 +429,7 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
 
     graph_name = PG_GETARG_NAME(0);
     label_name = PG_GETARG_NAME(1);
-    file_path = PG_GETARG_TEXT_P(2);
+    file_name = PG_GETARG_TEXT_P(2);
     id_field_exists = PG_GETARG_BOOL(3);
     load_as_agtype = PG_GETARG_BOOL(4);
 
@@ -336,7 +441,7 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
         label_name_str = AG_DEFAULT_LABEL_VERTEX;
     }
 
-    file_path_str = text_to_cstring(file_path);
+    file_path_str = build_safe_filename(text_to_cstring(file_name));
 
     graph_oid = get_or_create_graph(graph_name);
     label_id = get_or_create_label(graph_oid, graph_name_str,
@@ -345,6 +450,9 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
     create_labels_from_csv_file(file_path_str, graph_name_str, graph_oid,
                                 label_name_str, label_id, id_field_exists,
                                 load_as_agtype);
+
+    free(file_path_str);
+
     PG_RETURN_VOID();
 }
 
@@ -354,7 +462,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
 
     Name graph_name;
     Name label_name;
-    text* file_path;
+    text* file_name;
     char* graph_name_str;
     char* label_name_str;
     char* file_path_str;
@@ -382,7 +490,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
 
     graph_name = PG_GETARG_NAME(0);
     label_name = PG_GETARG_NAME(1);
-    file_path = PG_GETARG_TEXT_P(2);
+    file_name = PG_GETARG_TEXT_P(2);
     load_as_agtype = PG_GETARG_BOOL(3);
 
     graph_name_str = NameStr(*graph_name);
@@ -393,7 +501,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
         label_name_str = AG_DEFAULT_LABEL_EDGE;
     }
 
-    file_path_str = text_to_cstring(file_path);
+    file_path_str = build_safe_filename(text_to_cstring(file_name));
 
     graph_oid = get_or_create_graph(graph_name);
     label_id = get_or_create_label(graph_oid, graph_name_str,
@@ -401,6 +509,9 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
 
     create_edges_from_csv_file(file_path_str, graph_name_str, graph_oid,
                                label_name_str, label_id, load_as_agtype);
+
+    free(file_path_str);
+
     PG_RETURN_VOID();
 }
 
@@ -475,3 +586,79 @@ static int32 get_or_create_label(Oid graph_oid, char *graph_name,
 
     return label_id;
 }
+
+/*
+ * Initialize the batch insert state.
+ */
+void init_batch_insert(batch_insert_state **batch_state,
+                              char *label_name, Oid graph_oid)
+{
+    Relation relation;
+    Oid relid;
+    EState *estate;
+    ResultRelInfo *resultRelInfo;
+    int i;
+
+    /* Open the relation */
+    relid = get_label_relation(label_name, graph_oid);
+    relation = table_open(relid, RowExclusiveLock);
+
+    /* Initialize executor state */
+    estate = CreateExecutorState();
+
+    /* Initialize resultRelInfo */
+    resultRelInfo = makeNode(ResultRelInfo);
+    InitResultRelInfo(resultRelInfo, relation, 1, NULL, estate->es_instrument);
+    estate->es_result_relations = &resultRelInfo;
+
+    /* Open the indices */
+    ExecOpenIndices(resultRelInfo, false);
+
+    /* Initialize the batch insert state */
+    *batch_state = (batch_insert_state *) palloc0(sizeof(batch_insert_state));
+    (*batch_state)->slots = palloc(sizeof(TupleTableSlot *) * BATCH_SIZE);
+    (*batch_state)->estate = estate;
+    (*batch_state)->resultRelInfo = resultRelInfo;
+    (*batch_state)->max_tuples = BATCH_SIZE;
+    (*batch_state)->num_tuples = 0;
+
+    /* Create slots */
+    for (i = 0; i < BATCH_SIZE; i++)
+    {
+        (*batch_state)->slots[i] = MakeSingleTupleTableSlot(
+                                            RelationGetDescr(relation),
+                                            &TTSOpsHeapTuple);
+    }
+}
+
+/*
+ * Finish the batch insert for vertices. Insert the
+ * tuples remaining in the batch state and clean up.
+ */
+void finish_batch_insert(batch_insert_state **batch_state)
+{
+    int i;
+
+    if ((*batch_state)->num_tuples > 0)
+    {
+        insert_batch(*batch_state);
+        (*batch_state)->num_tuples = 0;
+    }
+
+    /* Free slots */
+    for (i = 0; i < BATCH_SIZE; i++)
+    {
+        ExecDropSingleTupleTableSlot((*batch_state)->slots[i]);
+    }
+
+    /* Clean up, close the indices and relation */
+    ExecCloseIndices((*batch_state)->resultRelInfo);
+    table_close((*batch_state)->resultRelInfo->ri_RelationDesc,
+                RowExclusiveLock);
+
+    /* Clean up batch state */
+    FreeExecutorState((*batch_state)->estate);
+    pfree((*batch_state)->slots);
+    pfree(*batch_state);
+    *batch_state = NULL;
+}
diff --git a/src/include/nodes/ag_nodes.h b/src/include/nodes/ag_nodes.h
index f0cc2204..121832c0 100644
--- a/src/include/nodes/ag_nodes.h
+++ b/src/include/nodes/ag_nodes.h
@@ -78,6 +78,9 @@ typedef enum ag_node_tag
     cypher_merge_information_t
 } ag_node_tag;
 
+extern const char *node_names[];
+extern const ExtensibleNodeMethods node_methods[];
+
 void register_ag_nodes(void);
 
 ExtensibleNode *_new_ag_node(Size size, ag_node_tag tag);
diff --git a/src/include/optimizer/cypher_createplan.h b/src/include/optimizer/cypher_createplan.h
index 2d5d2e69..ab01f2b5 100644
--- a/src/include/optimizer/cypher_createplan.h
+++ b/src/include/optimizer/cypher_createplan.h
@@ -20,6 +20,8 @@
 #ifndef AG_CYPHER_CREATEPLAN_H
 #define AG_CYPHER_CREATEPLAN_H
 
+#include "nodes/extensible.h"
+
 Plan *plan_cypher_create_path(PlannerInfo *root, RelOptInfo *rel,
                               CustomPath *best_path, List *tlist,
                               List *clauses, List *custom_plans);
@@ -36,4 +38,9 @@ Plan *plan_cypher_merge_path(PlannerInfo *root, RelOptInfo *rel,
                              CustomPath *best_path, List *tlist,
                              List *clauses, List *custom_plans);
 
+extern const CustomScanMethods cypher_create_plan_methods;
+extern const CustomScanMethods cypher_set_plan_methods;
+extern const CustomScanMethods cypher_delete_plan_methods;
+extern const CustomScanMethods cypher_merge_plan_methods;
+
 #endif
diff --git a/src/include/optimizer/cypher_pathnode.h b/src/include/optimizer/cypher_pathnode.h
index 75c2b07d..67683202 100644
--- a/src/include/optimizer/cypher_pathnode.h
+++ b/src/include/optimizer/cypher_pathnode.h
@@ -20,6 +20,8 @@
 #ifndef AG_CYPHER_PATHNODE_H
 #define AG_CYPHER_PATHNODE_H
 
+#include "nodes/extensible.h"
+
 #define CREATE_PATH_NAME "Cypher Create"
 #define SET_PATH_NAME "Cypher Set"
 #define DELETE_PATH_NAME "Cypher Delete"
@@ -34,4 +36,9 @@ CustomPath *create_cypher_delete_path(PlannerInfo *root, RelOptInfo *rel,
 CustomPath *create_cypher_merge_path(PlannerInfo *root, RelOptInfo *rel,
                                      List *custom_private);
 
+extern const CustomPathMethods cypher_create_path_methods;
+extern const CustomPathMethods cypher_set_path_methods;
+extern const CustomPathMethods cypher_delete_path_methods;
+extern const CustomPathMethods cypher_merge_path_methods;
+
 #endif
diff --git a/src/include/utils/agtype.h b/src/include/utils/agtype.h
index 48677532..ab2ba08c 100644
--- a/src/include/utils/agtype.h
+++ b/src/include/utils/agtype.h
@@ -556,6 +556,7 @@ void pfree_agtype_value(agtype_value* value);
 void pfree_agtype_value_content(agtype_value* value);
 void pfree_agtype_in_state(agtype_in_state* value);
 void pfree_if_not_null(void *ptr);
+void *repalloc_check(void *ptr, size_t len);
 agtype_value *agtype_value_from_cstring(char *str, int len);
 /* Oid accessors for AGTYPE */
 Oid get_AGTYPEOID(void);
diff --git a/src/include/utils/load/ag_load_labels.h b/src/include/utils/load/ag_load_labels.h
index 3a70a5c0..b8ed1572 100644
--- a/src/include/utils/load/ag_load_labels.h
+++ b/src/include/utils/load/ag_load_labels.h
@@ -24,10 +24,6 @@
 #include "access/heapam.h"
 #include "utils/load/age_load.h"
 
-#define AGE_VERTIX 1
-#define AGE_EDGE 2
-
-
 struct counts {
     long unsigned fields;
     long unsigned allvalues;
@@ -51,7 +47,6 @@ typedef struct {
     char *label_name;
     int label_id;
     Oid label_seq_relid;
-    Oid temp_table_relid;
     bool id_field_exists;
     bool load_as_agtype;
     int curr_seq_num;
diff --git a/src/include/utils/load/age_load.h b/src/include/utils/load/age_load.h
index b1335581..72f11493 100644
--- a/src/include/utils/load/age_load.h
+++ b/src/include/utils/load/age_load.h
@@ -30,16 +30,13 @@
 #ifndef AGE_ENTITY_CREATOR_H
 #define AGE_ENTITY_CREATOR_H
 
-#define TEMP_VERTEX_ID_TABLE_SUFFIX "_ag_vertex_ids"
-#define GET_TEMP_VERTEX_ID_TABLE(graph_name) \
-    psprintf("_%s%s", graph_name, TEMP_VERTEX_ID_TABLE_SUFFIX)
-
 #define BATCH_SIZE 1000
 
-typedef struct
+typedef struct batch_insert_state
 {
+    EState *estate;
+    ResultRelInfo *resultRelInfo;
     TupleTableSlot **slots;
-    TupleTableSlot **temp_id_slots;
     int num_tuples;
     int max_tuples;
 } batch_insert_state;
@@ -57,7 +54,10 @@ void insert_vertex_simple(Oid graph_oid, char *label_name, graphid vertex_id,
 void insert_edge_simple(Oid graph_oid, char *label_name, graphid edge_id,
                         graphid start_id, graphid end_id,
                         agtype* end_properties);
-void insert_batch(batch_insert_state *batch_state, char *label_name,
-                  Oid graph_oid);
+void insert_batch(batch_insert_state *batch_state);
+
+void init_batch_insert(batch_insert_state **batch_state,
+                       char *label_name, Oid graph_oid);
+void finish_batch_insert(batch_insert_state **batch_state);
 
 #endif /* AGE_ENTITY_CREATOR_H */
diff --git a/tools/gen_keywordlist.pl b/tools/gen_keywordlist.pl
index 49930043..58e66db8 100755
--- a/tools/gen_keywordlist.pl
+++ b/tools/gen_keywordlist.pl
@@ -112,6 +112,7 @@ printf $kwdef <<EOM, $base_filename, uc $base_filename, uc $base_filename;
 #define %s_H
 
 #include "common/kwlookup.h"
+#include "parser/cypher_keywords.h"
 
 EOM
 
