PostgreSQL Source Code git master
Loading...
Searching...
No Matches
propgraphcmds.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_collation_d.h"
#include "catalog/pg_operator_d.h"
#include "catalog/pg_propgraph_element.h"
#include "catalog/pg_propgraph_element_label.h"
#include "catalog/pg_propgraph_label.h"
#include "catalog/pg_propgraph_label_property.h"
#include "catalog/pg_propgraph_property.h"
#include "commands/defrem.h"
#include "commands/propgraphcmds.h"
#include "commands/tablecmds.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/syscache.h"
Include dependency graph for propgraphcmds.c:

Go to the source code of this file.

Data Structures

struct  element_info
 

Functions

static ArrayTypepropgraph_element_get_key (ParseState *pstate, const List *keycols, Relation element_rel, const char *aliasname, int location)
 
static void propgraph_edge_get_ref_keys (ParseState *pstate, const List *keycols, const List *refcols, Relation edge_rel, Relation ref_rel, const char *aliasname, int location, const char *type, ArrayType **outkey, ArrayType **outref, ArrayType **outeqop)
 
static AttrNumberarray_from_column_list (ParseState *pstate, const List *colnames, int location, Relation element_rel)
 
static ArrayTypearray_from_attnums (int numattrs, const AttrNumber *attnums)
 
static Oid insert_element_record (ObjectAddress pgaddress, struct element_info *einfo)
 
static Oid insert_label_record (Oid graphid, Oid peoid, const char *label)
 
static void insert_property_records (Oid graphid, Oid ellabeloid, Oid pgerelid, const PropGraphProperties *properties)
 
static void insert_property_record (Oid graphid, Oid ellabeloid, Oid pgerelid, const char *propname, const Expr *expr)
 
static void check_element_properties (Oid peoid)
 
static void check_element_label_properties (Oid ellabeloid)
 
static void check_all_labels_properties (Oid pgrelid)
 
static Oid get_vertex_oid (ParseState *pstate, Oid pgrelid, const char *alias, int location)
 
static Oid get_edge_oid (ParseState *pstate, Oid pgrelid, const char *alias, int location)
 
static Oid get_element_relid (Oid peid)
 
static Listget_graph_label_ids (Oid graphid)
 
static Listget_label_element_label_ids (Oid labelid)
 
static Listget_element_label_property_names (Oid ellabeloid)
 
static Listget_graph_property_ids (Oid graphid)
 
ObjectAddress CreatePropGraph (ParseState *pstate, const CreatePropGraphStmt *stmt)
 
static void array_of_attnums_to_objectaddrs (Oid relid, ArrayType *arr, ObjectAddresses *addrs)
 
static void array_of_opers_to_objectaddrs (ArrayType *arr, ObjectAddresses *addrs)
 
ObjectAddress AlterPropGraph (ParseState *pstate, const AlterPropGraphStmt *stmt)
 

Function Documentation

◆ AlterPropGraph()

ObjectAddress AlterPropGraph ( ParseState pstate,
const AlterPropGraphStmt stmt 
)

Definition at line 1291 of file propgraphcmds.c.

