| /* |
| * 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. |
| */ |
| |
| #include "postgres.h" |
| |
| #include "fmgr.h" |
| #include "utils/builtins.h" |
| #include "utils/sortsupport.h" |
| |
| #include "utils/graphid.h" |
| |
| static int graphid_btree_fast_cmp(Datum x, Datum y, SortSupport ssup); |
| |
| /* global storage of OID for graphid and _graphid */ |
| static Oid g_GRAPHIDOID = InvalidOid; |
| static Oid g_GRAPHIDARRAYOID = InvalidOid; |
| |
| /* helper function to quickly set, if necessary, and retrieve GRAPHIDOID */ |
| Oid get_GRAPHIDOID(void) |
| { |
| if (g_GRAPHIDOID == InvalidOid) |
| { |
| g_GRAPHIDOID = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid, |
| CStringGetDatum("graphid"), |
| ObjectIdGetDatum(ag_catalog_namespace_id())); |
| } |
| |
| return g_GRAPHIDOID; |
| } |
| |
| /* helper function to quickly set, if necessary, and retrieve GRAPHIDARRAYOID */ |
| Oid get_GRAPHIDARRAYOID(void) |
| { |
| if (g_GRAPHIDARRAYOID == InvalidOid) |
| { |
| g_GRAPHIDARRAYOID = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid, |
| CStringGetDatum("_graphid"), |
| ObjectIdGetDatum(ag_catalog_namespace_id())); |
| } |
| |
| return g_GRAPHIDARRAYOID; |
| } |
| |
| /* helper function to clear the GRAPHOIDs after a drop extension */ |
| void clear_global_Oids_GRAPHID(void) |
| { |
| g_GRAPHIDOID = InvalidOid; |
| g_GRAPHIDARRAYOID = InvalidOid; |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_in); |
| |
| // graphid type input function |
| Datum graphid_in(PG_FUNCTION_ARGS) |
| { |
| char *str = PG_GETARG_CSTRING(0); |
| char *endptr; |
| int64 i; |
| |
| errno = 0; |
| i = strtol(str, &endptr, 10); |
| if (errno != 0 || endptr == str || *endptr != '\0') |
| { |
| ereport(ERROR, |
| (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
| errmsg("invalid value for type graphid: \"%s\"", str))); |
| } |
| |
| AG_RETURN_GRAPHID(i); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_out); |
| |
| // graphid type output function |
| Datum graphid_out(PG_FUNCTION_ARGS) |
| { |
| graphid gid = AG_GETARG_GRAPHID(0); |
| char buf[32]; // greater than MAXINT8LEN+1 |
| char *out; |
| |
| pg_lltoa(gid, buf); |
| out = pstrdup(buf); |
| |
| PG_RETURN_CSTRING(out); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_eq); |
| |
| Datum graphid_eq(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid == rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_ne); |
| |
| Datum graphid_ne(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid != rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_lt); |
| |
| Datum graphid_lt(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid < rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_gt); |
| |
| Datum graphid_gt(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid > rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_le); |
| |
| Datum graphid_le(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid <= rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_ge); |
| |
| Datum graphid_ge(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| PG_RETURN_BOOL(lgid >= rgid); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_btree_cmp); |
| |
| Datum graphid_btree_cmp(PG_FUNCTION_ARGS) |
| { |
| graphid lgid = AG_GETARG_GRAPHID(0); |
| graphid rgid = AG_GETARG_GRAPHID(1); |
| |
| if (lgid > rgid) |
| PG_RETURN_INT32(1); |
| else if (lgid == rgid) |
| PG_RETURN_INT32(0); |
| else |
| PG_RETURN_INT32(-1); |
| } |
| |
| PG_FUNCTION_INFO_V1(graphid_btree_sort); |
| |
| Datum graphid_btree_sort(PG_FUNCTION_ARGS) |
| { |
| SortSupport ssup = (SortSupport)PG_GETARG_POINTER(0); |
| |
| ssup->comparator = graphid_btree_fast_cmp; |
| PG_RETURN_VOID(); |
| } |
| |
| static int graphid_btree_fast_cmp(Datum x, Datum y, SortSupport ssup) |
| { |
| graphid lgid = DATUM_GET_GRAPHID(x); |
| graphid rgid = DATUM_GET_GRAPHID(y); |
| |
| if (lgid > rgid) |
| return 1; |
| else if (lgid == rgid) |
| return 0; |
| else |
| return -1; |
| } |
| |
| graphid make_graphid(const int32 label_id, const int64 entry_id) |
| { |
| uint64 tmp; |
| |
| if (!label_id_is_valid(label_id)) |
| { |
| ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| errmsg("label_id must be %d .. %d", |
| LABEL_ID_MIN, LABEL_ID_MAX))); |
| } |
| if (!entry_id_is_valid(entry_id)) |
| { |
| ereport(ERROR, |
| (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| errmsg("entry_id must be " INT64_FORMAT " .. " INT64_FORMAT, |
| ENTRY_ID_MIN, ENTRY_ID_MAX))); |
| } |
| |
| tmp = (((uint64)label_id) << ENTRY_ID_BITS) | |
| (((uint64)entry_id) & ENTRY_ID_MASK); |
| |
| return (graphid)tmp; |
| } |
| |
| int32 get_graphid_label_id(const graphid gid) |
| { |
| return (int32)(((uint64)gid) >> ENTRY_ID_BITS); |
| } |
| |
| int64 get_graphid_entry_id(const graphid gid) |
| { |
| return (int64)(((uint64)gid) & ENTRY_ID_MASK); |
| } |
| |
| PG_FUNCTION_INFO_V1(_graphid); |
| |
| Datum _graphid(PG_FUNCTION_ARGS) |
| { |
| int32 label_id; |
| int64 entry_id; |
| graphid gid; |
| |
| if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) |
| { |
| ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| errmsg("label_id and entry_id must not be null"))); |
| } |
| label_id = PG_GETARG_INT32(0); |
| entry_id = PG_GETARG_INT64(1); |
| |
| gid = make_graphid(label_id, entry_id); |
| |
| AG_RETURN_GRAPHID(gid); |
| } |
| |
| //Hashing Function for Hash Indexes |
| PG_FUNCTION_INFO_V1(graphid_hash_cmp); |
| |
| Datum graphid_hash_cmp(PG_FUNCTION_ARGS) |
| { |
| graphid l = AG_GETARG_GRAPHID(0); |
| int hash = (int) ((l >> 32) ^ l);// ^ seed; |
| |
| PG_RETURN_INT32(hash); |
| } |