1292{
1293 Oid pgrelid;
1294 ListCell *lc;
1296
1299 stmt->missing_ok ? RVR_MISSING_OK : 0,
1301 NULL);
1302 if (pgrelid == InvalidOid)
1303 {
1305 (errmsg("relation \"%s\" does not exist, skipping",
1306 stmt->pgname->relname)));
1307 return InvalidObjectAddress;
1308 }
1309
1311
1312 foreach(lc, stmt->add_vertex_tables)
1313 {
1315 struct element_info *vinfo;
1316 Relation rel;
1317 Oid peoid;
1318
1320 vinfo->kind = PGEKIND_VERTEX;
1321
1323
1324 rel = table_open(vinfo->relid, NoLock);
1325
1327 ereport(ERROR,
1329 errmsg("cannot add temporary element table to non-temporary property graph"),
1330 errdetail("Table \"%s\" is a temporary table.", get_rel_name(vinfo->relid)),
1331 parser_errposition(pstate, vertex->vtable->location)));
1332
1333 if (vertex->vtable->alias)
1334 vinfo->aliasname = vertex->vtable->alias->aliasname;
1335 else
1336 vinfo->aliasname = vertex->vtable->relname;
1337
1338 vinfo->key = propgraph_element_get_key(pstate, vertex->vkey, rel, vinfo->aliasname, vertex->location);
1339
1340 vinfo->labels = vertex->labels;
1341
1342 table_close(rel, NoLock);
1343
1346 CStringGetDatum(vinfo->aliasname)))
1347 ereport(ERROR,
1349 errmsg("alias \"%s\" already exists in property graph \"%s\"",
1350 vinfo->aliasname, stmt->pgname->relname),
1351 parser_errposition(pstate, vertex->vtable->location));
1352
1354
1358 }
1359
1360 foreach(lc, stmt->add_edge_tables)
1361 {
1363 struct element_info *einfo;
1364 Relation rel;
1367 Oid peoid;
1368
1370 einfo->kind = PGEKIND_EDGE;
1371
1373
1374 rel = table_open(einfo->relid, NoLock);
1375
1377 ereport(ERROR,
1379 errmsg("cannot add temporary element table to non-temporary property graph"),
1380 errdetail("Table \"%s\" is a temporary table.", get_rel_name(einfo->relid)),
1381 parser_errposition(pstate, edge->etable->location)));
1382
1383 if (edge->etable->alias)
1384 einfo->aliasname = edge->etable->alias->aliasname;
1385 else
1386 einfo->aliasname = edge->etable->relname;
1387
1388 einfo->key = propgraph_element_get_key(pstate, edge->ekey, rel, einfo->aliasname, edge->location);
1389
1390 einfo->srcvertexid = get_vertex_oid(pstate, pgrelid, edge->esrcvertex, edge->location);
1391 einfo->destvertexid = get_vertex_oid(pstate, pgrelid, edge->edestvertex, edge->location);
1392
1393 einfo->srcrelid = get_element_relid(einfo->srcvertexid);
1394 einfo->destrelid = get_element_relid(einfo->destvertexid);
1395
1396 srcrel = table_open(einfo->srcrelid, AccessShareLock);
1397 destrel = table_open(einfo->destrelid, AccessShareLock);
1398
1399 propgraph_edge_get_ref_keys(pstate, edge->esrckey, edge->esrcvertexcols, rel, srcrel,
1400 einfo->aliasname, edge->location, "SOURCE",
1401 &einfo->srckey, &einfo->srcref, &einfo->srceqop);
1402 propgraph_edge_get_ref_keys(pstate, edge->edestkey, edge->edestvertexcols, rel, destrel,
1403 einfo->aliasname, edge->location, "DESTINATION",
1404 &einfo->destkey, &einfo->destref, &einfo->desteqop);
1405
1406 einfo->labels = edge->labels;
1407
1410
1411 table_close(rel, NoLock);
1412
1415 CStringGetDatum(einfo->aliasname)))
1416 ereport(ERROR,
1418 errmsg("alias \"%s\" already exists in property graph \"%s\"",
1419 einfo->aliasname, stmt->pgname->relname),
1420 parser_errposition(pstate, edge->etable->location));
1421
1423
1427 }
1428
1429 foreach(lc, stmt->drop_vertex_tables)
1430 {
1431 char *alias = strVal(lfirst(lc));
1432 Oid peoid;
1433 ObjectAddress obj;
1434
1435 peoid = get_vertex_oid(pstate, pgrelid, alias, -1);
1437 performDeletion(&obj, stmt->drop_behavior, 0);
1438 }
1439
1440 foreach(lc, stmt->drop_edge_tables)
1441 {
1442 char *alias = strVal(lfirst(lc));
1443 Oid peoid;
1444 ObjectAddress obj;
1445
1446 peoid = get_edge_oid(pstate, pgrelid, alias, -1);
1448 performDeletion(&obj, stmt->drop_behavior, 0);
1449 }
1450
1451 /* Remove any orphaned pg_propgraph_label entries */
1452 if (stmt->drop_vertex_tables || stmt->drop_edge_tables)
1453 {
1455 {
1457 {
1458 ObjectAddress obj;
1459
1461 performDeletion(&obj, stmt->drop_behavior, 0);
1462 }
1463 }
1464 }
1465
1466 foreach(lc, stmt->add_labels)
1467 {
1469 Oid peoid;
1470 Oid pgerelid;
1472
1473 Assert(lp->label);
1474
1475 if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX)
1476 peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1);
1477 else
1478 peoid = get_edge_oid(pstate, pgrelid, stmt->element_alias, -1);
1479
1481
1484
1488 }
1489
1490 if (stmt->drop_label)
1491 {
1492 Oid peoid;
1493 Oid labeloid;
1495 ObjectAddress obj;
1496
1497 if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX)
1498 peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1);
1499 else
1500 peoid = get_edge_oid(pstate, pgrelid, stmt->element_alias, -1);
1501
1505 CStringGetDatum(stmt->drop_label));
1506 if (!labeloid)
1507 ereport(ERROR,
1509 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1510 get_rel_name(pgrelid), stmt->element_alias, stmt->drop_label),
1511 parser_errposition(pstate, -1));
1512
1517
1518 if (!ellabeloid)
1519 ereport(ERROR,
1521 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1522 get_rel_name(pgrelid), stmt->element_alias, stmt->drop_label),
1523 parser_errposition(pstate, -1));
1524
1526 performDeletion(&obj, stmt->drop_behavior, 0);
1527
1528 /* Remove any orphaned pg_propgraph_label entries */
1530 {
1532 performDeletion(&obj, stmt->drop_behavior, 0);
1533 }
1534 }
1535
1536 if (stmt->add_properties)
1537 {
1538 Oid peoid;
1539 Oid pgerelid;
1540 Oid labeloid;
1542
1543 if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX)
1544 peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1);
1545 else
1546 peoid = get_edge_oid(pstate, pgrelid, stmt->element_alias, -1);
1547
1551 CStringGetDatum(stmt->alter_label));
1552 if (!labeloid)
1553 ereport(ERROR,
1555 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1556 get_rel_name(pgrelid), stmt->element_alias, stmt->alter_label),
1557 parser_errposition(pstate, -1));
1558
1563 if (!ellabeloid)
1564 ereport(ERROR,
1566 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1567 get_rel_name(pgrelid), stmt->element_alias, stmt->alter_label),
1568 parser_errposition(pstate, -1));
1569
1571
1573
1577 }
1578
1579 if (stmt->drop_properties)
1580 {
1581 Oid peoid;
1582 Oid labeloid;
1584 ObjectAddress obj;
1585
1586 if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX)
1587 peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1);
1588 else
1589 peoid = get_edge_oid(pstate, pgrelid, stmt->element_alias, -1);
1590
1594 CStringGetDatum(stmt->alter_label));
1595 if (!labeloid)
1596 ereport(ERROR,
1598 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1599 get_rel_name(pgrelid), stmt->element_alias, stmt->alter_label),
1600 parser_errposition(pstate, -1));
1601
1606
1607 if (!ellabeloid)
1608 ereport(ERROR,
1610 errmsg("property graph \"%s\" element \"%s\" has no label \"%s\"",
1611 get_rel_name(pgrelid), stmt->element_alias, stmt->alter_label),
1612 parser_errposition(pstate, -1));
1613
1614 foreach(lc, stmt->drop_properties)
1615 {
1616 char *propname = strVal(lfirst(lc));
1617 Oid propoid;
1618 Oid plpoid;
1619
1624 if (!propoid)
1625 ereport(ERROR,
1627 errmsg("property graph \"%s\" element \"%s\" label \"%s\" has no property \"%s\"",
1628 get_rel_name(pgrelid), stmt->element_alias, stmt->alter_label, propname),
1629 parser_errposition(pstate, -1));
1630
1632
1634 performDeletion(&obj, stmt->drop_behavior, 0);
1635 }
1636
1638 }
1639
1640 /* Remove any orphaned pg_propgraph_property entries */
1641 if (stmt->drop_properties || stmt->drop_vertex_tables || stmt->drop_edge_tables)
1642 {
1644 {
1645 Relation rel;
1646 SysScanDesc scan;
1647 ScanKeyData key[1];
1648
1650 ScanKeyInit(&key[0],
1654 /* XXX no suitable index */
1655 scan = systable_beginscan(rel, InvalidOid, true, NULL, 1, key);
1656 if (!systable_getnext(scan))
1657 {
1658 ObjectAddress obj;
1659
1661 performDeletion(&obj, stmt->drop_behavior, 0);
1662 }
1663
1664 systable_endscan(scan);
1666 }
1667 }
1668
1669 /*
1670 * Invalidate relcache entry of the property graph so that the queries in
1671 * the cached plans referencing the property graph will be rewritten
1672 * considering changes to the propert graph.
1673 */
1675
1676 return pgaddress;
1677}
#define Assert(condition)
Definition c.h:942
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition dependency.c:279
int errcode(int sqlerrcode)
Definition elog.c:874
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define NOTICE
Definition elog.h:35
#define ereport(elevel,...)
Definition elog.h:150
#define palloc0_object(type)
Definition fe_memutils.h:75
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
#define stmt
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition inval.c:1691
#define NoLock
Definition lockdefs.h:34
#define ShareRowExclusiveLock
Definition lockdefs.h:41
#define AccessShareLock
Definition lockdefs.h:36
#define RowShareLock
Definition lockdefs.h:37
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2298
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition namespace.c:442
@ RVR_MISSING_OK
Definition namespace.h:90
static char * errmsg
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
@ PROPGRAPH_ELEMENT_KIND_VERTEX
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define foreach_oid(var, lst)
Definition pg_list.h:471
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
#define InvalidOid
unsigned int Oid
static int fb(int x)
static void check_all_labels_properties(Oid pgrelid)
static Oid get_edge_oid(ParseState *pstate, Oid pgrelid, const char *alias, int location)
static ArrayType * propgraph_element_get_key(ParseState *pstate, const List *keycols, Relation element_rel, const char *aliasname, int location)
static Oid get_element_relid(Oid peid)
static Oid get_vertex_oid(ParseState *pstate, Oid pgrelid, const char *alias, int location)
static void insert_property_records(Oid graphid, Oid ellabeloid, Oid pgerelid, const PropGraphProperties *properties)
static Oid insert_label_record(Oid graphid, Oid peoid, const char *label)
static void check_element_label_properties(Oid ellabeloid)
static List * get_graph_label_ids(Oid graphid)
static Oid insert_element_record(ObjectAddress pgaddress, struct element_info *einfo)
static List * get_label_element_label_ids(Oid labelid)
static List * get_graph_property_ids(Oid graphid)
static void check_element_properties(Oid peoid)
static void propgraph_edge_get_ref_keys(ParseState *pstate, const List *keycols, const List *refcols, Relation edge_rel, Relation ref_rel, const char *aliasname, int location, const char *type, ArrayType **outkey, ArrayType **outref, ArrayType **outeqop)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31
Form_pg_class rd_rel
Definition rel.h:111
ArrayType * key
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
#define strVal(v)
Definition value.h:82
void CommandCounterIncrement(void)
Definition xact.c:1102

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheInvalidateRelcacheByRelid(), check_all_labels_properties(), check_element_label_properties(), check_element_properties(), CommandCounterIncrement(), CStringGetDatum(), ereport, errcode(), errdetail(), errmsg, ERROR, fb(), foreach_oid, get_edge_oid(), get_element_relid(), get_graph_label_ids(), get_graph_property_ids(), get_label_element_label_ids(), get_rel_name(), get_rel_persistence(), get_vertex_oid(), GetSysCacheOid2, insert_element_record(), insert_label_record(), insert_property_records(), InvalidObjectAddress, InvalidOid, element_info::key, lfirst, lfirst_node, NoLock, NOTICE, ObjectAddressSet, ObjectIdGetDatum(), palloc0_object, parser_errposition(), performDeletion(), propgraph_edge_get_ref_keys(), propgraph_element_get_key(), PROPGRAPH_ELEMENT_KIND_VERTEX, RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, RowShareLock, RVR_MISSING_OK, ScanKeyInit(), SearchSysCacheExists2, ShareRowExclusiveLock, stmt, strVal, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ProcessUtilitySlow().

◆ array_from_attnums()

static ArrayType * array_from_attnums ( int  numattrs,
const AttrNumber attnums 
)
static

Definition at line 561 of file propgraphcmds.c.

562{
564
566
567 for (int i = 0; i < numattrs; i++)
568 attnumsd[i] = Int16GetDatum(attnums[i]);
569
571}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define palloc_array(type, count)
Definition fe_memutils.h:76
int i
Definition isn.c:77
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
uint64_t Datum
Definition postgres.h:70

References construct_array_builtin(), fb(), i, Int16GetDatum(), and palloc_array.

Referenced by propgraph_edge_get_ref_keys(), and propgraph_element_get_key().

◆ array_from_column_list()

static AttrNumber * array_from_column_list ( ParseState pstate,
const List colnames,
int  location,
Relation  element_rel 
)
static

Definition at line 518 of file propgraphcmds.c.

519{
520 int numattrs;
521 AttrNumber *attnums;
522 int i;
523 ListCell *lc;
524
525 numattrs = list_length(colnames);
526 attnums = palloc_array(AttrNumber, numattrs);
527
528 i = 0;
529 foreach(lc, colnames)
530 {
531 char *colname = strVal(lfirst(lc));
534
535 attnum = get_attnum(relid, colname);
536 if (!attnum)
539 errmsg("column \"%s\" of relation \"%s\" does not exist",
540 colname, get_rel_name(relid)),
541 parser_errposition(pstate, location)));
542 attnums[i++] = attnum;
543 }
544
545 for (int j = 0; j < numattrs; j++)
546 {
547 for (int k = j + 1; k < numattrs; k++)
548 {
549 if (attnums[j] == attnums[k])
552 errmsg("graph key columns list must not contain duplicates"),
553 parser_errposition(pstate, location)));
554 }
555 }
556
557 return attnums;
558}
int16 AttrNumber
Definition attnum.h:21
int j
Definition isn.c:78
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:977
int16 attnum
static int list_length(const List *l)
Definition pg_list.h:152
#define RelationGetRelid(relation)
Definition rel.h:514

References attnum, ereport, errcode(), errmsg, ERROR, fb(), get_attnum(), get_rel_name(), i, j, lfirst, list_length(), palloc_array, parser_errposition(), RelationGetRelid, element_info::relid, and strVal.

Referenced by propgraph_edge_get_ref_keys(), and propgraph_element_get_key().

◆ array_of_attnums_to_objectaddrs()

static void array_of_attnums_to_objectaddrs ( Oid  relid,
ArrayType arr,
ObjectAddresses addrs 
)
static

Definition at line 574 of file propgraphcmds.c.

575{
577 int numattrs;
578
580
581 for (int i = 0; i < numattrs; i++)
582 {
584
587 }
588}
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
static int16 DatumGetInt16(Datum X)
Definition postgres.h:162

References add_exact_object_address(), DatumGetInt16(), deconstruct_array_builtin(), fb(), i, ObjectAddressSubSet, and element_info::relid.

Referenced by insert_element_record().

◆ array_of_opers_to_objectaddrs()

static void array_of_opers_to_objectaddrs ( ArrayType arr,
ObjectAddresses addrs 
)
static

Definition at line 591 of file propgraphcmds.c.

592{
593 Datum *opersd;
594 int numopers;
595
597
598 for (int i = 0; i < numopers; i++)
599 {
601
604 }
605}
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242

References add_exact_object_address(), DatumGetObjectId(), deconstruct_array_builtin(), fb(), i, and ObjectAddressSet.

Referenced by insert_element_record().

◆ check_all_labels_properties()

static void check_all_labels_properties ( Oid  pgrelid)
static

◆ check_element_label_properties()

static void check_element_label_properties ( Oid  ellabeloid)
static

Definition at line 1182 of file propgraphcmds.c.

1183{
1184 Relation rel;
1185 SysScanDesc scan;
1186 ScanKeyData key[1];
1187 HeapTuple tuple;
1188 Oid labelid = InvalidOid;
1190 List *myprops,
1191 *refprops;
1192 List *diff1,
1193 *diff2;
1194
1196
1197 /*
1198 * Get element label info
1199 */
1200 ScanKeyInit(&key[0],
1205 if (HeapTupleIsValid(tuple = systable_getnext(scan)))
1206 {
1208
1209 labelid = ellabel->pgellabelid;
1210 }
1211 systable_endscan(scan);
1212 if (!labelid)
1213 elog(ERROR, "element label %u not found", ellabeloid);
1214
1215 /*
1216 * Find a reference element label to fetch label properties. The
1217 * reference element label has to have the label OID as the one being
1218 * checked but be distinct from the one being checked.
1219 */
1220 ScanKeyInit(&key[0],
1223 F_OIDEQ, ObjectIdGetDatum(labelid));
1224 scan = systable_beginscan(rel, PropgraphElementLabelLabelIndexId, true, NULL, 1, key);
1225 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1226 {
1228
1229 if (otherellabel->oid != ellabeloid)
1230 {
1232 break;
1233 }
1234 }
1235 systable_endscan(scan);
1236
1238
1239 /*
1240 * If there is not previous definition of this label, then we are done.
1241 */
1242 if (!ref_ellabeloid)
1243 return;
1244
1245 /*
1246 * Now check number and names.
1247 *
1248 * XXX We could provide more detail in the error messages, but that would
1249 * probably only be useful for some ALTER commands, because otherwise it's
1250 * not really clear which label definition is the wrong one, and so you'd
1251 * have to construct a rather verbose report to be of any use. Let's keep
1252 * it simple for now.
1253 */
1254
1257
1259 ereport(ERROR,
1261 errmsg("mismatching number of properties in definition of label \"%s\"", get_propgraph_label_name(labelid)));
1262
1265
1266 if (diff1 || diff2)
1267 ereport(ERROR,
1269 errmsg("mismatching properties names in definition of label \"%s\"", get_propgraph_label_name(labelid)));
1270}
#define elog(elevel,...)
Definition elog.h:226
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
List * list_difference(const List *list1, const List *list2)
Definition list.c:1237
char * get_propgraph_label_name(Oid labeloid)
Definition lsyscache.c:3941
END_CATALOG_STRUCT typedef FormData_pg_propgraph_element_label * Form_pg_propgraph_element_label
static List * get_element_label_property_names(Oid ellabeloid)
Definition pg_list.h:54

References AccessShareLock, BTEqualStrategyNumber, elog, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_propgraph_element_label, get_element_label_property_names(), get_propgraph_label_name(), GETSTRUCT(), HeapTupleIsValid, InvalidOid, element_info::key, list_difference(), list_length(), ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterPropGraph(), and check_all_labels_properties().

◆ check_element_properties()

static void check_element_properties ( Oid  peoid)
static

Definition at line 1051 of file propgraphcmds.c.

1052{
1053 Relation rel1;
1054 ScanKeyData key1[1];
1057 List *propoids = NIL;
1058 List *propexprs = NIL;
1059
1061 ScanKeyInit(&key1[0],
1065
1068 {
1070 Relation rel2;
1071 ScanKeyData key2[1];
1074
1076 ScanKeyInit(&key2[0],
1080
1083 {
1085 Oid propoid;
1086 Datum datum;
1087 bool isnull;
1088 char *propexpr;
1089 ListCell *lc1,
1090 *lc2;
1091 bool found;
1092
1093 propoid = lprop->plppropid;
1095 Assert(!isnull);
1097
1098 found = false;
1100 {
1101 if (propoid == lfirst_oid(lc1))
1102 {
1103 Node *na,
1104 *nb;
1105
1108
1109 found = true;
1110
1111 if (!equal(na, nb))
1112 {
1115 List *dpcontext;
1116 char *dpa,
1117 *dpb;
1118
1120 if (!tuple3)
1121 elog(ERROR, "cache lookup failed for property graph element %u", peoid);
1123 dpcontext = deparse_context_for(get_rel_name(elform->pgerelid), elform->pgerelid);
1124
1125 dpa = deparse_expression(na, dpcontext, false, false);
1126 dpb = deparse_expression(nb, dpcontext, false, false);
1127
1128 /*
1129 * show in sorted order to keep output independent of
1130 * index order
1131 */
1132 if (strcmp(dpa, dpb) > 0)
1133 {
1134 char *tmp;
1135
1136 tmp = dpa;
1137 dpa = dpb;
1138 dpb = tmp;
1139 }
1140
1141 ereport(ERROR,
1143 errmsg("element \"%s\" property \"%s\" expression mismatch: %s vs. %s",
1145 errdetail("In a property graph element, a property of the same name has to have the same expression in each label."));
1146
1148 }
1149
1150 break;
1151 }
1152 }
1153
1154 if (!found)
1155 {
1158 }
1159 }
1162 }
1163
1166}
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:834
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
List * lappend(List *list, void *datum)
Definition list.c:339
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
char * get_propgraph_property_name(Oid propoid)
Definition lsyscache.c:3959
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
#define lfirst_oid(lc)
Definition pg_list.h:174
END_CATALOG_STRUCT typedef FormData_pg_propgraph_element * Form_pg_propgraph_element
END_CATALOG_STRUCT typedef FormData_pg_propgraph_label_property * Form_pg_propgraph_label_property
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetDescr(relation)
Definition rel.h:540
List * deparse_context_for(const char *aliasname, Oid relid)
Definition ruleutils.c:4039
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition ruleutils.c:3976
Definition nodes.h:135
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220

References AccessShareLock, Assert, BTEqualStrategyNumber, deparse_context_for(), deparse_expression(), elog, equal(), ereport, errcode(), errdetail(), errmsg, ERROR, fb(), forboth, Form_pg_propgraph_element, Form_pg_propgraph_element_label, Form_pg_propgraph_label_property, get_propgraph_property_name(), get_rel_name(), GETSTRUCT(), heap_getattr(), HeapTupleIsValid, lappend(), lappend_oid(), lfirst, lfirst_oid, NameStr, NIL, ObjectIdGetDatum(), RelationGetDescr, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and TextDatumGetCString.

Referenced by AlterPropGraph(), and CreatePropGraph().

◆ CreatePropGraph()

ObjectAddress CreatePropGraph ( ParseState pstate,
const CreatePropGraphStmt stmt 
)

Definition at line 104 of file propgraphcmds.c.

105{
108 ListCell *lc;
114
115 if (stmt->pgname->relpersistence == RELPERSISTENCE_UNLOGGED)
118 errmsg("property graphs cannot be unlogged because they do not have storage")));
119
121
122 foreach(lc, stmt->vertex_tables)
123 {
125 struct element_info *vinfo;
126 Relation rel;
127
129 vinfo->kind = PGEKIND_VERTEX;
130
132
133 rel = table_open(vinfo->relid, NoLock);
134
135 if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
137
138 if (vertex->vtable->alias)
139 vinfo->aliasname = vertex->vtable->alias->aliasname;
140 else
141 vinfo->aliasname = vertex->vtable->relname;
142
146 errmsg("alias \"%s\" used more than once as element table", vinfo->aliasname),
147 parser_errposition(pstate, vertex->location)));
148
149 vinfo->key = propgraph_element_get_key(pstate, vertex->vkey, rel, vinfo->aliasname, vertex->location);
150
151 vinfo->labels = vertex->labels;
152
153 table_close(rel, NoLock);
154
156
158 }
159
160 foreach(lc, stmt->edge_tables)
161 {
163 struct element_info *einfo;
164 Relation rel;
165 ListCell *lc2;
170
172 einfo->kind = PGEKIND_EDGE;
173
175
176 rel = table_open(einfo->relid, NoLock);
177
178 if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
180
181 if (edge->etable->alias)
182 einfo->aliasname = edge->etable->alias->aliasname;
183 else
184 einfo->aliasname = edge->etable->relname;
185
189 errmsg("alias \"%s\" used more than once as element table", einfo->aliasname),
190 parser_errposition(pstate, edge->location)));
191
192 einfo->key = propgraph_element_get_key(pstate, edge->ekey, rel, einfo->aliasname, edge->location);
193
194 einfo->srcvertex = edge->esrcvertex;
195 einfo->destvertex = edge->edestvertex;
196
197 srcrelid = 0;
198 destrelid = 0;
199 foreach(lc2, vertex_infos)
200 {
201 struct element_info *vinfo = lfirst(lc2);
202
203 if (strcmp(vinfo->aliasname, edge->esrcvertex) == 0)
204 srcrelid = vinfo->relid;
205
206 if (strcmp(vinfo->aliasname, edge->edestvertex) == 0)
207 destrelid = vinfo->relid;
208
209 if (srcrelid && destrelid)
210 break;
211 }
212 if (!srcrelid)
215 errmsg("source vertex \"%s\" of edge \"%s\" does not exist",
216 edge->esrcvertex, einfo->aliasname),
217 parser_errposition(pstate, edge->location)));
218 if (!destrelid)
221 errmsg("destination vertex \"%s\" of edge \"%s\" does not exist",
222 edge->edestvertex, einfo->aliasname),
223 parser_errposition(pstate, edge->location)));
224
227
228 propgraph_edge_get_ref_keys(pstate, edge->esrckey, edge->esrcvertexcols, rel, srcrel,
229 einfo->aliasname, edge->location, "SOURCE",
230 &einfo->srckey, &einfo->srcref, &einfo->srceqop);
231 propgraph_edge_get_ref_keys(pstate, edge->edestkey, edge->edestvertexcols, rel, destrel,
232 einfo->aliasname, edge->location, "DESTINATION",
233 &einfo->destkey, &einfo->destref, &einfo->desteqop);
234
235 einfo->labels = edge->labels;
236
239
240 table_close(rel, NoLock);
241
243
245 }
246
247 cstmt->relation = stmt->pgname;
248 cstmt->oncommit = ONCOMMIT_NOOP;
249
250 /*
251 * Automatically make it temporary if any component tables are temporary
252 * (see also DefineView()).
253 */
254 if (stmt->pgname->relpersistence == RELPERSISTENCE_PERMANENT
256 {
257 cstmt->relation = copyObject(cstmt->relation);
258 cstmt->relation->relpersistence = RELPERSISTENCE_TEMP;
260 (errmsg("property graph \"%s\" will be temporary",
261 stmt->pgname->relname)));
262 }
263
265
266 foreach(lc, vertex_infos)
267 {
268 struct element_info *vinfo = lfirst(lc);
269 Oid peoid;
270
273 }
274
275 foreach(lc, edge_infos)
276 {
277 struct element_info *einfo = lfirst(lc);
278 Oid peoid;
279 ListCell *lc2;
280
281 /*
282 * Look up the vertices again. Now the vertices have OIDs assigned,
283 * which we need.
284 */
285 foreach(lc2, vertex_infos)
286 {
287 struct element_info *vinfo = lfirst(lc2);
288
289 if (strcmp(vinfo->aliasname, einfo->srcvertex) == 0)
290 {
291 einfo->srcvertexid = vinfo->elementid;
292 einfo->srcrelid = vinfo->relid;
293 }
294 if (strcmp(vinfo->aliasname, einfo->destvertex) == 0)
295 {
296 einfo->destvertexid = vinfo->elementid;
297 einfo->destrelid = vinfo->relid;
298 }
299 if (einfo->srcvertexid && einfo->destvertexid)
300 break;
301 }
302 Assert(einfo->srcvertexid);
303 Assert(einfo->destvertexid);
304 Assert(einfo->srcrelid);
305 Assert(einfo->destrelid);
308 }
309
311
315
316 return pgaddress;
317}
bool list_member(const List *list, const void *datum)
Definition list.c:661
#define copyObject(obj)
Definition nodes.h:232
#define makeNode(_type_)
Definition nodes.h:161
@ ONCOMMIT_NOOP
Definition primnodes.h:59
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition tablecmds.c:784
String * makeString(char *str)
Definition value.c:63

References AccessShareLock, Assert, check_all_labels_properties(), check_element_properties(), CommandCounterIncrement(), copyObject, DefineRelation(), element_info::destrelid, ereport, errcode(), errmsg, ERROR, fb(), foreach_oid, insert_element_record(), InvalidOid, lappend(), lappend_oid(), lfirst, lfirst_node, list_member(), makeNode, makeString(), NIL, NoLock, NOTICE, ONCOMMIT_NOOP, palloc0_object, parser_errposition(), propgraph_edge_get_ref_keys(), propgraph_element_get_key(), RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, element_info::srcrelid, stmt, table_close(), and table_open().

Referenced by ProcessUtilitySlow().

◆ get_edge_oid()

static Oid get_edge_oid ( ParseState pstate,
Oid  pgrelid,
const char alias,
int  location 
)
static

Definition at line 1716 of file propgraphcmds.c.

1717{
1718 HeapTuple tuple;
1719 Oid peoid;
1720
1722 if (!tuple)
1723 ereport(ERROR,
1725 errmsg("property graph \"%s\" has no element with alias \"%s\"",
1726 get_rel_name(pgrelid), alias),
1727 parser_errposition(pstate, location));
1728
1730 ereport(ERROR,
1732 errmsg("element \"%s\" of property graph \"%s\" is not an edge",
1733 alias, get_rel_name(pgrelid)),
1734 parser_errposition(pstate, location));
1735
1736 peoid = ((Form_pg_propgraph_element) GETSTRUCT(tuple))->oid;
1737
1738 ReleaseSysCache(tuple);
1739
1740 return peoid;
1741}
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230

References CStringGetDatum(), ereport, errcode(), errmsg, ERROR, fb(), Form_pg_propgraph_element, get_rel_name(), GETSTRUCT(), ObjectIdGetDatum(), parser_errposition(), ReleaseSysCache(), and SearchSysCache2().

Referenced by AlterPropGraph().

◆ get_element_label_property_names()

◆ get_element_relid()

static Oid get_element_relid ( Oid  peid)
static

Definition at line 1747 of file propgraphcmds.c.

1748{
1749 HeapTuple tuple;
1750 Oid pgerelid;
1751
1753 if (!tuple)
1754 elog(ERROR, "cache lookup failed for property graph element %u", peid);
1755
1757
1758 ReleaseSysCache(tuple);
1759
1760 return pgerelid;
1761}

References elog, ERROR, fb(), Form_pg_propgraph_element, GETSTRUCT(), ObjectIdGetDatum(), ReleaseSysCache(), and SearchSysCache1().

Referenced by AlterPropGraph().

◆ get_graph_label_ids()

static List * get_graph_label_ids ( Oid  graphid)
static

Definition at line 1767 of file propgraphcmds.c.

1768{
1769 Relation rel;
1770 SysScanDesc scan;
1771 ScanKeyData key[1];
1772 HeapTuple tuple;
1773 List *result = NIL;
1774
1776 ScanKeyInit(&key[0],
1779 F_OIDEQ, ObjectIdGetDatum(graphid));
1780 scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, true, NULL, 1, key);
1781 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1782 {
1783 result = lappend_oid(result, ((Form_pg_propgraph_label) GETSTRUCT(tuple))->oid);
1784 }
1785 systable_endscan(scan);
1787
1788 return result;
1789}
END_CATALOG_STRUCT typedef FormData_pg_propgraph_label * Form_pg_propgraph_label

References AccessShareLock, BTEqualStrategyNumber, fb(), Form_pg_propgraph_label, GETSTRUCT(), HeapTupleIsValid, element_info::key, lappend_oid(), NIL, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterPropGraph(), and check_all_labels_properties().

◆ get_graph_property_ids()

static List * get_graph_property_ids ( Oid  graphid)
static

Definition at line 1860 of file propgraphcmds.c.

1861{
1862 Relation rel;
1863 SysScanDesc scan;
1864 ScanKeyData key[1];
1865 HeapTuple tuple;
1866 List *result = NIL;
1867
1869 ScanKeyInit(&key[0],
1872 F_OIDEQ, ObjectIdGetDatum(graphid));
1873 scan = systable_beginscan(rel, PropgraphPropertyNameIndexId, true, NULL, 1, key);
1874 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1875 {
1876 result = lappend_oid(result, ((Form_pg_propgraph_property) GETSTRUCT(tuple))->oid);
1877 }
1878 systable_endscan(scan);
1880
1881 return result;
1882}
END_CATALOG_STRUCT typedef FormData_pg_propgraph_property * Form_pg_propgraph_property

References AccessShareLock, BTEqualStrategyNumber, fb(), Form_pg_propgraph_property, GETSTRUCT(), HeapTupleIsValid, element_info::key, lappend_oid(), NIL, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterPropGraph().

◆ get_label_element_label_ids()

static List * get_label_element_label_ids ( Oid  labelid)
static

◆ get_vertex_oid()

static Oid get_vertex_oid ( ParseState pstate,
Oid  pgrelid,
const char alias,
int  location 
)
static

Definition at line 1684 of file propgraphcmds.c.

1685{
1686 HeapTuple tuple;
1687 Oid peoid;
1688
1690 if (!tuple)
1691 ereport(ERROR,
1693 errmsg("property graph \"%s\" has no element with alias \"%s\"",
1694 get_rel_name(pgrelid), alias),
1695 parser_errposition(pstate, location));
1696
1698 ereport(ERROR,
1700 errmsg("element \"%s\" of property graph \"%s\" is not a vertex",
1701 alias, get_rel_name(pgrelid)),
1702 parser_errposition(pstate, location));
1703
1704 peoid = ((Form_pg_propgraph_element) GETSTRUCT(tuple))->oid;
1705
1706 ReleaseSysCache(tuple);
1707
1708 return peoid;
1709}

References CStringGetDatum(), ereport, errcode(), errmsg, ERROR, fb(), Form_pg_propgraph_element, get_rel_name(), GETSTRUCT(), ObjectIdGetDatum(), parser_errposition(), ReleaseSysCache(), and SearchSysCache2().

Referenced by AlterPropGraph().

◆ insert_element_record()

static Oid insert_element_record ( ObjectAddress  pgaddress,
struct element_info einfo 
)
static

Definition at line 612 of file propgraphcmds.c.

613{
614 Oid graphid = pgaddress.objectId;
615 Relation rel;
616 NameData aliasname;
617 Oid peoid;
619 bool nulls[Natts_pg_propgraph_element] = {0};
623 ObjectAddresses *addrs;
624
626
628 einfo->elementid = peoid;
632 namestrcpy(&aliasname, einfo->aliasname);
638
639 if (einfo->srckey)
641 else
642 nulls[Anum_pg_propgraph_element_pgesrckey - 1] = true;
643 if (einfo->srcref)
645 else
646 nulls[Anum_pg_propgraph_element_pgesrcref - 1] = true;
647 if (einfo->srceqop)
649 else
650 nulls[Anum_pg_propgraph_element_pgesrceqop - 1] = true;
651 if (einfo->destkey)
653 else
654 nulls[Anum_pg_propgraph_element_pgedestkey - 1] = true;
655 if (einfo->destref)
657 else
658 nulls[Anum_pg_propgraph_element_pgedestref - 1] = true;
659 if (einfo->desteqop)
661 else
663
667
669
670 /* Add dependency on the property graph */
672
673 addrs = new_object_addresses();
674
675 /* Add dependency on the relation */
678 array_of_attnums_to_objectaddrs(einfo->relid, einfo->key, addrs);
679
680 /*
681 * Add dependencies on vertices and equality operators used for key
682 * comparison.
683 */
684 if (einfo->srcvertexid)
685 {
688 array_of_attnums_to_objectaddrs(einfo->relid, einfo->srckey, addrs);
689 array_of_attnums_to_objectaddrs(einfo->srcrelid, einfo->srcref, addrs);
690 array_of_opers_to_objectaddrs(einfo->srceqop, addrs);
691 }
692 if (einfo->destvertexid)
693 {
696 array_of_attnums_to_objectaddrs(einfo->relid, einfo->destkey, addrs);
697 array_of_attnums_to_objectaddrs(einfo->destrelid, einfo->destref, addrs);
698 array_of_opers_to_objectaddrs(einfo->desteqop, addrs);
699 }
700
702
703 table_close(rel, NoLock);
704
705 if (einfo->labels)
706 {
707 ListCell *lc;
708
709 foreach(lc, einfo->labels)
710 {
713
714 if (lp->label)
715 ellabeloid = insert_label_record(graphid, peoid, lp->label);
716 else
717 ellabeloid = insert_label_record(graphid, peoid, einfo->aliasname);
718 insert_property_records(graphid, ellabeloid, einfo->relid, lp->properties);
719
721 }
722 }
723 else
724 {
727
728 pr->all = true;
729 pr->location = -1;
730
731 ellabeloid = insert_label_record(graphid, peoid, einfo->aliasname);
732 insert_property_records(graphid, ellabeloid, einfo->relid, pr);
733 }
734
735 return peoid;
736}
static Datum values[MAXATTR]
Definition bootstrap.c:188
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
ObjectAddresses * new_object_addresses(void)
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_NORMAL
Definition dependency.h:33
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1384
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
#define RowExclusiveLock
Definition lockdefs.h:38
void namestrcpy(Name name, const char *str)
Definition name.c:233
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:393
static Datum CharGetDatum(char X)
Definition postgres.h:132
static void array_of_opers_to_objectaddrs(ArrayType *arr, ObjectAddresses *addrs)
static void array_of_attnums_to_objectaddrs(Oid relid, ArrayType *arr, ObjectAddresses *addrs)
Definition c.h:829

References add_exact_object_address(), element_info::aliasname, array_of_attnums_to_objectaddrs(), array_of_opers_to_objectaddrs(), CatalogTupleInsert(), CharGetDatum(), CommandCounterIncrement(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, fb(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), insert_label_record(), insert_property_records(), lfirst_node, makeNode, NameGetDatum(), namestrcpy(), new_object_addresses(), NoLock, ObjectAddressSet, ObjectIdGetDatum(), PointerGetDatum(), record_object_address_dependencies(), recordDependencyOn(), RelationGetDescr, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by AlterPropGraph(), and CreatePropGraph().

◆ insert_label_record()

static Oid insert_label_record ( Oid  graphid,
Oid  peoid,
const char label 
)
static

Definition at line 745 of file propgraphcmds.c.

746{
749
750 /*
751 * Insert into pg_propgraph_label if not already existing.
752 */
754 if (!labeloid)
755 {
756 Relation rel;
758 bool nulls[Natts_pg_propgraph_label] = {0};
763
765
771
775
777
780
781 table_close(rel, NoLock);
782 }
783
784 /*
785 * Insert into pg_propgraph_element_label
786 */
787 {
788 Relation rel;
790 bool nulls[Natts_pg_propgraph_element_label] = {0};
794
796
801
805
807
812
813 table_close(rel, NoLock);
814 }
815
816 return ellabeloid;
817}
static char * label

References CatalogTupleInsert(), CStringGetDatum(), DEPENDENCY_AUTO, fb(), GetNewOidWithIndex(), GetSysCacheOid2, heap_form_tuple(), heap_freetuple(), label, NameGetDatum(), namestrcpy(), NoLock, ObjectAddressSet, ObjectIdGetDatum(), recordDependencyOn(), RelationGetDescr, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by AlterPropGraph(), and insert_element_record().

◆ insert_property_record()

static void insert_property_record ( Oid  graphid,
Oid  ellabeloid,
Oid  pgerelid,
const char propname,
const Expr expr 
)
static

Definition at line 915 of file propgraphcmds.c.

916{
917 Oid propoid;
918 Oid exprtypid = exprType((const Node *) expr);
919 int32 exprtypmod = exprTypmod((const Node *) expr);
920 Oid exprcollation = exprCollation((const Node *) expr);
921
922 /*
923 * Insert into pg_propgraph_property if not already existing.
924 */
926 if (!OidIsValid(propoid))
927 {
928 Relation rel;
931 bool nulls[Natts_pg_propgraph_property] = {0};
935
937
946
950
952
958 {
961 }
962
963 table_close(rel, NoLock);
964 }
965 else
966 {
969 Oid proptypid = pgpform->pgptypid;
970 int32 proptypmod = pgpform->pgptypmod;
971 Oid propcollation = pgpform->pgpcollation;
972
974
975 /*
976 * Check that in the graph, all properties with the same name have the
977 * same type (independent of which label they are on). (See SQL/PGQ
978 * subclause "Consistency check of a tabular property graph
979 * descriptor".)
980 */
982 {
985 errmsg("property \"%s\" data type mismatch: %s vs. %s",
987 errdetail("In a property graph, a property of the same name has to have the same data type in each label."));
988 }
989
990 /* Similarly for collation */
992 {
995 errmsg("property \"%s\" collation mismatch: %s vs. %s",
997 errdetail("In a property graph, a property of the same name has to have the same collation in each label."));
998 }
999 }
1000
1001 /*
1002 * Insert into pg_propgraph_label_property
1003 */
1004 {
1005 Relation rel;
1007 bool nulls[Natts_pg_propgraph_label_property] = {0};
1008 Oid plpoid;
1009 HeapTuple tup;
1012
1014
1020
1022 CatalogTupleInsert(rel, tup);
1024
1026
1029
1032
1034
1035 table_close(rel, NoLock);
1036 }
1037}
#define CStringGetTextDatum(s)
Definition builtins.h:98
int32_t int32
Definition c.h:611
#define OidIsValid(objectId)
Definition c.h:857
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
char * format_type_with_typemod(Oid type_oid, int32 typemod)
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1181
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
char * nodeToString(const void *obj)
Definition outfuncs.c:811
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212

References CatalogTupleInsert(), copyObject, CStringGetDatum(), CStringGetTextDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, ereport, errcode(), errdetail(), errmsg, ERROR, exprCollation(), exprType(), exprTypmod(), fb(), Form_pg_propgraph_property, format_type_with_typemod(), get_collation_name(), GetNewOidWithIndex(), GETSTRUCT(), GetSysCacheOid2, heap_form_tuple(), heap_freetuple(), Int32GetDatum(), NameGetDatum(), namestrcpy(), nodeToString(), NoLock, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), table_open(), and values.

Referenced by insert_property_records().

◆ insert_property_records()

static void insert_property_records ( Oid  graphid,
Oid  ellabeloid,
Oid  pgerelid,
const PropGraphProperties properties 
)
static

Definition at line 823 of file propgraphcmds.c.

824{
825 List *proplist = NIL;
826 ParseState *pstate;
828 List *tp;
829 Relation rel;
830 ListCell *lc;
831
832 if (properties->all)
833 {
835 SysScanDesc scan;
836 ScanKeyData key[1];
838
840 ScanKeyInit(&key[0],
845 true, NULL, 1, key);
847 {
849 ColumnRef *cr;
850 ResTarget *rt;
851
852 if (att->attnum <= 0 || att->attisdropped)
853 continue;
854
857
858 cr->fields = list_make1(makeString(pstrdup(NameStr(att->attname))));
859 cr->location = -1;
860
861 rt->name = pstrdup(NameStr(att->attname));
862 rt->val = (Node *) cr;
863 rt->location = -1;
864
866 }
867 systable_endscan(scan);
869 }
870 else
871 {
872 proplist = properties->properties;
873
874 foreach(lc, proplist)
875 {
877
878 if (!rt->name && !IsA(rt->val, ColumnRef))
881 errmsg("property name required"),
882 parser_errposition(NULL, rt->location));
883 }
884 }
885
887
888 pstate = make_parsestate(NULL);
890 rel,
892 NULL,
893 false,
894 true);
895 addNSItemToQuery(pstate, nsitem, true, true, true);
896
897 table_close(rel, NoLock);
898
900 assign_expr_collations(pstate, (Node *) tp);
901
902 foreach(lc, tp)
903 {
905
906 insert_property_record(graphid, ellabeloid, pgerelid, te->resname, te->expr);
907 }
908}
char * pstrdup(const char *in)
Definition mcxt.c:1781
#define IsA(nodeptr, _type_)
Definition nodes.h:164
void assign_expr_collations(ParseState *pstate, Node *expr)
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
@ EXPR_KIND_PROPGRAPH_PROPERTY
Definition parse_node.h:85
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, LOCKMODE lockmode, Alias *alias, bool inh, bool inFromCl)
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
FormData_pg_attribute * Form_pg_attribute
#define list_make1(x1)
Definition pg_list.h:212
static void insert_property_record(Oid graphid, Oid ellabeloid, Oid pgerelid, const char *propname, const Expr *expr)
Expr * expr
Definition primnodes.h:2264

References AccessShareLock, addNSItemToQuery(), addRangeTableEntryForRelation(), PropGraphProperties::all, assign_expr_collations(), BTEqualStrategyNumber, ereport, errcode(), errmsg, ERROR, TargetEntry::expr, EXPR_KIND_PROPGRAPH_PROPERTY, fb(), GETSTRUCT(), HeapTupleIsValid, insert_property_record(), IsA, element_info::key, lappend(), lfirst_node, list_make1, make_parsestate(), makeNode, makeString(), NameStr, NIL, NoLock, ObjectIdGetDatum(), parser_errposition(), PropGraphProperties::properties, pstrdup(), RowShareLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and transformTargetList().

Referenced by AlterPropGraph(), and insert_element_record().

◆ propgraph_edge_get_ref_keys()

static void propgraph_edge_get_ref_keys ( ParseState pstate,
const List keycols,
const List refcols,
Relation  edge_rel,
Relation  ref_rel,
const char aliasname,
int  location,
const char type,
ArrayType **  outkey,
ArrayType **  outref,
ArrayType **  outeqop 
)
static

Definition at line 371 of file propgraphcmds.c.

375{
376 int nkeys;
379 Oid *keyeqops;
380 Datum *datums;
381
382 Assert((keycols && refcols) || (!keycols && !refcols));
383
384 if (keycols)
385 {
389 errmsg("mismatching number of columns in %s vertex definition of edge \"%s\"", type, aliasname),
390 parser_errposition(pstate, location));
391
392 nkeys = list_length(keycols);
394 refattnums = array_from_column_list(pstate, refcols, location, ref_rel);
395 keyeqops = palloc_array(Oid, nkeys);
396
397 for (int i = 0; i < nkeys; i++)
398 {
399 Oid keytype;
401 Oid keycoll;
402 Oid reftype;
404 Oid refcoll;
405 Oid opc;
406 Oid opf;
407 StrategyNumber strategy;
408
409 /*
410 * Lookup equality operator to be used for edge and vertex key.
411 * Vertex key is equivalent to primary key and edge key is similar
412 * to foreign key since edge key references vertex key. Hence
413 * vertex key is used as left operand and edge key is used as
414 * right operand. The method used to find the equality operators
415 * is similar to the method used to find equality operators for
416 * FK/PK comparison in ATAddForeignKeyConstraint() except that
417 * opclass of the the vertex key type is used as a starting point.
418 * Since we need only equality operators we use both BT and HASH
419 * strategies.
420 *
421 * If the required operators do not exist, we can not construct
422 * quals linking an edge to its adjacent vertexes.
423 */
427 strategy = BTEqualStrategyNumber;
429 if (!OidIsValid(opc))
430 {
432 strategy = HTEqualStrategyNumber;
433 }
434 if (OidIsValid(opc))
435 {
437 if (OidIsValid(opf))
438 {
440 if (!OidIsValid(keyeqops[i]))
441 {
442 /* Last resort, implicit cast. */
445 }
446 }
447 }
448
449 if (!OidIsValid(keyeqops[i]))
452 errmsg("no equality operator exists for %s key comparison of edge \"%s\"",
453 type, aliasname),
454 parser_errposition(pstate, location));
455
456 /*
457 * If collations of key attribute and referenced attribute are
458 * different, an edge may end up being adjacent to undesired
459 * vertexes. Prohibit such a case.
460 *
461 * PK/FK allows different collations as long as they are
462 * deterministic for backward compatibility. But we can be a bit
463 * stricter here and follow SQL standard.
464 */
465 if (keycoll != refcoll &&
470 errmsg("collation mismatch in %s key of edge \"%s\": %s vs. %s",
471 type, aliasname,
473 parser_errposition(pstate, location));
474 }
475 }
476 else
477 {
479
481 {
482 if (tmp->confrelid == RelationGetRelid(ref_rel))
483 {
484 if (fk)
487 errmsg("more than one suitable foreign key exists for %s key of edge \"%s\"", type, aliasname),
488 parser_errposition(pstate, location));
489 fk = tmp;
490 }
491 }
492
493 if (!fk)
496 errmsg("no %s key specified and no suitable foreign key exists for definition of edge \"%s\"", type, aliasname),
497 parser_errposition(pstate, location));
498
499 nkeys = fk->nkeys;
500 keyattnums = fk->conkey;
501 refattnums = fk->confkey;
502 keyeqops = fk->conpfeqop;
503 }
504
507 datums = palloc_array(Datum, nkeys);
508 for (int i = 0; i < nkeys; i++)
509 datums[i] = ObjectIdGetDatum(keyeqops[i]);
510 *outeqop = construct_array_builtin(datums, nkeys, OIDOID);
511}
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition indexcmds.c:2369
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1362
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:170
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition lsyscache.c:1062
bool can_coerce_type(int nargs, const Oid *input_typeids, const Oid *target_typeids, CoercionContext ccontext)
#define foreach_node(type, var, lst)
Definition pg_list.h:496
@ COERCION_IMPLICIT
Definition primnodes.h:747
static AttrNumber * array_from_column_list(ParseState *pstate, const List *colnames, int location, Relation element_rel)
static ArrayType * array_from_attnums(int numattrs, const AttrNumber *attnums)
List * RelationGetFKeyList(Relation relation)
Definition relcache.c:4721
uint16 StrategyNumber
Definition stratnum.h:22
#define HTEqualStrategyNumber
Definition stratnum.h:41
const char * type

References element_info::aliasname, array_from_attnums(), array_from_column_list(), Assert, BTEqualStrategyNumber, can_coerce_type(), COERCION_IMPLICIT, construct_array_builtin(), ereport, errcode(), errmsg, ERROR, fb(), foreach_node, get_atttypetypmodcoll(), get_collation_name(), get_opclass_family(), get_opfamily_member(), GetDefaultOpClass(), HTEqualStrategyNumber, i, InvalidOid, list_length(), ObjectIdGetDatum(), OidIsValid, palloc_array, parser_errposition(), RelationGetFKeyList(), RelationGetRelid, and type.

Referenced by AlterPropGraph(), and CreatePropGraph().

◆ propgraph_element_get_key()

static ArrayType * propgraph_element_get_key ( ParseState pstate,
const List keycols,
Relation  element_rel,
const char aliasname,
int  location 
)
static

Definition at line 325 of file propgraphcmds.c.

326{
327 ArrayType *a;
328
329 if (key_clause == NIL)
330 {
332
333 if (!pkidx)
336 errmsg("no key specified and no suitable primary key exists for definition of element \"%s\"", aliasname),
337 parser_errposition(pstate, location));
338 else
339 {
341
343 a = array_from_attnums(indexDesc->rd_index->indkey.dim1, indexDesc->rd_index->indkey.values);
345 }
346 }
347 else
348 {
350 array_from_column_list(pstate, key_clause, location, element_rel));
351 }
352
353 return a;
354}
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
int a
Definition isn.c:73
Oid RelationGetPrimaryKeyIndex(Relation relation, bool deferrable_ok)
Definition relcache.c:5037

References a, AccessShareLock, element_info::aliasname, array_from_attnums(), array_from_column_list(), ereport, errcode(), errmsg, ERROR, fb(), index_close(), index_open(), list_length(), NIL, NoLock, parser_errposition(), and RelationGetPrimaryKeyIndex().

Referenced by AlterPropGraph(), and CreatePropGraph().