From ed8f12a6a8a68938cd5bd9a685e442ebfb2074de Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Tue, 19 Sep 2023 16:50:59 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9cgptree=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/gs_cgroup/cgptree.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bin/gs_cgroup/cgptree.cpp b/src/bin/gs_cgroup/cgptree.cpp index 81ad6fdb8..b1cf52e3e 100644 --- a/src/bin/gs_cgroup/cgptree.cpp +++ b/src/bin/gs_cgroup/cgptree.cpp @@ -363,6 +363,7 @@ void cgptree_get_group_info(struct group_info* curr_ginfo, const struct cgroup_m */ static struct group_info* cgptree_get_group_tree(const struct cgroup_mount_point& mount_info) { + /* init the variable */ int curr_depth = -1; int prev_depth = -1; void* tree_handle = NULL; @@ -401,15 +402,15 @@ static struct group_info* cgptree_get_group_tree(const struct cgroup_mount_point while (error != ECGEOF) { /* get the relative path */ rel_path = (char*)(info.full_path + strlen(root_path)); - + /* specific path of the file */ tmpstr = rel_path + sizeof(GSCGROUP_TOP_DATABASE); cm_tmpstr = rel_path + sizeof(GSCGROUP_CM); tmplen = strlen(cgutil_passwd_user->pw_name); if ((CHECK_GSCGROUP_TOP_DATABASE || CHECK_GSCGROUP_CM) && info.type == CGROUP_FILE_TYPE_DIR) { curr_ginfo = (struct group_info*)calloc(1, sizeof(struct group_info)); - - if (curr_ginfo == NULL) + /* when it doesn't exit , create error_report*/ + if (curr_ginfo == NULL) goto error; curr_ginfo->depth = info.depth; -- 2.34.1 From 9a30eec7ac08be0a53344b196cffac399ae8b52f Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Tue, 19 Sep 2023 23:54:33 +0800 Subject: [PATCH 2/7] =?UTF-8?q?cgpdree=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/script/build_opengauss.sh | 4 + contrib/adminpack/adminpack--1.0.sql | 11 +- contrib/adminpack/adminpack.cpp | 169 +++++++++++++++------------ 3 files changed, 106 insertions(+), 78 deletions(-) diff --git a/build/script/build_opengauss.sh b/build/script/build_opengauss.sh index 971fda45f..ab2a72e08 100755 --- a/build/script/build_opengauss.sh +++ b/build/script/build_opengauss.sh @@ -23,6 +23,8 @@ declare binarylib_dir='None' declare make_check='off' declare separate_symbol='on' +# function name: print_help +# Note: this function is used to show the command if you forget function print_help() { echo "Usage: $0 [OPTION] @@ -38,6 +40,8 @@ function print_help() " } +# function name: print_version +# Note: this function is used to show the version the user is using function print_version() { echo $(cat ${SCRIPT_DIR}/gaussdb.ver | grep 'VERSION' | awk -F "=" '{print $2}') diff --git a/contrib/adminpack/adminpack--1.0.sql b/contrib/adminpack/adminpack--1.0.sql index f76f5c3cd..f811da772 100644 --- a/contrib/adminpack/adminpack--1.0.sql +++ b/contrib/adminpack/adminpack--1.0.sql @@ -1,6 +1,6 @@ /* contrib/adminpack/adminpack--1.0.sql */ --- complain if script is sourced in psql, rather than via CREATE EXTENSION +-- check if the script runs in psql, or remind user to use "CREATE EXTENSION adminpack" to run \echo Use "CREATE EXTENSION adminpack" to load this file. \quit /* *********************************************** @@ -8,27 +8,31 @@ * *********************************************** */ /* generic file access functions */ - +-- check the file whether is coverd CREATE FUNCTION pg_catalog.pg_file_write(text, text, bool) RETURNS bigint AS 'MODULE_PATHNAME', 'pg_file_write' LANGUAGE C VOLATILE STRICT; +-- change the name of file CREATE FUNCTION pg_catalog.pg_file_rename(text, text, text) RETURNS bool AS 'MODULE_PATHNAME', 'pg_file_rename' LANGUAGE C VOLATILE; +-- an overloaded version of the definition function CREATE FUNCTION pg_catalog.pg_file_rename(text, text) RETURNS bool AS 'SELECT pg_catalog.pg_file_rename($1, $2, NULL::pg_catalog.text);' LANGUAGE SQL VOLATILE STRICT; +-- delete the file CREATE FUNCTION pg_catalog.pg_file_unlink(text) RETURNS bool AS 'MODULE_PATHNAME', 'pg_file_unlink' LANGUAGE C VOLATILE STRICT; +-- list files in the log directory. CREATE FUNCTION pg_catalog.pg_logdir_ls() RETURNS setof record AS 'MODULE_PATHNAME', 'pg_logdir_ls' @@ -37,16 +41,19 @@ LANGUAGE C VOLATILE STRICT; /* Renaming of existing backend functions for pgAdmin compatibility */ +-- read the contents of the file CREATE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint) RETURNS text AS 'pg_read_file' LANGUAGE INTERNAL VOLATILE STRICT; +-- get the size of the file CREATE FUNCTION pg_catalog.pg_file_length(text) RETURNS bigint AS 'SELECT size FROM pg_catalog.pg_stat_file($1)' LANGUAGE SQL VOLATILE STRICT; +-- manually starting log file rotation. CREATE FUNCTION pg_catalog.pg_logfile_rotate() RETURNS int4 AS 'pg_rotate_logfile' diff --git a/contrib/adminpack/adminpack.cpp b/contrib/adminpack/adminpack.cpp index ceb884e8e..d6065a34a 100644 --- a/contrib/adminpack/adminpack.cpp +++ b/contrib/adminpack/adminpack.cpp @@ -51,8 +51,8 @@ PG_FUNCTION_INFO_V1(pg_file_unlink); PG_FUNCTION_INFO_V1(pg_logdir_ls); typedef struct { - char* location; - DIR* dirdesc; + char *location; + DIR *dirdesc; } directory_fctx; /*----------------------- @@ -65,30 +65,30 @@ typedef struct { * Filename may be absolute or relative to the t_thrd.proc_cxt.DataDir, but we only allow * absolute paths that match t_thrd.proc_cxt.DataDir or u_sess->attr.attr_common.Log_directory. */ -static char* convert_and_check_filename(text* arg, bool logAllowed) +static char *convert_and_check_filename(text *arg, bool logAllowed) { - char* filename = text_to_cstring(arg); + char *filename = text_to_cstring(arg); - canonicalize_path(filename); /* filename can change length here */ + canonicalize_path(filename); /* May change the length of 'filename' */ if (is_absolute_path(filename)) { /* Disallow '/a/b/data/..' */ if (path_contains_parent_reference(filename)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - (errmsg("reference to parent directory (\"..\") not allowed")))); + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("reference to parent directory (\"..\") not allowed")))); /* - * Allow absolute paths if within t_thrd.proc_cxt.DataDir or u_sess->attr.attr_common.Log_directory, even - * though u_sess->attr.attr_common.Log_directory might be outside t_thrd.proc_cxt.DataDir. + * Allow absolute paths if they are within t_thrd.proc_cxt.DataDir or u_sess->attr.attr_common.Log_directory. + * However, if 'logAllowed' is false, absolute paths outside u_sess->attr.attr_common.Log_directory are + * disallowed. */ if (!path_is_prefix_of_path(t_thrd.proc_cxt.DataDir, filename) && (!logAllowed || !is_absolute_path(u_sess->attr.attr_common.Log_directory) || - !path_is_prefix_of_path(u_sess->attr.attr_common.Log_directory, filename))) + !path_is_prefix_of_path(u_sess->attr.attr_common.Log_directory, filename))) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("absolute path not allowed")))); } else if (!path_is_relative_and_below_cwd(filename)) ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("path must be in or below the current directory")))); + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("path must be in or below the current directory")))); return filename; } @@ -99,8 +99,9 @@ static char* convert_and_check_filename(text* arg, bool logAllowed) static void requireSuperuser(void) { if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("only system admin may access generic file functions")))); + // print the ERROR_REPORT + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("only system admin may access generic file functions")))); } /* ------------------------------------ @@ -109,56 +110,67 @@ static void requireSuperuser(void) Datum pg_file_write(PG_FUNCTION_ARGS) { - FILE* f = NULL; - char* filename = NULL; - text* data = NULL; - int64 count = 0; + FILE *f = NULL; // File pointer for file operations + char *filename = NULL; // File name + text *data = NULL; // Data content + int64 count = 0; // Number of bytes written - requireSuperuser(); + requireSuperuser(); // Check if the current user is a superuser, and raise an error if not - filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); - data = PG_GETARG_TEXT_P(1); + filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); // Get and validate the file name + data = PG_GETARG_TEXT_P(1); // Get the data to be written if (!PG_GETARG_BOOL(2)) { struct stat fst; + // Check if the file already exists, and raise an error if it does if (stat(filename, &fst) >= 0) ereport(ERROR, (ERRCODE_DUPLICATE_FILE, errmsg("file \"%s\" exists", filename))); + // Open the file in write mode f = fopen(filename, "wb"); - } else + } else { + // Open the file in append mode f = fopen(filename, "ab"); + } + // Check if the file opening is successful, and raise an error if not if (!f) ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\" for writing: %m", filename))); + // If the data content is not empty, write the data to the file if (VARSIZE(data) != 0) { + // Write the data content to the file and record the number of bytes written count = fwrite(VARDATA(data), 1, VARSIZE(data) - VARHDRSZ, f); + // Check if the write operation is successful, and raise an error if not if (count != VARSIZE(data) - VARHDRSZ) ereport(ERROR, (errcode_for_file_access(), errmsg("could not write file \"%s\": %m", filename))); } - fclose(f); + fclose(f); // Close the file + + // Return the number of bytes successfully written PG_RETURN_INT64(count); } Datum pg_file_rename(PG_FUNCTION_ARGS) { - char *fn1, *fn2, *fn3; - int rc; + char *fn1, *fn2, *fn3; // File name variables + int rc; // Return code for access operation - requireSuperuser(); + requireSuperuser(); // Check if the current user is a superuser, and raise an error if not if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) PG_RETURN_NULL(); - fn1 = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); - fn2 = convert_and_check_filename(PG_GETARG_TEXT_P(1), false); + fn1 = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); // Get and validate the source file name + fn2 = convert_and_check_filename(PG_GETARG_TEXT_P(1), false); // Get and validate the destination file name + if (PG_ARGISNULL(2)) fn3 = 0; else - fn3 = convert_and_check_filename(PG_GETARG_TEXT_P(2), false); + fn3 = convert_and_check_filename(PG_GETARG_TEXT_P(2), false); // Get and validate the backup file name if (access(fn1, W_OK) < 0) { ereport(WARNING, (errcode_for_file_access(), errmsg("file \"%s\" is not accessible: %m", fn1))); @@ -172,7 +184,7 @@ Datum pg_file_rename(PG_FUNCTION_ARGS) PG_RETURN_BOOL(false); } - rc = access(fn3 ? fn3 : fn2, 2); + rc = access(fn3 ? fn3 : fn2, 2); // Check if the target file exists if (rc >= 0 || errno != ENOENT) { ereport(ERROR, (ERRCODE_DUPLICATE_FILE, errmsg("cannot rename to target file \"%s\"", fn3 ? fn3 : fn2))); } @@ -185,8 +197,8 @@ Datum pg_file_rename(PG_FUNCTION_ARGS) ereport(WARNING, (errcode_for_file_access(), errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2))); if (rename(fn3, fn2) != 0) { - ereport( - ERROR, (errcode_for_file_access(), errmsg("could not rename \"%s\" back to \"%s\": %m", fn3, fn2))); + ereport(ERROR, + (errcode_for_file_access(), errmsg("could not rename \"%s\" back to \"%s\": %m", fn3, fn2))); } else { ereport(ERROR, (ERRCODE_UNDEFINED_FILE, errmsg("renaming \"%s\" to \"%s\" was reverted", fn2, fn3))); } @@ -200,111 +212,116 @@ Datum pg_file_rename(PG_FUNCTION_ARGS) Datum pg_file_unlink(PG_FUNCTION_ARGS) { - char* filename = NULL; + char *filename = NULL; // File name variable - requireSuperuser(); + requireSuperuser(); // Check if the current user is a superuser, and raise an error if not - filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); + filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false); // Get and validate the file name if (access(filename, W_OK) < 0) { if (errno == ENOENT) - PG_RETURN_BOOL(false); + PG_RETURN_BOOL(false); // Return false if the file does not exist else ereport(ERROR, (errcode_for_file_access(), errmsg("file \"%s\" is not accessible: %m", filename))); + // Raise an error if the file is not accessible } if (unlink(filename) < 0) { ereport(WARNING, (errcode_for_file_access(), errmsg("could not unlink file \"%s\": %m", filename))); + // Raise a warning with an error code if the file unlinking fails - PG_RETURN_BOOL(false); + PG_RETURN_BOOL(false); // Return false indicating the unlinking operation failed } - PG_RETURN_BOOL(true); + + PG_RETURN_BOOL(true); // Return true to indicate a successful unlinking operation } Datum pg_logdir_ls(PG_FUNCTION_ARGS) { - FuncCallContext* funcctx = NULL; - struct dirent* de; - directory_fctx* fctx = NULL; + FuncCallContext *funcctx = NULL; // Function call context + struct dirent *de; // Directory entry + directory_fctx *fctx = NULL; // Directory context if (!superuser()) - ereport( - ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("only system admin can list the log directory")))); - + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("only system admin can list the log directory")))); + if (strcmp(u_sess->attr.attr_common.Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log") != 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - (errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'")))); - + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'")))); + if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; TupleDesc tupdesc; - + + /* Initialize function call context and memory */ funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - - fctx = (directory_fctx*)palloc(sizeof(directory_fctx)); - + + fctx = (directory_fctx *)palloc(sizeof(directory_fctx)); + + /* Create tuple descriptor */ tupdesc = CreateTemplateTupleDesc(2, false); TupleDescInitEntry(tupdesc, (AttrNumber)1, "starttime", TIMESTAMPOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber)2, "filename", TEXTOID, -1, 0); - + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); - + fctx->location = pstrdup(u_sess->attr.attr_common.Log_directory); fctx->dirdesc = AllocateDir(fctx->location); - + if (!fctx->dirdesc) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read directory \"%s\": %m", fctx->location))); - + funcctx->user_fctx = fctx; (void)MemoryContextSwitchTo(oldcontext); } - + + /* Set up the function call context and directory context */ funcctx = SRF_PERCALL_SETUP(); - fctx = (directory_fctx*)funcctx->user_fctx; - + fctx = (directory_fctx *)funcctx->user_fctx; + + /* Loop through directory entries */ while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL) { - char* values[2]; + char *values[2]; HeapTuple tuple; char timestampbuf[32]; - char* field[MAXDATEFIELDS]; + char *field[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; int dtype; int nf, ftype[MAXDATEFIELDS]; fsec_t fsec; int tz = 0; struct pg_tm date; - + /* * Default format: postgresql-YYYY-MM-DD_HHMMSS.log */ - if (strlen(de->d_name) != 32 || strncmp(de->d_name, "postgresql-", 11) != 0 || de->d_name[21] != '_' || - strcmp(de->d_name + 28, ".log") != 0) + if (strlen(de->d_name) != 32 || strncmp(de->d_name, "postgresql-", 11) != 0 || + de->d_name[21] != '_' || strcmp(de->d_name + 28, ".log") != 0) continue; - - /* extract timestamp portion of filename */ + + /* Extract timestamp portion of filename */ strcpy(timestampbuf, de->d_name + 11); timestampbuf[17] = '\0'; - - /* parse and decode expected timestamp to verify it's OK format */ + + /* Parse and decode expected timestamp to verify it's a valid format */ if (ParseDateTime(timestampbuf, lowstr, MAXDATELEN, field, ftype, MAXDATEFIELDS, &nf)) continue; - + if (DecodeDateTime(field, ftype, nf, &dtype, &date, &fsec, &tz)) continue; - - /* Seems the timestamp is OK; prepare and return tuple */ - + + /* Timestamp is valid; prepare and return tuple */ values[0] = timestampbuf; - values[1] = (char*)palloc(strlen(fctx->location) + strlen(de->d_name) + 2); + values[1] = (char *)palloc(strlen(fctx->location) + strlen(de->d_name) + 2); sprintf(values[1], "%s/%s", fctx->location, de->d_name); - + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); } - + + /* Clean up and return */ FreeDir(fctx->dirdesc); SRF_RETURN_DONE(funcctx); } -- 2.34.1 From b69573e1d85b6bf33bc37bb184f40e79627e5a36 Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Wed, 20 Sep 2023 13:18:51 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E5=85=B3=E4=BA=8Egs=5Fcgroup/main.cpp?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/gs_cgroup/main.cpp | 98 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/src/bin/gs_cgroup/main.cpp b/src/bin/gs_cgroup/main.cpp index a8c0b933f..201149c25 100644 --- a/src/bin/gs_cgroup/main.cpp +++ b/src/bin/gs_cgroup/main.cpp @@ -197,11 +197,10 @@ static int check_percentage_value(int bkd, int grp, int cls, int top) /* fixed mode */ if (cgutil_opt.fixed) { /* - * it is not allowed if more than one group percentage is specified when updating - * cpuset by percentage + * Alert: Fixed mode only allows one group percentage at a time when updating cpuset by percentage. */ if (bkd + cls + top + grp > 1) { - fprintf(stderr, "ERROR: redundant options of cpu core percentage. \n"); + fprintf(stderr, "ERROR: Redundant options for cpu core percentage. \n"); return -1; } else if (bkd + cls + top + grp == 0) { return 0; @@ -209,36 +208,36 @@ static int check_percentage_value(int bkd, int grp, int cls, int top) check_group_name_redundant(bkd, grp, cls, top); - /* check backend percentage, cpuset percentage range is 1-100 */ + /* Check backend percentage. Valid range: 1-100. */ if (cgutil_opt.uflag && bkd) { if (cgutil_opt.bkdpct > 100 || cgutil_opt.bkdpct < 0) { fprintf(stderr, - "ERROR: invalid value for cpu core percentage. " - "its range should be 0-100. \n"); + "ERROR: Invalid value for cpu core percentage. " + "The range should be 0-100. \n"); return -1; } cgutil_opt.setspct = cgutil_opt.bkdpct; cgutil_opt.bkdpct = 0; } - /* check group percentage */ + /* Check group percentage */ if (cgutil_opt.uflag && grp) { if (cgutil_opt.grppct > 100 || cgutil_opt.grppct < 0) { fprintf(stderr, - "ERROR: invalid value for cpu core percentage. " - "its range should be 0-100. \n"); + "ERROR: Invalid value for cpu core percentage. " + "The range should be 0-100. \n"); return -1; } cgutil_opt.setspct = cgutil_opt.grppct; cgutil_opt.grppct = 0; } - /* check class percentage */ + /* Check class percentage */ if (cgutil_opt.uflag && cls) { if (cgutil_opt.clspct > 100 || cgutil_opt.clspct < 0) { fprintf(stderr, - "ERROR: invalid value for cpu core percentage. " - "its range should be 0-100. \n"); + "ERROR: Invalid value for cpu core percentage. " + "The range should be 0-100. \n"); return -1; } cgutil_opt.setspct = cgutil_opt.clspct; @@ -246,50 +245,50 @@ static int check_percentage_value(int bkd, int grp, int cls, int top) cgutil_opt.clssetpct = 1; } - /* check top group percentage */ + /* Check top group percentage */ if (cgutil_opt.uflag && top) { if (cgutil_opt.toppct > 100 || cgutil_opt.toppct < 0) { fprintf(stderr, - "ERROR: invalid value for cpu core percentage. " - "its range should be 0-100. \n"); + "ERROR: Invalid value for cpu core percentage. " + "The range should be 0-100. \n"); return -1; } cgutil_opt.setspct = cgutil_opt.toppct; cgutil_opt.toppct = 0; } - // if user set core percentage is 0, set a flag to show that user set + // Set a flag to indicate that user set core percentage is 0 if (cgutil_opt.setspct == 0) cgutil_opt.setfixed = 1; } else { if ((cgutil_opt.cflag || cgutil_opt.uflag) && bkd && (cgutil_opt.bkdpct >= 100 || cgutil_opt.bkdpct < 1)) { fprintf(stderr, - "ERROR: invalid value for backend group dynamic percentage. " - "its range should be 1 ~ 99!\n"); + "ERROR: Invalid value for backend group dynamic percentage. " + "The range should be 1 ~ 99!\n"); return -1; } - /* check backend percentage */ + /* Check backend percentage */ if ((cgutil_opt.cflag || cgutil_opt.uflag) && grp && (cgutil_opt.grppct >= 100 || cgutil_opt.grppct < 1)) { fprintf(stderr, - "ERROR: invalid value for workload group dynamic percentage. " - "its range should be 1 ~ 99!\n"); + "ERROR: Invalid value for workload group dynamic percentage. " + "The range should be 1 ~ 99!\n"); return -1; } - /* check group percentage */ + /* Check group percentage */ if ((cgutil_opt.cflag || cgutil_opt.uflag) && cls && (cgutil_opt.clspct >= 100 || (cgutil_opt.clspct < 1))) { fprintf(stderr, - "ERROR: invalid value for class group dynamic percentage. " - "its range should be 1 ~ 99!\n"); + "ERROR: Invalid value for class group dynamic percentage. " + "The range should be 1 ~ 99!\n"); return -1; } - /* check class percentage */ + /* Check class percentage */ if ((cgutil_opt.cflag || cgutil_opt.uflag) && top && (cgutil_opt.toppct >= 100 || cgutil_opt.toppct < 1)) { fprintf(stderr, - "ERROR: invalid value for top group dynamic percentage. " - "its range should be 1 ~ 99!\n"); + "ERROR: Invalid value for top group dynamic percentage. " + "The range should be 1 ~ 99!\n"); return -1; } } @@ -348,11 +347,13 @@ static int check_node_group_name() */ static void check_input_for_security(char* input) { - char* danger_token[] = {"|", ";", "&", "$", "<", ">", "`", "\\", "!", "\n", NULL}; + // Array of dangerous tokens + char* danger_token[] = {"|", ";", "&", "$", "<", ">", "`", "\", "!", "\n", NULL}; + // Check if any of the dangerous tokens are present in the input string for (int i = 0; danger_token[i] != NULL; ++i) { if (strstr(input, danger_token[i]) != NULL) { - printf("invalid token \"%s\"\n", danger_token[i]); + printf("Invalid token \"%s\"\n", danger_token[i]); exit(1); } } @@ -413,20 +414,20 @@ static int check_name_valid(void) */ static int check_input_valid(void) { - /* check group name with flag '--fixed' */ + // Check group name with flag '--fixed' if (*cgutil_opt.clsname == '\0' && *cgutil_opt.wdname == '\0' && *cgutil_opt.bkdname == '\0' && *cgutil_opt.topname == '\0' && cgutil_opt.fixed) { fprintf(stderr, "ERROR: Please specify a group name with flag \"--fixed\"\n"); return -1; } - /* check flag '--fixed' and '-u' */ + // Check flag '--fixed' and '-u' if (cgutil_opt.fixed && 0 == cgutil_opt.uflag) { fprintf(stderr, "ERROR: Please specify \'--fixed\' flag together with \'-u\' flag.\n"); return -1; } - /* check group name with flag '-f' */ + // Check group name with flag '-f' if ((*cgutil_opt.clsname || *cgutil_opt.wdname || *cgutil_opt.bkdname || (*cgutil_opt.topname && (0 != strncmp(cgutil_opt.topname, GSCGROUP_TOP_DATABASE, sizeof(GSCGROUP_TOP_DATABASE))))) && @@ -435,43 +436,43 @@ static int check_input_valid(void) return -1; } - /* users cannot use -f and --fixed at the same time */ + // Users cannot use -f and --fixed at the same time if (cgutil_opt.fixed && *cgutil_opt.sets) { fprintf(stderr, "ERROR: Please specify one option from \'-f\',\'--fixed\'.\n"); return -1; } - /* get current mount points */ + // Get current mount points if (cgexec_get_mount_points() < 0) { return -1; } - /* check '-c', '-d', '-u' flag */ + // Check '-c', '-d', '-u' flag if ((cgutil_opt.cflag && cgutil_opt.dflag) || (cgutil_opt.cflag && cgutil_opt.uflag) || (cgutil_opt.uflag && cgutil_opt.dflag)) { fprintf(stderr, "ERROR: please only specify one option from '-c', '-d' and '-u'.\n"); return -1; } - /* check '-e' flag */ + // Check '-e' flag if (IS_EXCEPT_FLAG(cgutil_opt.eflag, EXCEPT_ERROR)) { fprintf(stderr, "ERROR: abort and penalty cannot be specified together!\n"); return -1; } - /* check exception data from '-e' flag */ + // Check exception data from '-e' flag if (cgutil_opt.clsname[0] == '\0' && IS_EXCEPT_FLAG(cgutil_opt.eflag, EXCEPT_PENALTY)) { fprintf(stderr, "ERROR: you must specify a class name with penalty!\n"); return -1; } - /* set default exception data without '--penalty', '--abort' and '-a' flag */ + // Set default exception data without '--penalty', '--abort' and '-a' flag if (*cgutil_opt.edata && IS_EXCEPT_FLAG(cgutil_opt.eflag, EXCEPT_NONE)) { cgutil_opt.eflag = EXCEPT_FLAG(EXCEPT_PENALTY); fprintf(stdout, "NOTICE: if do not specify exceptional action, default is penalty!\n"); } - /* check '--refresh', '--revert' and '--recover' flag */ + // Check '--refresh', '--revert' and '--recover' flag if ((cgutil_opt.cflag || cgutil_opt.dflag || cgutil_opt.uflag) && (cgutil_opt.refresh || cgutil_opt.revert || cgutil_opt.recover)) { fprintf(stderr, @@ -480,7 +481,7 @@ static int check_input_valid(void) return -1; } - /* check '--recover' flag */ + // Check '--recover' flag if ((geteuid() == 0) && cgutil_opt.recover) { fprintf(stderr, "ERROR: you cannpt specify option '--recover' by root user!\n"); return -1; @@ -488,16 +489,17 @@ static int check_input_valid(void) return 0; } - /* * @Description: check user info with flags. * @IN void * @Return: -1: abnormal 0: normal * @See also: */ +// This function checks the user and process information for the cgutil command. +// It ensures that the command is being run with the correct permissions and that the user information is being specified correctly. static int check_user_process(void) { - /* check root user process */ + // Check if running as root user and user info is missing for certain flags if ((geteuid() == 0) && ((cgutil_opt.cflag || cgutil_opt.display || cgutil_opt.uflag || cgutil_opt.dflag) && cgutil_opt.user[0] == '\0')) { fprintf(stderr, @@ -506,13 +508,13 @@ static int check_user_process(void) return -1; } - /* check non-root user process */ + // Check if running as non-root user and user info is specified if (geteuid() && cgutil_opt.user[0] != '\0') { fprintf(stderr, "ERROR: you can't specify the user name while running as non-root user.\n"); return -1; } - /* check user info for '-P' flag */ + // Check if running as root user and user info is missing for '-P' flag if (0 == geteuid() && cgutil_opt.ptree && '\0' == *cgutil_opt.user) { fprintf(stderr, "ERROR: you must specify the user name when running as root user " @@ -520,7 +522,7 @@ static int check_user_process(void) return -1; } - /* check non-root user info for '-M' flag */ + // Check if running as non-root user and trying to mount or unmount cgroup if ((cgutil_opt.mflag || cgutil_opt.umflag) && geteuid()) { fprintf(stderr, "ERROR: you must run mount or umount cgroup by root user!\n"); return -1; @@ -537,7 +539,7 @@ static int check_user_process(void) */ static int check_flag_process(void) { - /* create flag process */ + // Check if creating a cgroup and validate group and class names if (cgutil_opt.cflag) { /* check top and backend group name */ if (cgutil_opt.topname[0] != '\0' || cgutil_opt.bkdname[0] != '\0') { @@ -561,7 +563,7 @@ static int check_flag_process(void) } } - /* delete flag process */ + // Check if deleting a cgroup and validate group and class names if (cgutil_opt.dflag) { /* check top and backend group name */ if (cgutil_opt.topname[0] != '\0' || cgutil_opt.bkdname[0] != '\0') { @@ -572,7 +574,7 @@ static int check_flag_process(void) } } - /* update flag process */ + // Check if updating a cgroup and validate group and class names if (cgutil_opt.uflag && ('\0' == cgutil_opt.topname[0] && '\0' == cgutil_opt.bkdname[0] && '\0' == cgutil_opt.clsname[0])) { fprintf(stderr, "ERROR: please specify the Group name when updating!\n"); -- 2.34.1 From 18d7731b5e56e414d19611ac1a0b8843f672e593 Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Wed, 20 Sep 2023 14:25:22 +0800 Subject: [PATCH 4/7] =?UTF-8?q?btree=5Finet.cpp=E4=BB=A3=E7=A0=81=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/auto_explain/auto_explain.cpp | 4 +++- src/bin/gs_cgroup/main.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/contrib/auto_explain/auto_explain.cpp b/contrib/auto_explain/auto_explain.cpp index 2eaf18bed..a59829b90 100644 --- a/contrib/auto_explain/auto_explain.cpp +++ b/contrib/auto_explain/auto_explain.cpp @@ -72,7 +72,7 @@ void _PG_init(void) NULL, NULL, NULL); - + // Define common Boolean variables DefineCustomBoolVariable("auto_explain.log_analyze", "Use EXPLAIN ANALYZE for plan logging.", NULL, @@ -84,6 +84,7 @@ void _PG_init(void) NULL, NULL); + // Define common Boolean variables of auto_explain.log_verbose DefineCustomBoolVariable("auto_explain.log_verbose", "Use EXPLAIN VERBOSE for plan logging.", NULL, @@ -95,6 +96,7 @@ void _PG_init(void) NULL, NULL); + // Define common Boolean variables of auto_explain.log_buffers DefineCustomBoolVariable("auto_explain.log_buffers", "Log buffers usage.", NULL, diff --git a/src/bin/gs_cgroup/main.cpp b/src/bin/gs_cgroup/main.cpp index 201149c25..c0baa05cf 100644 --- a/src/bin/gs_cgroup/main.cpp +++ b/src/bin/gs_cgroup/main.cpp @@ -827,7 +827,7 @@ static int check_cpuset_value_valid(char* cpuset) return -1; } } - + // check the value if ((a < 0) || (b < 0) || (a > b) || (b >= cgutil_cpucnt)) { fprintf(stderr, "ERROR: please specify the cpuset with a valid value.\n"); return -1; @@ -845,6 +845,7 @@ static int check_cpuset_value_valid(char* cpuset) * @Return: 1: OK 0: Not OK * @See also: */ +// check configuration static int check_config_flag(void) { if (cgutil_opt.cflag || (cgutil_opt.dflag && (*cgutil_opt.clsname || *cgutil_opt.nodegroup)) || cgutil_opt.uflag || @@ -861,6 +862,7 @@ static int check_config_flag(void) * @Return: -1: abnormal 0: normal * @See also: */ +// initialize the configuration static int initialize_cgroup_config(void) { char* hpath = NULL; @@ -907,6 +909,7 @@ static int initialize_cgroup_config(void) * @Return: -1: abnormal 0: normal * @See also: */ +// check the configuration status static int check_and_get_group_percent(char* percent, char* gtype) { char* bad = NULL; @@ -943,6 +946,7 @@ static int check_and_get_group_percent(char* percent, char* gtype) * -1: abnormal * 0: normal */ +// structure of long options static struct option long_options[] = {{"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {"abort", no_argument, NULL, 'a'}, @@ -956,6 +960,7 @@ static struct option long_options[] = {{"help", no_argument, NULL, 'h'}, {"rename", no_argument, NULL, 7}, {NULL, 0, NULL, 0}}; +// match the choice static int parse_options(int argc, char** argv) { int c; @@ -1166,7 +1171,7 @@ int main(int argc, char** argv) " or \"/sys/devices/system\" is acceptable. \n"); exit(-1); } - + // set the style of string int rc = sprintf_s(cgutil_allset, sizeof(cgutil_allset), "%d-%d", 0, cgutil_cpucnt - 1); securec_check_intval(rc, , -1); -- 2.34.1 From 0ff71e4c79aa20476163f26b55b5b0c0ab99e233 Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Fri, 22 Sep 2023 00:16:29 +0800 Subject: [PATCH 5/7] btree-gist --- contrib/btree_gist/btree_bit.cpp | 54 +++- contrib/btree_gist/btree_gist.cpp | 86 +++---- contrib/btree_gist/btree_inet.cpp | 11 + contrib/btree_gist/btree_int2.cpp | 27 ++ contrib/btree_gist/btree_int4.cpp | 354 +++++++++++++++------------ contrib/btree_gist/btree_int8.cpp | 12 + contrib/btree_gist/btree_numeric.cpp | 230 ++++++++++------- 7 files changed, 488 insertions(+), 286 deletions(-) diff --git a/contrib/btree_gist/btree_bit.cpp b/contrib/btree_gist/btree_bit.cpp index cbc1e1940..1f4b3adf9 100644 --- a/contrib/btree_gist/btree_bit.cpp +++ b/contrib/btree_gist/btree_bit.cpp @@ -87,10 +87,13 @@ static GBT_VARKEY* gbt_bit_l2n(GBT_VARKEY* leaf) static const gbtree_vinfo tinfo = { gbt_t_bit, 0, TRUE, gbt_bitgt, gbt_bitge, gbt_biteq, gbt_bitle, gbt_bitlt, gbt_bitcmp, gbt_bit_l2n}; -/************************************************** - * Bit ops - **************************************************/ - +/* + * This function compresses a GIST entry using variable-length bitstrings. + * The input is a pointer to a GISTENTRY struct. + * The output is a pointer to the compressed data, which is obtained by calling + * the gbt_var_compress function with the GISTENTRY pointer and a pointer to + * the tinfo struct. + */ Datum gbt_bit_compress(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -98,6 +101,20 @@ Datum gbt_bit_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); } +/* + * This function checks if a GIST entry is consistent with a query using + * variable-length bitstrings. The input is a pointer to a GISTENTRY struct, + * a pointer to the query data, and a strategy number. The output is a boolean + * value indicating whether the entry is consistent with the query. + * + * The function also sets a flag indicating whether a recheck is needed, but + * this flag is always set to false for all cases served by this function. + * + * If the entry is a leaf node, the function calls gbt_var_consistent with + * the readable key of the entry and the query data. Otherwise, the function + * transforms the query data using gbt_bit_xfrm and calls gbt_var_consistent + * with the readable key of the entry and the transformed query data. + */ Datum gbt_bit_consistent(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -122,6 +139,15 @@ Datum gbt_bit_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } +/* + * This function performs a union of a set of GIST entries using + * variable-length bitstrings. The input is a pointer to a GistEntryVector + * struct and a pointer to an integer that will hold the size of the resulting + * union. The output is a pointer to the union of the entries. + * + * The function calls gbt_var_union with the GistEntryVector, the collation, + * and a pointer to the tinfo struct. + */ Datum gbt_bit_union(PG_FUNCTION_ARGS) { GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); @@ -130,6 +156,16 @@ Datum gbt_bit_union(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(), &tinfo)); } +/* + * This function performs a picksplit operation on a set of GIST entries using + * variable-length bitstrings. The input is a pointer to a GistEntryVector + * struct and a pointer to a GIST_SPLITVEC struct that will hold the results + * of the picksplit operation. The output is a pointer to the GIST_SPLITVEC + * struct. + * + * The function calls gbt_var_picksplit with the GistEntryVector, the GIST_SPLITVEC + * struct, the collation, and a pointer to the tinfo struct. + */ Datum gbt_bit_picksplit(PG_FUNCTION_ARGS) { GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); @@ -139,6 +175,16 @@ Datum gbt_bit_picksplit(PG_FUNCTION_ARGS) PG_RETURN_POINTER(v); } +/* + * This function checks if two variable-length bitstrings are the same. The input + * is two Datums representing the bitstrings and a pointer to a boolean variable + * that will hold the result of the comparison. The output is a pointer to the + * boolean variable. + * + * The function calls gbt_var_same with the two Datums, the collation, and a + * pointer to the tinfo struct. The result of the comparison is stored in the + * boolean variable pointed to by the input argument. + */ Datum gbt_bit_same(PG_FUNCTION_ARGS) { Datum d1 = PG_GETARG_DATUM(0); diff --git a/contrib/btree_gist/btree_gist.cpp b/contrib/btree_gist/btree_gist.cpp index 11c7e9351..adbdf25a3 100644 --- a/contrib/btree_gist/btree_gist.cpp +++ b/contrib/btree_gist/btree_gist.cpp @@ -1,43 +1,43 @@ -/* - * contrib/btree_gist/btree_gist.c - */ -#include "postgres.h" -#include "knl/knl_variable.h" - -#include "btree_gist.h" - -PG_MODULE_MAGIC; - -PG_FUNCTION_INFO_V1(gbt_decompress); -PG_FUNCTION_INFO_V1(gbtreekey_in); -PG_FUNCTION_INFO_V1(gbtreekey_out); - -extern "C" Datum gbt_decompress(PG_FUNCTION_ARGS); - -/************************************************** - * In/Out for keys - **************************************************/ - -Datum gbtreekey_in(PG_FUNCTION_ARGS) -{ - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_in() not implemented"))); - - PG_RETURN_POINTER(NULL); -} - -#include "btree_utils_var.h" -#include "utils/builtins.h" -Datum gbtreekey_out(PG_FUNCTION_ARGS) -{ - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_out() not implemented"))); - PG_RETURN_POINTER(NULL); -} - -/* -** GiST DeCompress methods -** do not do anything. -*/ -Datum gbt_decompress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} +/* + * contrib/btree_gist/btree_gist.c + */ +#include "postgres.h" // Include the PostgreSQL database header file +#include "knl/knl_variable.h" // Include the knl_variable.h header file, which may contain internal variable definitions + +#include "btree_gist.h" // Include the btree_gist.h header file, which defines the data structures and function prototypes required for B-tree GiST indexing + +PG_MODULE_MAGIC; // Macro definition to identify this as a PostgreSQL module + +PG_FUNCTION_INFO_V1(gbt_decompress); // Macro definition to declare a PostgreSQL function, gbt_decompress, with version 1 information +PG_FUNCTION_INFO_V1(gbtreekey_in); // Macro definition to declare a PostgreSQL function, gbtreekey_in, with version 1 information +PG_FUNCTION_INFO_V1(gbtreekey_out); // Macro definition to declare a PostgreSQL function, gbtreekey_out, with version 1 information + +extern "C" Datum gbt_decompress(PG_FUNCTION_ARGS); // Define a C function named gbt_decompress that returns a Datum type and accepts PG_FUNCTION_ARGS parameters + +/************************************************** + * In/Out for keys + **************************************************/ + +Datum gbtreekey_in(PG_FUNCTION_ARGS) // Define a function named gbtreekey_in that returns a Datum type and accepts PG_FUNCTION_ARGS parameters +{ + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_in() not implemented"))); // If the function is called, output an error message indicating that the feature is not supported + + PG_RETURN_POINTER(NULL); // Return a null pointer, indicating that there is no return value +} + +#include "btree_utils_var.h" // Include the btree_utils_var.h header file, which may contain auxiliary functions and variables related to B-trees +#include "utils/builtins.h" // Include the builtins.h header file, which may contain definitions related to built-in functions +Datum gbtreekey_out(PG_FUNCTION_ARGS) // Define the gbtreekey_out function, which converts internal keys to output form and returns a Datum type result +{ + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_out() not implemented"))); // If the function is called, output an error message indicating that the feature is not supported + PG_RETURN_POINTER(NULL); // Return a null pointer, indicating that there is no return value +} + +/* +** GiST DeCompress methods +** do not do anything. +*/ +Datum gbt_decompress(PG_FUNCTION_ARGS) // Define the gbt_decompress function, which decompresses GiST keys and returns a Datum type result +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); // Directly return the pointer to the input argument as the result, without performing any decompression operations +} \ No newline at end of file diff --git a/contrib/btree_gist/btree_inet.cpp b/contrib/btree_gist/btree_inet.cpp index 1a05e7028..f36431f34 100644 --- a/contrib/btree_gist/btree_inet.cpp +++ b/contrib/btree_gist/btree_inet.cpp @@ -138,6 +138,17 @@ Datum gbt_inet_picksplit(PG_FUNCTION_ARGS) gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); } +/* + function name: gbt_inet_same + description: + This function checks whether two inet keys are equal. The input is two + inetKEY pointers representing the keys to compare, and a pointer to a boolean + to hold the result. The output is a pointer to the boolean result. + The function calls gbt_num_same with the two keys and a pointer to the tinfo + struct. The result of the comparison is stored in the result pointer and + returned. + +*/ Datum gbt_inet_same(PG_FUNCTION_ARGS) { inetKEY* b1 = (inetKEY*)PG_GETARG_POINTER(0); diff --git a/contrib/btree_gist/btree_int2.cpp b/contrib/btree_gist/btree_int2.cpp index 3a69b3922..a40a3cea1 100644 --- a/contrib/btree_gist/btree_int2.cpp +++ b/contrib/btree_gist/btree_int2.cpp @@ -132,6 +132,21 @@ Datum gbt_int2_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); } +/* +function name: gbt_int2_distance +description: + This function calculates the distance between an int2 key and a query value. + The input is a GISTENTRY pointer representing the key, and an int16 value + representing the query. The output is a float8 value representing the + distance between the key and the query. + + The function extracts the lower and upper bounds of the int2 key and stores + them in a GBT_NUMKEY_R struct. It then calls gbt_num_distance with the key, + the query value, a boolean indicating whether the key is a leaf node, and a + pointer to the tinfo struct. The result of the distance calculation is + returned as a float8 value. + +*/ Datum gbt_int2_distance(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -172,6 +187,18 @@ Datum gbt_int2_picksplit(PG_FUNCTION_ARGS) gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); } +/* +function name: gbt_int2_same +description: + This function checks whether two int2 keys are the same. + The input is two pointers to int16KEY structs representing the keys, + and a pointer to a boolean variable to store the result. + The output is a pointer to the boolean variable. + + The function calls gbt_num_same with the two keys, and a pointer to the tinfo + struct. The result of the comparison is stored in the boolean variable + pointed to by the result argument, and a pointer to this variable is returned. +*/ Datum gbt_int2_same(PG_FUNCTION_ARGS) { int16KEY* b1 = (int16KEY*)PG_GETARG_POINTER(0); diff --git a/contrib/btree_gist/btree_int4.cpp b/contrib/btree_gist/btree_int4.cpp index e07cf529d..ff3295f7e 100644 --- a/contrib/btree_gist/btree_int4.cpp +++ b/contrib/btree_gist/btree_int4.cpp @@ -15,169 +15,211 @@ typedef struct int32key { /* ** int32 ops */ -PG_FUNCTION_INFO_V1(gbt_int4_compress); -PG_FUNCTION_INFO_V1(gbt_int4_union); -PG_FUNCTION_INFO_V1(gbt_int4_picksplit); -PG_FUNCTION_INFO_V1(gbt_int4_consistent); -PG_FUNCTION_INFO_V1(gbt_int4_distance); -PG_FUNCTION_INFO_V1(gbt_int4_penalty); -PG_FUNCTION_INFO_V1(gbt_int4_same); - -extern "C" Datum gbt_int4_compress(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_union(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_picksplit(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_consistent(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_distance(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_penalty(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int4_same(PG_FUNCTION_ARGS); - -static bool gbt_int4gt(const void* a, const void* b) -{ - return (*((const int32*)a) > *((const int32*)b)); -} -static bool gbt_int4ge(const void* a, const void* b) -{ - return (*((const int32*)a) >= *((const int32*)b)); -} -static bool gbt_int4eq(const void* a, const void* b) -{ - return (*((const int32*)a) == *((const int32*)b)); -} -static bool gbt_int4le(const void* a, const void* b) -{ - return (*((const int32*)a) <= *((const int32*)b)); -} -static bool gbt_int4lt(const void* a, const void* b) -{ - return (*((const int32*)a) < *((const int32*)b)); +// Define a set of function info macros for the different GiST functions. +PG_FUNCTION_INFO_V1(gbt_int4_compress); // Compress function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_union); // Union function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_picksplit); // Picksplit function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_consistent);// Consistent function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_distance); // Distance function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_penalty); // Penalty function for GiST index. +PG_FUNCTION_INFO_V1(gbt_int4_same); // Same function for GiST index. + +// Declare the different GiST functions. +extern "C" Datum gbt_int4_compress(PG_FUNCTION_ARGS); // Compress function. +extern "C" Datum gbt_int4_union(PG_FUNCTION_ARGS); // Union function. +extern "C" Datum gbt_int4_picksplit(PG_FUNCTION_ARGS); // Picksplit function. +extern "C" Datum gbt_int4_consistent(PG_FUNCTION_ARGS);// Consistent function. +extern "C" Datum gbt_int4_distance(PG_FUNCTION_ARGS); // Distance function. +extern "C" Datum gbt_int4_penalty(PG_FUNCTION_ARGS); // Penalty function. +extern "C" Datum gbt_int4_same(PG_FUNCTION_ARGS); // Same function. + +// Define a set of comparison functions for integers. +static bool gbt_int4gt(const void* a, const void* b) // Greater than comparison. +{ + return (*((const int32*)a) > *((const int32*)b)); +} +static bool gbt_int4ge(const void* a, const void* b) // Greater than or equal to comparison. +{ + return (*((const int32*)a) >= *((const int32*)b)); +} +static bool gbt_int4eq(const void* a, const void* b) // Equal to comparison. +{ + return (*((const int32*)a) == *((const int32*)b)); +} +static bool gbt_int4le(const void* a, const void* b) // Less than or equal to comparison. +{ + return (*((const int32*)a) <= *((const int32*)b)); +} +static bool gbt_int4lt(const void* a, const void* b) // Less than comparison. +{ + return (*((const int32*)a) < *((const int32*)b)); } -static int gbt_int4key_cmp(const void* a, const void* b) -{ - int32KEY* ia = (int32KEY*)(((const Nsrt*)a)->t); - int32KEY* ib = (int32KEY*)(((const Nsrt*)b)->t); - - if (ia->lower == ib->lower) { - if (ia->upper == ib->upper) - return 0; - - return (ia->upper > ib->upper) ? 1 : -1; - } - - return (ia->lower > ib->lower) ? 1 : -1; +// Define a function that compares two integer keys. +static int gbt_int4key_cmp(const void* a, const void* b) +{ + // Cast the input pointers to their actual types. + int32KEY* ia = (int32KEY*)(((const Nsrt*)a)->t); + int32KEY* ib = (int32KEY*)(((const Nsrt*)b)->t); + + // Compare the lower bounds first. If they are equal... + if (ia->lower == ib->lower) { + // Compare the upper bounds. If they are equal... + if (ia->upper == ib->upper) + return 0; // Return 0 if both are equal. + + // Return 1 or -1 depending on which upper bound is greater. + return (ia->upper > ib->upper) ? 1 : -1; + } + + // Return 1 or -1 depending on which lower bound is greater. + return (ia->lower > ib->lower) ? 1 : -1; +} + +// Define a function that calculates the distance between two integer keys. +static float8 gbt_int4_dist(const void* a, const void* b) +{ + // Use a macro to calculate the distance between the two integers. + return GET_FLOAT_DISTANCE(int4, a, b); +} + +// Define a structure with information about the integer keys. +static const gbtree_ninfo tinfo = {gbt_t_int4, + sizeof(int32), + gbt_int4gt, + gbt_int4ge, + gbt_int4eq, + gbt_int4le, + gbt_int4lt, + gbt_int4key_cmp, + gbt_int4_dist}; + +// Declare the function that will calculate the distance between two integers. +PG_FUNCTION_INFO_V1(int4_dist); +extern "C" Datum int4_dist(PG_FUNCTION_ARGS); +Datum int4_dist(PG_FUNCTION_ARGS) +{ + // Get the two integer arguments. + int4 a = PG_GETARG_INT32(0); + int4 b = PG_GETARG_INT32(1); + int4 r; + int4 ra; + + // Calculate the difference between the two integers. + r = a - b; + ra = Abs(r); // Calculate the absolute value of the difference. + + /* Check for overflow. */ + if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a))) + ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); // Report an error if there is an overflow. + + // Return the absolute value of the difference. + PG_RETURN_INT32(ra); } - -static float8 gbt_int4_dist(const void* a, const void* b) -{ - return GET_FLOAT_DISTANCE(int4, a, b); -} - -static const gbtree_ninfo tinfo = {gbt_t_int4, - sizeof(int32), - gbt_int4gt, - gbt_int4ge, - gbt_int4eq, - gbt_int4le, - gbt_int4lt, - gbt_int4key_cmp, - gbt_int4_dist}; - -PG_FUNCTION_INFO_V1(int4_dist); -extern "C" Datum int4_dist(PG_FUNCTION_ARGS); -Datum int4_dist(PG_FUNCTION_ARGS) -{ - int4 a = PG_GETARG_INT32(0); - int4 b = PG_GETARG_INT32(1); - int4 r; - int4 ra; - - r = a - b; - ra = Abs(r); - - /* Overflow check. */ - if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a))) - ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); - - PG_RETURN_INT32(ra); -} - /************************************************** * int32 ops **************************************************/ -Datum gbt_int4_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +// Define a function that compresses a GiST entry. +Datum gbt_int4_compress(PG_FUNCTION_ARGS) +{ + // Get the GiST entry from the function arguments. + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + GISTENTRY* retval = NULL; + + // Compress the GiST entry and return the result. + PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +} + +// Define a function that checks if a GiST entry is consistent with a query value. +Datum gbt_int4_consistent(PG_FUNCTION_ARGS) +{ + // Get the GiST entry, query value, strategy number, and output buffer from the function arguments. + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + int32 query = PG_GETARG_INT32(1); + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + bool* recheck = (bool*)PG_GETARG_POINTER(4); + int32KEY* kkk = (int32KEY*)DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + // Set the recheck flag to false, indicating that all cases served by this function are exact. + /* All cases served by this function are exact */ + *recheck = false; + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + // Check if the GiST entry is consistent with the query value and return the result. + PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); } -Datum gbt_int4_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - int32 query = PG_GETARG_INT32(1); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - int32KEY* kkk = (int32KEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - /* All cases served by this function are exact */ - *recheck = false; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_int4_distance(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - int32 query = PG_GETARG_INT32(1); - - int32KEY* kkk = (int32KEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_int4_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - void* out = palloc(sizeof(int32KEY)); - - *(int*)PG_GETARG_POINTER(1) = sizeof(int32KEY); - PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); -} - -Datum gbt_int4_penalty(PG_FUNCTION_ARGS) -{ - int32KEY* origentry = (int32KEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); - int32KEY* newentry = (int32KEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); - float* result = (float*)PG_GETARG_POINTER(2); - - penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - PG_RETURN_POINTER(result); -} - -Datum gbt_int4_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER( - gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); -} - -Datum gbt_int4_same(PG_FUNCTION_ARGS) -{ - int32KEY* b1 = (int32KEY*)PG_GETARG_POINTER(0); - int32KEY* b2 = (int32KEY*)PG_GETARG_POINTER(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); - PG_RETURN_POINTER(result); +// Define a function that calculates the distance between two GiST entries. +Datum gbt_int4_distance(PG_FUNCTION_ARGS) +{ + // Get the GiST entry and query value from the function arguments. + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + int32 query = PG_GETARG_INT32(1); + + // Extract the lower and upper bounds from the GiST entry. + int32KEY* kkk = (int32KEY*)DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + // Calculate and return the distance between the GiST entry and the query value. + PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); +} + +// Define a function that calculates the union of a set of GiST entries. +Datum gbt_int4_union(PG_FUNCTION_ARGS) +{ + // Get the vector of GiST entries and output buffer from the function arguments. + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + void* out = palloc(sizeof(int32KEY)); + + // Set the size of the output buffer. + *(int*)PG_GETARG_POINTER(1) = sizeof(int32KEY); + + // Calculate and return the union of the set of GiST entries. + PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); +} + +// Define a function that calculates the penalty for splitting a set of GiST entries. +Datum gbt_int4_penalty(PG_FUNCTION_ARGS) +{ + // Get the original and new GiST entries, as well as the output buffer, from the function arguments. + int32KEY* origentry = (int32KEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); + int32KEY* newentry = (int32KEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); + float* result = (float*)PG_GETARG_POINTER(2); + + // Calculate the penalty for splitting the set of GiST entries. + penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper); + + // Return the calculated penalty. + PG_RETURN_POINTER(result); +} + +// Define a function that selects which GiST entries to split. +Datum gbt_int4_picksplit(PG_FUNCTION_ARGS) +{ + // Select which GiST entries to split and return the result. + PG_RETURN_POINTER( + gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); +} + +// Define a function that checks if two GiST entries are equal. +Datum gbt_int4_same(PG_FUNCTION_ARGS) +{ + // Get the two GiST entries and output buffer from the function arguments. + int32KEY* b1 = (int32KEY*)PG_GETARG_POINTER(0); + int32KEY* b2 = (int32KEY*)PG_GETARG_POINTER(1); + bool* result = (bool*)PG_GETARG_POINTER(2); + + // Check if the two GiST entries are equal and store the result in the output buffer. + *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); + + // Return the output buffer. + PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_int8.cpp b/contrib/btree_gist/btree_int8.cpp index 14e373a50..6749efea7 100644 --- a/contrib/btree_gist/btree_int8.cpp +++ b/contrib/btree_gist/btree_int8.cpp @@ -172,6 +172,18 @@ Datum gbt_int8_picksplit(PG_FUNCTION_ARGS) gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); } +/* +function name: gbt_int8_same +description: + This function checks whether two int8 keys are the same. + The input is two pointers to int64KEY structs representing the keys, + and a pointer to a boolean variable to store the result. + The output is a pointer to the boolean variable. + + The function calls gbt_num_same with the two keys, and a pointer to the tinfo + struct. The result of the comparison is stored in the boolean variable + pointed to by the result argument, and a pointer to this variable is returned. +*/ Datum gbt_int8_same(PG_FUNCTION_ARGS) { int64KEY* b1 = (int64KEY*)PG_GETARG_POINTER(0); diff --git a/contrib/btree_gist/btree_numeric.cpp b/contrib/btree_gist/btree_numeric.cpp index 18542a2ca..fcec9d536 100644 --- a/contrib/btree_gist/btree_numeric.cpp +++ b/contrib/btree_gist/btree_numeric.cpp @@ -87,95 +87,159 @@ Datum gbt_numeric_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); } -Datum gbt_numeric_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - void* query = (void*)DatumGetNumeric(PG_GETARG_DATUM(1)); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - bool retval = false; - GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); - GBT_VARKEY_R r = gbt_var_key_readable(key); - - /* All cases served by this function are exact */ - *recheck = false; - - retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); - PG_RETURN_BOOL(retval); +// Function to check consistency of a numeric value with a GIST entry +Datum gbt_numeric_consistent(PG_FUNCTION_ARGS) +{ + // Pointer to the GIST entry + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + + // The numeric value to be checked + void* query = (void*)DatumGetNumeric(PG_GETARG_DATUM(1)); + + // The strategy number representing the strategy to be used + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + // Pointer to a boolean variable that indicates whether a recheck is necessary + bool* recheck = (bool*)PG_GETARG_POINTER(4); + + // The return value, initialized to false + bool retval = false; + + // Pointer to the key of the GIST entry, converted to a GBT_VARKEY* + GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); + + // The readable representation of the GBT_VARKEY + GBT_VARKEY_R r = gbt_var_key_readable(key); + + // All cases served by this function are exact, so set *recheck to false + *recheck = false; + + // Check consistency using the gbt_var_consistent function and store the result in retval + retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); + + // Return the result of the consistency check as a boolean value + PG_RETURN_BOOL(retval); } -Datum gbt_numeric_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - int32* size = (int*)PG_GETARG_POINTER(1); - - PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(), &tinfo)); +// Function to perform a union operation on numeric values using GBT +Datum gbt_numeric_union(PG_FUNCTION_ARGS) +{ + // Pointer to the GistEntryVector containing the GIST entries + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + + // Pointer to an integer representing the size of the union + int32* size = (int*)PG_GETARG_POINTER(1); + + // Perform the union operation using gbt_var_union and return the result as a pointer + PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(), &tinfo)); } -Datum gbt_numeric_same(PG_FUNCTION_ARGS) -{ - Datum d1 = PG_GETARG_DATUM(0); - Datum d2 = PG_GETARG_DATUM(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo); - PG_RETURN_POINTER(result); +// Function to check if two numeric values are the same using GBT +Datum gbt_numeric_same(PG_FUNCTION_ARGS) +{ + // The first numeric value + Datum d1 = PG_GETARG_DATUM(0); + + // The second numeric value + Datum d2 = PG_GETARG_DATUM(1); + + // Pointer to a boolean variable that will store the result + bool* result = (bool*)PG_GETARG_POINTER(2); + + // Check if the two numeric values are the same using gbt_var_same and store the result in *result + *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo); + + // Return the result as a pointer + PG_RETURN_POINTER(result); } -Datum gbt_numeric_penalty(PG_FUNCTION_ARGS) -{ - GISTENTRY* o = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* n = (GISTENTRY*)PG_GETARG_POINTER(1); - float* result = (float*)PG_GETARG_POINTER(2); - - Numeric us, os, ds; - - GBT_VARKEY* org = (GBT_VARKEY*)DatumGetPointer(o->key); - GBT_VARKEY* newe = (GBT_VARKEY*)DatumGetPointer(n->key); - Datum uni; - GBT_VARKEY_R rk, ok, uk; - - rk = gbt_var_key_readable(org); - uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE)); - gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo); - ok = gbt_var_key_readable(org); - uk = gbt_var_key_readable((GBT_VARKEY*)DatumGetPointer(uni)); - - us = DatumGetNumeric(DirectFunctionCall2(numeric_sub, PointerGetDatum(uk.upper), PointerGetDatum(uk.lower))); - - os = DatumGetNumeric(DirectFunctionCall2(numeric_sub, PointerGetDatum(ok.upper), PointerGetDatum(ok.lower))); - - ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub, NumericGetDatum(us), NumericGetDatum(os))); - - if (numeric_is_nan(us)) { - if (numeric_is_nan(os)) - *result = 0.0; - else - *result = 1.0; - } else { - Numeric nul = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0))); - - *result = 0.0; - - if (DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))) { - *result += FLT_MIN; - os = DatumGetNumeric(DirectFunctionCall2(numeric_div, NumericGetDatum(ds), NumericGetDatum(us))); - *result += (float4)DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os))); - } - } - - if (*result > 0) - *result *= (FLT_MAX / (((GISTENTRY*)PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - - PG_RETURN_POINTER(result); +// Function to calculate the penalty for a numeric value using GBT +Datum gbt_numeric_penalty(PG_FUNCTION_ARGS) +{ + // Pointer to the original GIST entry + GISTENTRY* o = (GISTENTRY*)PG_GETARG_POINTER(0); + + // Pointer to the new GIST entry + GISTENTRY* n = (GISTENTRY*)PG_GETARG_POINTER(1); + + // Pointer to a float variable that will store the result + float* result = (float*)PG_GETARG_POINTER(2); + + Numeric us, os, ds; + + // Pointers to the keys of the original and new GIST entries + GBT_VARKEY* org = (GBT_VARKEY*)DatumGetPointer(o->key); + GBT_VARKEY* newe = (GBT_VARKEY*)DatumGetPointer(n->key); + + // The union of the original and new keys + Datum uni; + GBT_VARKEY_R rk, ok, uk; + + // Make the original key readable and store it in rk + rk = gbt_var_key_readable(org); + + // Create a copy of the original key and store it in uni + uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE)); + + // Perform a union operation on the original and new keys and update uni + gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo); + + // Make the original key readable and store it in ok + ok = gbt_var_key_readable(org); + + // Make the union key readable and store it in uk + uk = gbt_var_key_readable((GBT_VARKEY*)DatumGetPointer(uni)); + + // Calculate the upper and lower bounds of the union and store them in us + us = DatumGetNumeric(DirectFunctionCall2(numeric_sub, PointerGetDatum(uk.upper), PointerGetDatum(uk.lower))); + + // Calculate the upper and lower bounds of the original key and store them in os + os = DatumGetNumeric(DirectFunctionCall2(numeric_sub, PointerGetDatum(ok.upper), PointerGetDatum(ok.lower))); + + // Calculate the difference between us and os and store it in ds + ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub, NumericGetDatum(us), NumericGetDatum(os))); + + // Check if us is NaN (Not a Number) + if (numeric_is_nan(us)) { + // If os is also NaN, set the result to 0.0; otherwise, set it to 1.0 + if (numeric_is_nan(os)) + *result = 0.0; + else + *result = 1.0; + } else { + // Create a numeric value representing 0 and store it in nul + Numeric nul = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0))); + + // Initialize the result to 0.0 + *result = 0.0; + + // Check if ds is greater than nul and, if so, update the result accordingly + if (DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))) { + *result += FLT_MIN; + os = DatumGetNumeric(DirectFunctionCall2(numeric_div, NumericGetDatum(ds), NumericGetDatum(us))); + *result += (float4)DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os))); + } + } + + // If the result is greater than 0, scale it by a certain factor and return it as a pointer; otherwise, return it as-is + if (*result > 0) + *result *= (FLT_MAX / (((GISTENTRY*)PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); + + PG_RETURN_POINTER(result); } -Datum gbt_numeric_picksplit(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - GIST_SPLITVEC* v = (GIST_SPLITVEC*)PG_GETARG_POINTER(1); - - gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(), &tinfo); - PG_RETURN_POINTER(v); +// Function to perform a picksplit operation on numeric values using GBT +Datum gbt_numeric_picksplit(PG_FUNCTION_ARGS) +{ + // Pointer to the GistEntryVector containing the GIST entries + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + + // Pointer to the GIST_SPLITVEC that will store the result of the picksplit operation + GIST_SPLITVEC* v = (GIST_SPLITVEC*)PG_GETARG_POINTER(1); + + // Perform the picksplit operation using gbt_var_picksplit and store the result in v + gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(), &tinfo); + + // Return the result as a pointer + PG_RETURN_POINTER(v); } -- 2.34.1 From 9c287ac5ada797c1cb7f9fbf15646efd78381e3d Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Fri, 22 Sep 2023 09:08:10 +0800 Subject: [PATCH 6/7] =?UTF-8?q?contrib=E6=96=87=E4=BB=B6=E5=A4=B9=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/btree_gist/btree_int8.cpp | 234 ++++++------ contrib/btree_gist/btree_macaddr.cpp | 287 ++++++++------- contrib/btree_gist/btree_oid.cpp | 337 ++++++++++-------- contrib/btree_gist/btree_text.cpp | 264 ++++++++------ contrib/btree_gist/btree_time.cpp | 510 ++++++++++++++++----------- 5 files changed, 922 insertions(+), 710 deletions(-) diff --git a/contrib/btree_gist/btree_int8.cpp b/contrib/btree_gist/btree_int8.cpp index 6749efea7..46138b485 100644 --- a/contrib/btree_gist/btree_int8.cpp +++ b/contrib/btree_gist/btree_int8.cpp @@ -1,110 +1,130 @@ /* * contrib/btree_gist/btree_int8.c */ -#include "postgres.h" -#include "knl/knl_variable.h" - -#include "btree_gist.h" -#include "btree_utils_num.h" - -typedef struct int64key { - int64 lower; - int64 upper; -} int64KEY; - -/* -** int64 ops -*/ -PG_FUNCTION_INFO_V1(gbt_int8_compress); -PG_FUNCTION_INFO_V1(gbt_int8_union); -PG_FUNCTION_INFO_V1(gbt_int8_picksplit); -PG_FUNCTION_INFO_V1(gbt_int8_consistent); -PG_FUNCTION_INFO_V1(gbt_int8_distance); -PG_FUNCTION_INFO_V1(gbt_int8_penalty); -PG_FUNCTION_INFO_V1(gbt_int8_same); - -extern "C" Datum gbt_int8_compress(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_union(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_picksplit(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_consistent(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_distance(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_penalty(PG_FUNCTION_ARGS); -extern "C" Datum gbt_int8_same(PG_FUNCTION_ARGS); - -static bool gbt_int8gt(const void* a, const void* b) -{ - return (*((const int64*)a) > *((const int64*)b)); -} -static bool gbt_int8ge(const void* a, const void* b) -{ - return (*((const int64*)a) >= *((const int64*)b)); -} -static bool gbt_int8eq(const void* a, const void* b) -{ - return (*((const int64*)a) == *((const int64*)b)); -} -static bool gbt_int8le(const void* a, const void* b) -{ - return (*((const int64*)a) <= *((const int64*)b)); -} -static bool gbt_int8lt(const void* a, const void* b) -{ - return (*((const int64*)a) < *((const int64*)b)); +// Include the PostgreSQL header file, which contains all the basic PostgreSQL data types and function definitions. +#include "postgres.h" +// Include the knl/knl_variable.h header file, which is part of the PostgreSQL kernel and contains the definitions of some internal variables and functions. +#include "knl/knl_variable.h" + +// Include the btree_gist.h header file, which defines the B-tree structure used to implement the GiST index. +#include "btree_gist.h" +// Include the btree_utils_num.h header file, which contains some utility functions for operating on B-trees. +#include "btree_utils_num.h" + +// Define a structure int64key for storing the lower and upper bounds of a 64-bit integer. +typedef struct int64key { + // The lower bound of the 64-bit integer. + int64 lower; + // The upper bound of the 64-bit integer. + int64 upper; +} int64KEY; + +/* +** int64 ops +*/ +// Define a series of function info macros, which are used to register functions in PostgreSQL. +PG_FUNCTION_INFO_V1(gbt_int8_compress); // Compression function. +PG_FUNCTION_INFO_V1(gbt_int8_union); // Merging function. +PG_FUNCTION_INFO_V1(gbt_int8_picksplit); // Splitting function. +PG_FUNCTION_INFO_V1(gbt_int8_consistent);// Consistency check function. +PG_FUNCTION_INFO_V1(gbt_int8_distance); // Distance function. +PG_FUNCTION_INFO_V1(gbt_int8_penalty); // Penalty function. +PG_FUNCTION_INFO_V1(gbt_int8_same); // Sameness check function. + +// Define a series of function prototypes, which are used to implement different operations on the GiST index. +extern "C" Datum gbt_int8_compress(PG_FUNCTION_ARGS); // Compression function. +extern "C" Datum gbt_int8_union(PG_FUNCTION_ARGS); // Merging function. +extern "C" Datum gbt_int8_picksplit(PG_FUNCTION_ARGS); // Splitting function. +extern "C" Datum gbt_int8_consistent(PG_FUNCTION_ARGS);// Consistency check function. +extern "C" Datum gbt_int8_distance(PG_FUNCTION_ARGS); // Distance function. +extern "C" Datum gbt_int8_penalty(PG_FUNCTION_ARGS); // Penalty function. +extern "C" Datum gbt_int8_same(PG_FUNCTION_ARGS); // Sameness check function. + +// Define a series of comparison functions, which are used to compare the sizes of two 64-bit integers. +static bool gbt_int8gt(const void* a, const void* b) // Greater than comparison. +{ + return (*((const int64*)a) > *((const int64*)b)); +} +static bool gbt_int8ge(const void* a, const void* b) // Greater than or equal to comparison. +{ + return (*((const int64*)a) >= *((const int64*)b)); +} +static bool gbt_int8eq(const void* a, const void* b) // Equal to comparison. +{ + return (*((const int64*)a) == *((const int64*)b)); +} +static bool gbt_int8le(const void* a, const void* b) // Less than or equal to comparison. +{ + return (*((const int64*)a) <= *((const int64*)b)); +} +static bool gbt_int8lt(const void* a, const void* b) // Less than comparison. +{ + return (*((const int64*)a) < *((const int64*)b)); } -static int gbt_int8key_cmp(const void* a, const void* b) -{ - int64KEY* ia = (int64KEY*)(((const Nsrt*)a)->t); - int64KEY* ib = (int64KEY*)(((const Nsrt*)b)->t); - - if (ia->lower == ib->lower) { - if (ia->upper == ib->upper) - return 0; - - return (ia->upper > ib->upper) ? 1 : -1; - } - - return (ia->lower > ib->lower) ? 1 : -1; +// Define a function to compare two 64-bit integers. +static int gbt_int8key_cmp(const void* a, const void* b) +{ + // Cast the input pointers to their original types. + int64KEY* ia = (int64KEY*)(((const Nsrt*)a)->t); + int64KEY* ib = (int64KEY*)(((const Nsrt*)b)->t); + + // Compare the lower bounds first. If they are equal, compare the upper bounds. + if (ia->lower == ib->lower) { + if (ia->upper == ib->upper) + return 0; // Return 0 if both are equal. + + return (ia->upper > ib->upper) ? 1 : -1; // Return 1 if ia->upper is greater than ib->upper, else return -1. + } + + return (ia->lower > ib->lower) ? 1 : -1; // Return 1 if ia->lower is greater than ib->lower, else return -1. +} + +// Define a function to calculate the distance between two 64-bit integers. +static float8 gbt_int8_dist(const void* a, const void* b) +{ + // Use the macro GET_FLOAT_DISTANCE to calculate the distance. + return GET_FLOAT_DISTANCE(int64, a, b); +} + +// Define a structure to store the information about the GiST index. +static const gbtree_ninfo tinfo = {gbt_t_int8, + sizeof(int64), + gbt_int8gt, + gbt_int8ge, + gbt_int8eq, + gbt_int8le, + gbt_int8lt, + gbt_int8key_cmp, + gbt_int8_dist}; + +// Register the int8_dist function in PostgreSQL. +PG_FUNCTION_INFO_V1(int8_dist); +extern "C" Datum int8_dist(PG_FUNCTION_ARGS); +Datum int8_dist(PG_FUNCTION_ARGS) +{ + // Get the input arguments. + int64 a = PG_GETARG_INT64(0); + int64 b = PG_GETARG_INT64(1); + int64 r; + int64 ra; + + // Calculate the difference between a and b. + r = a - b; + ra = Abs(r); // Calculate the absolute value of r. + + /* Check for overflow. */ + if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a))) + ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); // Report an error if there is an overflow. + + // Return the absolute value of the difference. + PG_RETURN_INT64(ra); } - -static float8 gbt_int8_dist(const void* a, const void* b) -{ - return GET_FLOAT_DISTANCE(int64, a, b); -} - -static const gbtree_ninfo tinfo = {gbt_t_int8, - sizeof(int64), - gbt_int8gt, - gbt_int8ge, - gbt_int8eq, - gbt_int8le, - gbt_int8lt, - gbt_int8key_cmp, - gbt_int8_dist}; - -PG_FUNCTION_INFO_V1(int8_dist); -extern "C" Datum int8_dist(PG_FUNCTION_ARGS); -Datum int8_dist(PG_FUNCTION_ARGS) -{ - int64 a = PG_GETARG_INT64(0); - int64 b = PG_GETARG_INT64(1); - int64 r; - int64 ra; - - r = a - b; - ra = Abs(r); - - /* Overflow check. */ - if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a))) - ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); - - PG_RETURN_INT64(ra); -} - /************************************************** * int64 ops **************************************************/ +/* gbt_int8_compress - compresses a GIST entry containing an int8 key */ Datum gbt_int8_compress(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -113,6 +133,7 @@ Datum gbt_int8_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); } +/* gbt_int8_consistent - checks if a query is consistent with an int8 key */ Datum gbt_int8_consistent(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -132,6 +153,7 @@ Datum gbt_int8_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); } +/* gbt_int8_distance - calculates the distance between an int8 key and a query */ Datum gbt_int8_distance(PG_FUNCTION_ARGS) { GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); @@ -146,6 +168,7 @@ Datum gbt_int8_distance(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); } +/* gbt_int8_union - performs a union on a vector of int8 keys */ Datum gbt_int8_union(PG_FUNCTION_ARGS) { GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); @@ -155,6 +178,7 @@ Datum gbt_int8_union(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); } +/* gbt_int8_penalty - calculates the penalty for splitting an int8 key */ Datum gbt_int8_penalty(PG_FUNCTION_ARGS) { int64KEY* origentry = (int64KEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); @@ -166,24 +190,14 @@ Datum gbt_int8_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +/* gbt_int8_picksplit - performs a picksplit on a GIST entry vector */ Datum gbt_int8_picksplit(PG_FUNCTION_ARGS) { PG_RETURN_POINTER( gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); } -/* -function name: gbt_int8_same -description: - This function checks whether two int8 keys are the same. - The input is two pointers to int64KEY structs representing the keys, - and a pointer to a boolean variable to store the result. - The output is a pointer to the boolean variable. - - The function calls gbt_num_same with the two keys, and a pointer to the tinfo - struct. The result of the comparison is stored in the boolean variable - pointed to by the result argument, and a pointer to this variable is returned. -*/ +/* gbt_int8_same - checks if two int8 keys are the same */ Datum gbt_int8_same(PG_FUNCTION_ARGS) { int64KEY* b1 = (int64KEY*)PG_GETARG_POINTER(0); @@ -192,4 +206,4 @@ Datum gbt_int8_same(PG_FUNCTION_ARGS) *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); PG_RETURN_POINTER(result); -} +} \ No newline at end of file diff --git a/contrib/btree_gist/btree_macaddr.cpp b/contrib/btree_gist/btree_macaddr.cpp index c11d98500..c3f1c31a4 100644 --- a/contrib/btree_gist/btree_macaddr.cpp +++ b/contrib/btree_gist/btree_macaddr.cpp @@ -31,134 +31,169 @@ extern "C" Datum gbt_macad_consistent(PG_FUNCTION_ARGS); extern "C" Datum gbt_macad_penalty(PG_FUNCTION_ARGS); extern "C" Datum gbt_macad_same(PG_FUNCTION_ARGS); -static bool gbt_macadgt(const void* a, const void* b) -{ - return DatumGetBool(DirectFunctionCall2(macaddr_gt, PointerGetDatum(a), PointerGetDatum(b))); -} -static bool gbt_macadge(const void* a, const void* b) -{ - return DatumGetBool(DirectFunctionCall2(macaddr_ge, PointerGetDatum(a), PointerGetDatum(b))); +// Define a function to compare two macaddr values. +static bool gbt_macadgt(const void* a, const void* b) +{ + // Use the macaddr_gt function to compare the input pointers and return the result as a boolean value. + return DatumGetBool(DirectFunctionCall2(macaddr_gt, PointerGetDatum(a), PointerGetDatum(b))); +} + +// Define a function to compare two macaddr values. +static bool gbt_macadge(const void* a, const void* b) +{ + // Use the macaddr_ge function to compare the input pointers and return the result as a boolean value. + return DatumGetBool(DirectFunctionCall2(macaddr_ge, PointerGetDatum(a), PointerGetDatum(b))); +} + +// Define a function to compare two macaddr values. +static bool gbt_macadeq(const void* a, const void* b) +{ + // Use the macaddr_eq function to compare the input pointers and return the result as a boolean value. + return DatumGetBool(DirectFunctionCall2(macaddr_eq, PointerGetDatum(a), PointerGetDatum(b))); +} + +// Define a function to compare two macaddr values. +static bool gbt_macadle(const void* a, const void* b) +{ + // Use the macaddr_le function to compare the input pointers and return the result as a boolean value. + return DatumGetBool(DirectFunctionCall2(macaddr_le, PointerGetDatum(a), PointerGetDatum(b))); +} + +// Define a function to compare two macaddr values. +static bool gbt_macadlt(const void* a, const void* b) +{ + // Use the macaddr_lt function to compare the input pointers and return the result as a boolean value. + return DatumGetBool(DirectFunctionCall2(macaddr_lt, PointerGetDatum(a), PointerGetDatum(b))); +} + +// Define a function to compare two macaddr keys. +static int gbt_macadkey_cmp(const void* a, const void* b) +{ + // Cast the input pointers to their original types. + macKEY* ia = (macKEY*)(((const Nsrt*)a)->t); + macKEY* ib = (macKEY*)(((const Nsrt*)b)->t); + int res; + + // Compare the lower bounds first. If they are equal, compare the upper bounds. + res = DatumGetInt32(DirectFunctionCall2(macaddr_cmp, MacaddrPGetDatum(&ia->lower), MacaddrPGetDatum(&ib->lower))); + if (res == 0) + return DatumGetInt32(DirectFunctionCall2(macaddr_cmp, MacaddrPGetDatum(&ia->upper), MacaddrPGetDatum(&ib->upper))); + + return res; // Return the result of the comparison. } -static bool gbt_macadeq(const void* a, const void* b) -{ - return DatumGetBool(DirectFunctionCall2(macaddr_eq, PointerGetDatum(a), PointerGetDatum(b))); +// Define a structure to store the information about the GiST index. +static const gbtree_ninfo tinfo = {gbt_t_macad, + sizeof(macaddr), + gbt_macadgt, + gbt_macadge, + gbt_macadeq, + gbt_macadle, + gbt_macadlt, + gbt_macadkey_cmp, + NULL}; + +/************************************************** + * macaddr ops + **************************************************/ + +// Define a function to convert a macaddr to a uint64. +static uint64 mac_2_uint64(macaddr* m) +{ + unsigned char* mi = (unsigned char*)m; + uint64 res = 0; + int i; + + // Loop through each byte of the macaddr and shift it to the correct position. + for (i = 0; i < 6; i++) + res += (((uint64)mi[i]) << ((uint64)((5 - i) * 8))); + return res; +} + +// Define a function to compress a GiST entry. +Datum gbt_macad_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + GISTENTRY* retval = NULL; + + // Use the gbt_num_compress function to compress the entry and return it. + PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +} + +// Define a function to check the consistency of a GiST entry. +Datum gbt_macad_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + macaddr* query = (macaddr*)PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + bool* recheck = (bool*)PG_GETARG_POINTER(4); + macKEY* kkk = (macKEY*)DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + // All cases served by this function are exact, so set *recheck to false. + *recheck = false; + + // Set the lower and upper bounds of the key. + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + // Use the gbt_num_consistent function to check the consistency of the entry and return the result. + PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)query, &strategy, GIST_LEAF(entry), &tinfo)); } -static bool gbt_macadle(const void* a, const void* b) -{ - return DatumGetBool(DirectFunctionCall2(macaddr_le, PointerGetDatum(a), PointerGetDatum(b))); -} - -static bool gbt_macadlt(const void* a, const void* b) -{ - return DatumGetBool(DirectFunctionCall2(macaddr_lt, PointerGetDatum(a), PointerGetDatum(b))); -} - -static int gbt_macadkey_cmp(const void* a, const void* b) -{ - macKEY* ia = (macKEY*)(((const Nsrt*)a)->t); - macKEY* ib = (macKEY*)(((const Nsrt*)b)->t); - int res; - - res = DatumGetInt32(DirectFunctionCall2(macaddr_cmp, MacaddrPGetDatum(&ia->lower), MacaddrPGetDatum(&ib->lower))); - if (res == 0) - return DatumGetInt32( - DirectFunctionCall2(macaddr_cmp, MacaddrPGetDatum(&ia->upper), MacaddrPGetDatum(&ib->upper))); - - return res; -} - -static const gbtree_ninfo tinfo = {gbt_t_macad, - sizeof(macaddr), - gbt_macadgt, - gbt_macadge, - gbt_macadeq, - gbt_macadle, - gbt_macadlt, - gbt_macadkey_cmp, - NULL}; - -/************************************************** - * macaddr ops - **************************************************/ - -static uint64 mac_2_uint64(macaddr* m) -{ - unsigned char* mi = (unsigned char*)m; - uint64 res = 0; - int i; - - for (i = 0; i < 6; i++) - res += (((uint64)mi[i]) << ((uint64)((5 - i) * 8))); - return res; -} - -Datum gbt_macad_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); -} - -Datum gbt_macad_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - macaddr* query = (macaddr*)PG_GETARG_POINTER(1); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - macKEY* kkk = (macKEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - /* All cases served by this function are exact */ - *recheck = false; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)query, &strategy, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_macad_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - void* out = palloc(sizeof(macKEY)); - - *(int*)PG_GETARG_POINTER(1) = sizeof(macKEY); - PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); -} - -Datum gbt_macad_penalty(PG_FUNCTION_ARGS) -{ - macKEY* origentry = (macKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); - macKEY* newentry = (macKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); - float* result = (float*)PG_GETARG_POINTER(2); - uint64 iorg[2], inew[2]; - - iorg[0] = mac_2_uint64(&origentry->lower); - iorg[1] = mac_2_uint64(&origentry->upper); - inew[0] = mac_2_uint64(&newentry->lower); - inew[1] = mac_2_uint64(&newentry->upper); - - penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]); - - PG_RETURN_POINTER(result); -} - -Datum gbt_macad_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER( - gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); -} - -Datum gbt_macad_same(PG_FUNCTION_ARGS) -{ - macKEY* b1 = (macKEY*)PG_GETARG_POINTER(0); - macKEY* b2 = (macKEY*)PG_GETARG_POINTER(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); - PG_RETURN_POINTER(result); +// Define a function to union GiST entries. +Datum gbt_macad_union(PG_FUNCTION_ARGS) +{ + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + void* out = palloc(sizeof(macKEY)); + + // Set the size of the output to the size of a macKEY. + *(int*)PG_GETARG_POINTER(1) = sizeof(macKEY); + + // Use the gbt_num_union function to union the entries and return the result. + PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); +} + +// Define a function to calculate the penalty of GiST entries. +Datum gbt_macad_penalty(PG_FUNCTION_ARGS) +{ + macKEY* origentry = (macKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); + macKEY* newentry = (macKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); + float* result = (float*)PG_GETARG_POINTER(2); + uint64 iorg[2], inew[2]; + + // Convert the original and new entries to uint64. + iorg[0] = mac_2_uint64(&origentry->lower); + iorg[1] = mac_2_uint64(&origentry->upper); + inew[0] = mac_2_uint64(&newentry->lower); + inew[1] = mac_2_uint64(&newentry->upper); + + // Calculate the penalty and store it in the result. + penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]); + + // Return the result. + PG_RETURN_POINTER(result); +} + +// Define a function to pick a split point for GiST entries. +Datum gbt_macad_picksplit(PG_FUNCTION_ARGS) +{ + // Use the gbt_num_picksplit function to pick a split point and return the result. + PG_RETURN_POINTER( + gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); +} + +// Define a function to check if two GiST entries are the same. +Datum gbt_macad_same(PG_FUNCTION_ARGS) +{ + macKEY* b1 = (macKEY*)PG_GETARG_POINTER(0); + macKEY* b2 = (macKEY*)PG_GETARG_POINTER(1); + bool* result = (bool*)PG_GETARG_POINTER(2); + + // Use the gbt_num_same function to check if the two entries are the same and store the result. + *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); + + // Return the result. + PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_oid.cpp b/contrib/btree_gist/btree_oid.cpp index 6a40a8791..aa658d35c 100644 --- a/contrib/btree_gist/btree_oid.cpp +++ b/contrib/btree_gist/btree_oid.cpp @@ -15,164 +15,199 @@ typedef struct { /* ** OID ops */ -PG_FUNCTION_INFO_V1(gbt_oid_compress); -PG_FUNCTION_INFO_V1(gbt_oid_union); -PG_FUNCTION_INFO_V1(gbt_oid_picksplit); -PG_FUNCTION_INFO_V1(gbt_oid_consistent); -PG_FUNCTION_INFO_V1(gbt_oid_distance); -PG_FUNCTION_INFO_V1(gbt_oid_penalty); -PG_FUNCTION_INFO_V1(gbt_oid_same); - -extern "C" Datum gbt_oid_compress(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_union(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_picksplit(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_consistent(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_distance(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_penalty(PG_FUNCTION_ARGS); -extern "C" Datum gbt_oid_same(PG_FUNCTION_ARGS); - -static bool gbt_oidgt(const void* a, const void* b) -{ - return (*((const Oid*)a) > *((const Oid*)b)); -} -static bool gbt_oidge(const void* a, const void* b) -{ - return (*((const Oid*)a) >= *((const Oid*)b)); -} -static bool gbt_oideq(const void* a, const void* b) -{ - return (*((const Oid*)a) == *((const Oid*)b)); -} -static bool gbt_oidle(const void* a, const void* b) -{ - return (*((const Oid*)a) <= *((const Oid*)b)); -} -static bool gbt_oidlt(const void* a, const void* b) -{ - return (*((const Oid*)a) < *((const Oid*)b)); +// These macros define the function information for each of the GiST functions. +PG_FUNCTION_INFO_V1(gbt_oid_compress); +PG_FUNCTION_INFO_V1(gbt_oid_union); +PG_FUNCTION_INFO_V1(gbt_oid_picksplit); +PG_FUNCTION_INFO_V1(gbt_oid_consistent); +PG_FUNCTION_INFO_V1(gbt_oid_distance); +PG_FUNCTION_INFO_V1(gbt_oid_penalty); +PG_FUNCTION_INFO_V1(gbt_oid_same); + +// These functions are defined as extern "C" because they are called from C code. +// Each function takes PG_FUNCTION_ARGS as parameters and returns a Datum. +extern "C" Datum gbt_oid_compress(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_union(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_picksplit(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_consistent(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_distance(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_penalty(PG_FUNCTION_ARGS); +extern "C" Datum gbt_oid_same(PG_FUNCTION_ARGS); + +// These functions are used to compare Oids. They take two void pointers and return a bool. +static bool gbt_oidgt(const void* a, const void* b) +{ + // Compare the Oids and return true if the first is greater than the second. + return (*((const Oid*)a) > *((const Oid*)b)); +} +static bool gbt_oidge(const void* a, const void* b) +{ + // Compare the Oids and return true if the first is greater than or equal to the second. + return (*((const Oid*)a) >= *((const Oid*)b)); +} +static bool gbt_oideq(const void* a, const void* b) +{ + // Compare the Oids and return true if they are equal. + return (*((const Oid*)a) == *((const Oid*)b)); +} +static bool gbt_oidle(const void* a, const void* b) +{ + // Compare the Oids and return true if the first is less than or equal to the second. + return (*((const Oid*)a) <= *((const Oid*)b)); +} +static bool gbt_oidlt(const void* a, const void* b) +{ + // Compare the Oids and return true if the first is less than the second. + return (*((const Oid*)a) < *((const Oid*)b)); } -static int gbt_oidkey_cmp(const void* a, const void* b) -{ - oidKEY* ia = (oidKEY*)(((const Nsrt*)a)->t); - oidKEY* ib = (oidKEY*)(((const Nsrt*)b)->t); - - if (ia->lower == ib->lower) { - if (ia->upper == ib->upper) - return 0; - - return (ia->upper > ib->upper) ? 1 : -1; - } - - return (ia->lower > ib->lower) ? 1 : -1; +// Define a function to compare two oidKEYs. +static int gbt_oidkey_cmp(const void* a, const void* b) +{ + oidKEY* ia = (oidKEY*)(((const Nsrt*)a)->t); + oidKEY* ib = (oidKEY*)(((const Nsrt*)b)->t); + + // Compare the lower and upper bounds of the oidKEYs. + if (ia->lower == ib->lower) { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +// Define a function to calculate the distance between two Oids. +static float8 gbt_oid_dist(const void* a, const void* b) +{ + Oid aa = *(const Oid*)a; + Oid bb = *(const Oid*)b; + + // Calculate the distance between the two Oids. + if (aa < bb) + return (float8)(bb - aa); + else + return (float8)(aa - bb); +} + +// Define the tree information for the GiST index. +static const gbtree_ninfo tinfo = { + gbt_t_oid, sizeof(Oid), gbt_oidgt, gbt_oidge, gbt_oideq, gbt_oidle, gbt_oidlt, gbt_oidkey_cmp, gbt_oid_dist}; + +// Define the function information for the oid_dist function. +PG_FUNCTION_INFO_V1(oid_dist); +extern "C" Datum oid_dist(PG_FUNCTION_ARGS); +Datum oid_dist(PG_FUNCTION_ARGS) +{ + Oid a = PG_GETARG_OID(0); + Oid b = PG_GETARG_OID(1); + Oid res; + + // Calculate the distance between the two Oids. + if (a < b) + res = b - a; + else + res = a - b; + PG_RETURN_OID(res); } - -static float8 gbt_oid_dist(const void* a, const void* b) -{ - Oid aa = *(const Oid*)a; - Oid bb = *(const Oid*)b; - - if (aa < bb) - return (float8)(bb - aa); - else - return (float8)(aa - bb); -} - -static const gbtree_ninfo tinfo = { - gbt_t_oid, sizeof(Oid), gbt_oidgt, gbt_oidge, gbt_oideq, gbt_oidle, gbt_oidlt, gbt_oidkey_cmp, gbt_oid_dist}; - -PG_FUNCTION_INFO_V1(oid_dist); -extern "C" Datum oid_dist(PG_FUNCTION_ARGS); -Datum oid_dist(PG_FUNCTION_ARGS) -{ - Oid a = PG_GETARG_OID(0); - Oid b = PG_GETARG_OID(1); - Oid res; - - if (a < b) - res = b - a; - else - res = a - b; - PG_RETURN_OID(res); -} - /************************************************** * Oid ops **************************************************/ -Datum gbt_oid_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +// Function to compress a GiST entry. +// It takes a single argument of type GISTENTRY* and returns a pointer to the compressed entry. +Datum gbt_oid_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + GISTENTRY* retval = NULL; + + PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +} + +// Function to check if an Oid is consistent with a GiST entry. +// It takes four arguments: a GISTENTRY*, an Oid, a StrategyNumber, and a bool*. +// The function sets the bool* to false, indicating that all cases served by this function are exact. +// It returns a bool indicating if the Oid is consistent with the GiST entry. +Datum gbt_oid_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + Oid query = PG_GETARG_OID(1); + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + bool* recheck = (bool*)PG_GETARG_POINTER(4); + oidKEY* kkk = (oidKEY*)DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + /* All cases served by this function are exact */ + *recheck = false; + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); +} + +// Function to calculate the distance between an Oid and a GiST entry. +// It takes two arguments: a GISTENTRY* and an Oid. +// The function returns a float8 representing the distance between the Oid and the GiST entry. +Datum gbt_oid_distance(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + Oid query = PG_GETARG_OID(1); + + oidKEY* kkk = (oidKEY*)DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); } -Datum gbt_oid_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - Oid query = PG_GETARG_OID(1); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - oidKEY* kkk = (oidKEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - /* All cases served by this function are exact */ - *recheck = false; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_oid_distance(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - Oid query = PG_GETARG_OID(1); - - oidKEY* kkk = (oidKEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_oid_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - void* out = palloc(sizeof(oidKEY)); - - *(int*)PG_GETARG_POINTER(1) = sizeof(oidKEY); - PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); -} - -Datum gbt_oid_penalty(PG_FUNCTION_ARGS) -{ - oidKEY* origentry = (oidKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); - oidKEY* newentry = (oidKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); - float* result = (float*)PG_GETARG_POINTER(2); - - penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - PG_RETURN_POINTER(result); -} - -Datum gbt_oid_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER( - gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); -} - -Datum gbt_oid_same(PG_FUNCTION_ARGS) -{ - oidKEY* b1 = (oidKEY*)PG_GETARG_POINTER(0); - oidKEY* b2 = (oidKEY*)PG_GETARG_POINTER(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); - PG_RETURN_POINTER(result); +// Function to union a GiST entry vector. +// It takes a single argument of type GistEntryVector* and returns a pointer to the unioned entry. +Datum gbt_oid_union(PG_FUNCTION_ARGS) +{ + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + void* out = palloc(sizeof(oidKEY)); + + *(int*)PG_GETARG_POINTER(1) = sizeof(oidKEY); + PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); +} + +// Function to calculate the penalty of merging two GiST entries. +// It takes two arguments of type oidKEY* and a float*. +// The function calls penalty_num to calculate the penalty and returns a pointer to the result. +Datum gbt_oid_penalty(PG_FUNCTION_ARGS) +{ + oidKEY* origentry = (oidKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); + oidKEY* newentry = (oidKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); + float* result = (float*)PG_GETARG_POINTER(2); + + penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper); + + PG_RETURN_POINTER(result); +} + +// Function to pick a split point for a GiST entry vector. +// It takes two arguments of type GistEntryVector* and GIST_SPLITVEC*. +// The function returns a pointer to the split point. +Datum gbt_oid_picksplit(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER( + gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); +} + +// Function to check if two GiST entries are the same. +// It takes two arguments of type oidKEY* and a bool*. +// The function calls gbt_num_same to check if the entries are the same and returns a pointer to the result. +Datum gbt_oid_same(PG_FUNCTION_ARGS) +{ + oidKEY* b1 = (oidKEY*)PG_GETARG_POINTER(0); + oidKEY* b2 = (oidKEY*)PG_GETARG_POINTER(1); + bool* result = (bool*)PG_GETARG_POINTER(2); + + *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); + PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_text.cpp b/contrib/btree_gist/btree_text.cpp index 9e047c93a..31cd385df 100644 --- a/contrib/btree_gist/btree_text.cpp +++ b/contrib/btree_gist/btree_text.cpp @@ -68,118 +68,158 @@ static gbtree_vinfo tinfo = { * Text ops **************************************************/ -Datum gbt_text_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - - if (tinfo.eml == 0) { - tinfo.eml = pg_database_encoding_max_length(); - } - - PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); +// Function to compress a GiST entry for text type. +// It takes a single argument of type GISTENTRY* and returns a pointer to the compressed entry. +// If the tinfo.eml is 0, it sets it to the maximum length of the database encoding. +Datum gbt_text_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + + if (tinfo.eml == 0) { + tinfo.eml = pg_database_encoding_max_length(); + } + + PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); +} + +// Function to compress a GiST entry for bpchar type. +// It takes a single argument of type GISTENTRY* and returns a pointer to the compressed entry. +// If the tinfo.eml is 0, it sets it to the maximum length of the database encoding. +// If the entry is a leafkey, it trims the key and compresses the trimmed entry. Otherwise, it returns the entry as it is. +Datum gbt_bpchar_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + GISTENTRY* retval = NULL; + + if (tinfo.eml == 0) { + tinfo.eml = pg_database_encoding_max_length(); + } + + if (entry->leafkey) { + Datum d = DirectFunctionCall1(rtrim1, entry->key); + GISTENTRY trim; + + gistentryinit(trim, d, entry->rel, entry->page, entry->offset, TRUE); + retval = gbt_var_compress(&trim, &tinfo); + } else + retval = entry; + + PG_RETURN_POINTER(retval); +} + +// Function to check if a text is consistent with a GiST entry for text type. +// It takes four arguments: a GISTENTRY*, a void* representing the text, a StrategyNumber, and a bool*. +// The function sets the bool* to false, indicating that all cases served by this function are exact. +// It returns a bool indicating if the text is consistent with the GiST entry. +// If the tinfo.eml is 0, it sets it to the maximum length of the database encoding. +Datum gbt_text_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + void* query = (void*)DatumGetTextP(PG_GETARG_DATUM(1)); + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + bool* recheck = (bool*)PG_GETARG_POINTER(4); + bool retval = false; + GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); + GBT_VARKEY_R r = gbt_var_key_readable(key); + + /* All cases served by this function are exact */ + *recheck = false; + + if (tinfo.eml == 0) { + tinfo.eml = pg_database_encoding_max_length(); + } + + retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); + + PG_RETURN_BOOL(retval); } -Datum gbt_bpchar_compress(PG_FUNCTION_ARGS) -{ - - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - if (tinfo.eml == 0) { - tinfo.eml = pg_database_encoding_max_length(); - } - - if (entry->leafkey) { - - Datum d = DirectFunctionCall1(rtrim1, entry->key); - GISTENTRY trim; - - gistentryinit(trim, d, entry->rel, entry->page, entry->offset, TRUE); - retval = gbt_var_compress(&trim, &tinfo); - } else - retval = entry; - - PG_RETURN_POINTER(retval); -} - -Datum gbt_text_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - void* query = (void*)DatumGetTextP(PG_GETARG_DATUM(1)); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - bool retval = false; - GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); - GBT_VARKEY_R r = gbt_var_key_readable(key); - - /* All cases served by this function are exact */ - *recheck = false; - - if (tinfo.eml == 0) { - tinfo.eml = pg_database_encoding_max_length(); - } - - retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); - - PG_RETURN_BOOL(retval); -} - -Datum gbt_bpchar_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - void* query = (void*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1))); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - bool retval = false; - GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); - GBT_VARKEY_R r = gbt_var_key_readable(key); - void* trim = (void*)DatumGetPointer(DirectFunctionCall1(rtrim1, PointerGetDatum(query))); - - /* All cases served by this function are exact */ - *recheck = false; - - if (tinfo.eml == 0) { - tinfo.eml = pg_database_encoding_max_length(); - } - - retval = gbt_var_consistent(&r, trim, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); - PG_RETURN_BOOL(retval); -} - -Datum gbt_text_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - int32* size = (int*)PG_GETARG_POINTER(1); - - PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(), &tinfo)); -} - -Datum gbt_text_picksplit(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); - GIST_SPLITVEC* v = (GIST_SPLITVEC*)PG_GETARG_POINTER(1); - - gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(), &tinfo); - PG_RETURN_POINTER(v); -} - -Datum gbt_text_same(PG_FUNCTION_ARGS) -{ - Datum d1 = PG_GETARG_DATUM(0); - Datum d2 = PG_GETARG_DATUM(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo); - PG_RETURN_POINTER(result); -} - -Datum gbt_text_penalty(PG_FUNCTION_ARGS) -{ - GISTENTRY* o = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* n = (GISTENTRY*)PG_GETARG_POINTER(1); - float* result = (float*)PG_GETARG_POINTER(2); - - PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(), &tinfo)); +// Check if a bpchar is consistent with a GiST entry for bpchar type. +Datum gbt_bpchar_consistent(PG_FUNCTION_ARGS) +{ + // Get the GiST entry. + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Get the query. + void* query = (void*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1))); + // Get the strategy. + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + // Get the recheck boolean. + bool* recheck = (bool*)PG_GETARG_POINTER(4); + // Initialize the return value. + bool retval = false; + // Get the key. + GBT_VARKEY* key = (GBT_VARKEY*)DatumGetPointer(entry->key); + // Make the key readable. + GBT_VARKEY_R r = gbt_var_key_readable(key); + // Trim the query. + void* trim = (void*)DatumGetPointer(DirectFunctionCall1(rtrim1, PointerGetDatum(query))); + + // All cases served by this function are exact. + *recheck = false; + + // If the tinfo.eml is 0, set it to the maximum length of the database encoding. + if (tinfo.eml == 0) { + tinfo.eml = pg_database_encoding_max_length(); + } + + // Check if the query is consistent with the GiST entry. + retval = gbt_var_consistent(&r, trim, strategy, PG_GET_COLLATION(), GIST_LEAF(entry), &tinfo); + // Return the result. + PG_RETURN_BOOL(retval); +} + +// Union GiST entries for text type. +Datum gbt_text_union(PG_FUNCTION_ARGS) +{ + // Get the GiST entry vector. + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + // Get the size. + int32* size = (int*)PG_GETARG_POINTER(1); + + // Union the entries and return the result. + PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(), &tinfo)); +} + +// Split GiST entries for text type. +Datum gbt_text_picksplit(PG_FUNCTION_ARGS) +{ + // Get the GiST entry vector. + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); + // Get the split vector. + GIST_SPLITVEC* v = (GIST_SPLITVEC*)PG_GETARG_POINTER(1); + + // Split the entries. + gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(), &tinfo); + // Return the split vector. + PG_RETURN_POINTER(v); +} + +// Check if two text values are the same. +Datum gbt_text_same(PG_FUNCTION_ARGS) +{ + // Get the two text values. + Datum d1 = PG_GETARG_DATUM(0); + Datum d2 = PG_GETARG_DATUM(1); + // Get the result boolean. + bool* result = (bool*)PG_GETARG_POINTER(2); + + // Check if the two text values are the same. + *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo); + // Return the result. + PG_RETURN_POINTER(result); +} + +// Calculate the penalty for GiST entries for text type. +Datum gbt_text_penalty(PG_FUNCTION_ARGS) +{ + // Get the two GiST entries. + GISTENTRY* o = (GISTENTRY*)PG_GETARG_POINTER(0); + GISTENTRY* n = (GISTENTRY*)PG_GETARG_POINTER(1); + // Get the result float. + float* result = (float*)PG_GETARG_POINTER(2); + + // Calculate the penalty + PG_RETURN_POINTER(gbt_var_penalty(result,o,n,PG_GET_COLLATION(),&tinfo)); } diff --git a/contrib/btree_gist/btree_time.cpp b/contrib/btree_gist/btree_time.cpp index a249e3dd6..b2b1c546d 100644 --- a/contrib/btree_gist/btree_time.cpp +++ b/contrib/btree_gist/btree_time.cpp @@ -43,133 +43,180 @@ extern "C" Datum gbt_time_same(PG_FUNCTION_ARGS); #define TimeADTGetDatumFast(X) PointerGetDatum(&(X)) #endif -static bool gbt_timegt(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - - return DatumGetBool(DirectFunctionCall2(time_gt, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); +// Compare if time a is greater than time b +static bool gbt_timegt(const void* a, const void* b) +{ + const TimeADT* aa = (const TimeADT*)a; // Cast void pointer a to TimeADT pointer + const TimeADT* bb = (const TimeADT*)b; // Cast void pointer b to TimeADT pointer + + // Use the function time_gt to compare the two time objects, and return the result as a boolean value + return DatumGetBool(DirectFunctionCall2(time_gt, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); +} + +// Compare if time a is greater than or equal to time b +static bool gbt_timege(const void* a, const void* b) +{ + const TimeADT* aa = (const TimeADT*)a; // Cast void pointer a to TimeADT pointer + const TimeADT* bb = (const TimeADT*)b; // Cast void pointer b to TimeADT pointer + + // Use the function time_ge to compare the two time objects, and return the result as a boolean value + return DatumGetBool(DirectFunctionCall2(time_ge, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); +} + +// Compare if time a is equal to time b +static bool gbt_timeeq(const void* a, const void* b) +{ + const TimeADT* aa = (const TimeADT*)a; // Cast void pointer a to TimeADT pointer + const TimeADT* bb = (const TimeADT*)b; // Cast void pointer b to TimeADT pointer + + // Use the function time_eq to compare the two time objects, and return the result as a boolean value + return DatumGetBool(DirectFunctionCall2(time_eq, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); +} + +// Compare if time a is less than or equal to time b +static bool gbt_timele(const void* a, const void* b) +{ + const TimeADT* aa = (const TimeADT*)a; // Cast void pointer a to TimeADT pointer + const TimeADT* bb = (const TimeADT*)b; // Cast void pointer b to TimeADT pointer + + // Use the function time_le to compare the two time objects, and return the result as a boolean value + return DatumGetBool(DirectFunctionCall2(time_le, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); +} + +// Compare if time a is less than time b +static bool gbt_timelt(const void* a, const void* b) +{ + const TimeADT* aa = (const TimeADT*)a; // Cast void pointer a to TimeADT pointer + const TimeADT* bb = (const TimeADT*)b; // Cast void pointer b to TimeADT pointer + + // Use the function time_lt to compare the two time objects, and return the result as a boolean value + return DatumGetBool(DirectFunctionCall2(time_lt, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); } -static bool gbt_timege(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - - return DatumGetBool(DirectFunctionCall2(time_ge, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); -} - -static bool gbt_timeeq(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - - return DatumGetBool(DirectFunctionCall2(time_eq, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); -} - -static bool gbt_timele(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - - return DatumGetBool(DirectFunctionCall2(time_le, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); -} - -static bool gbt_timelt(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - - return DatumGetBool(DirectFunctionCall2(time_lt, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); -} - -static int gbt_timekey_cmp(const void* a, const void* b) -{ - timeKEY* ia = (timeKEY*)(((const Nsrt*)a)->t); - timeKEY* ib = (timeKEY*)(((const Nsrt*)b)->t); - int res; - - res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->lower), TimeADTGetDatumFast(ib->lower))); - if (res == 0) - return DatumGetInt32( - DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->upper), TimeADTGetDatumFast(ib->upper))); - - return res; -} - -static float8 gbt_time_dist(const void* a, const void* b) -{ - const TimeADT* aa = (const TimeADT*)a; - const TimeADT* bb = (const TimeADT*)b; - Interval* i = NULL; - - i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); - return (float8)Abs(INTERVAL_TO_SEC(i)); -} - -static const gbtree_ninfo tinfo = {gbt_t_time, - sizeof(TimeADT), - gbt_timegt, - gbt_timege, - gbt_timeeq, - gbt_timele, - gbt_timelt, - gbt_timekey_cmp, - gbt_time_dist}; - -PG_FUNCTION_INFO_V1(time_dist); -extern "C" Datum time_dist(PG_FUNCTION_ARGS); -Datum time_dist(PG_FUNCTION_ARGS) -{ - Datum diff = DirectFunctionCall2(time_mi_time, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)); - - PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff))); +// Compare two timeKEY objects a and b +static int gbt_timekey_cmp(const void* a, const void* b) +{ + // Cast void pointers a and b to timeKEY pointers + timeKEY* ia = (timeKEY*)(((const Nsrt*)a)->t); + timeKEY* ib = (timeKEY*)(((const Nsrt*)b)->t); + int res; + + // Compare the lower bounds of the timeKEY objects + res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->lower), TimeADTGetDatumFast(ib->lower))); + // If the lower bounds are equal, compare the upper bounds + if (res == 0) + return DatumGetInt32( + DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->upper), TimeADTGetDatumFast(ib->upper))); + + // Return the result of the comparison of the lower bounds + return res; +} + +// Calculate the distance between two time objects a and b +static float8 gbt_time_dist(const void* a, const void* b) +{ + // Cast void pointers a and b to TimeADT pointers + const TimeADT* aa = (const TimeADT*)a; + const TimeADT* bb = (const TimeADT*)b; + Interval* i = NULL; + + // Call the function time_mi_time to get the interval between the two time objects + i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(*aa), TimeADTGetDatumFast(*bb))); + // Return the absolute value of the interval converted to seconds + return (float8)Abs(INTERVAL_TO_SEC(i)); +} + +// Define the information about the time type for the generalized binary tree (gbtree) +static const gbtree_ninfo tinfo = {gbt_t_time, + sizeof(TimeADT), + gbt_timegt, + gbt_timege, + gbt_timeeq, + gbt_timele, + gbt_timelt, + gbt_timekey_cmp, + gbt_time_dist}; + +// Define the information about the time_dist function for PostgreSQL +PG_FUNCTION_INFO_V1(time_dist); +extern "C" Datum time_dist(PG_FUNCTION_ARGS); +// Define the time_dist function for PostgreSQL +Datum time_dist(PG_FUNCTION_ARGS) +{ + // Call the function time_mi_time to get the interval between the two time objects passed as arguments + Datum diff = DirectFunctionCall2(time_mi_time, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)); + + // Return the absolute value of the interval as a PostgreSQL interval object + PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff))); } /************************************************** * time ops **************************************************/ -Datum gbt_time_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); -} - -Datum gbt_timetz_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - GISTENTRY* retval = NULL; - - if (entry->leafkey) { - timeKEY* r = (timeKEY*)palloc(sizeof(timeKEY)); - TimeTzADT* tz = DatumGetTimeTzADTP(entry->key); - TimeADT tmp; - - retval = (GISTENTRY*)palloc(sizeof(GISTENTRY)); - - /* We are using the time + zone only to compress */ -#ifdef HAVE_INT64_TIMESTAMP - tmp = tz->time + (tz->zone * INT64CONST(1000000)); -#else - tmp = (tz->time + tz->zone); -#endif - r->lower = r->upper = tmp; - gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); - } else - retval = entry; - PG_RETURN_POINTER(retval); -} - -Datum gbt_time_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - TimeADT query = PG_GETARG_TIMEADT(1); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); +// Compress the time data +Datum gbt_time_compress(PG_FUNCTION_ARGS) +{ + // Get the entry from the argument + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Initialize the return value + GISTENTRY* retval = NULL; + + // Return the compressed value + PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo)); +} + +// Compress the time zone data +Datum gbt_timetz_compress(PG_FUNCTION_ARGS) +{ + // Get the entry from the argument + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Initialize the return value + GISTENTRY* retval = NULL; + + // If the entry is a leaf key + if (entry->leafkey) { + // Allocate memory for the timeKEY object + timeKEY* r = (timeKEY*)palloc(sizeof(timeKEY)); + // Get the time zone data from the entry + TimeTzADT* tz = DatumGetTimeTzADTP(entry->key); + // Initialize a temporary time object + TimeADT tmp; + + // Allocate memory for the return entry + retval = (GISTENTRY*)palloc(sizeof(GISTENTRY)); + + // Use the time and zone to compress the data +#ifdef HAVE_INT64_TIMESTAMP + tmp = tz->time + (tz->zone * INT64CONST(1000000)); +#else + tmp = (tz->time + tz->zone); +#endif + // Set the lower and upper bounds of the timeKEY object to the compressed time value + r->lower = r->upper = tmp; + // Initialize the return entry with the compressed timeKEY object and other information from the original entry + gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); + } else { + // If the entry is not a leaf key, return the original entry + retval = entry; + } + // Return the compressed entry or the original entry if it is not a leaf key + PG_RETURN_POINTER(retval); +} + +// Check if the query is consistent with the compressed time data +Datum gbt_time_consistent(PG_FUNCTION_ARGS) +{ + // Get the entry from the argument + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Get the query time from the argument + TimeADT query = PG_GETARG_TIMEADT(1); + // Get the strategy number from the argument + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + // Get a pointer to the recheck boolean from the argument + bool* recheck = (bool*)PG_GETARG_POINTER(4); + timeKEY* kkk = (timeKEY*)DatumGetPointer(entry->key); GBT_NUMKEY_R key; @@ -182,101 +229,142 @@ Datum gbt_time_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&query, &strategy, GIST_LEAF(entry), &tinfo)); } -Datum gbt_time_distance(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - TimeADT query = PG_GETARG_TIMEADT(1); - - timeKEY* kkk = (timeKEY*)DatumGetPointer(entry->key); - GBT_NUMKEY_R key; - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_timetz_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); - TimeTzADT* query = PG_GETARG_TIMETZADT_P(1); - StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); - - bool* recheck = (bool*)PG_GETARG_POINTER(4); - timeKEY* kkk = (timeKEY*)DatumGetPointer(entry->key); - TimeADT qqq; - GBT_NUMKEY_R key; - - /* All cases served by this function are inexact */ - *recheck = true; - -#ifdef HAVE_INT64_TIMESTAMP - qqq = query->time + (query->zone * INT64CONST(1000000)); -#else - qqq = (query->time + query->zone); -#endif - - key.lower = (GBT_NUMKEY*)&kkk->lower; - key.upper = (GBT_NUMKEY*)&kkk->upper; - - PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&qqq, &strategy, GIST_LEAF(entry), &tinfo)); -} - -Datum gbt_time_union(PG_FUNCTION_ARGS) -{ - GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); +// Calculate the distance between the time data and the query +Datum gbt_time_distance(PG_FUNCTION_ARGS) +{ + // Get the entry from the argument + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Get the query time from the argument + TimeADT query = PG_GETARG_TIMEADT(1); + + // Get the timeKEY object from the entry's key datum object + timeKEY* kkk = (timeKEY*)DatumGetPointer(entry->key); + // Initialize the key structure with the lower and upper bounds of the timeKEY object + GBT_NUMKEY_R key; + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + // Return the distance between the time data and the query + PG_RETURN_FLOAT8(gbt_num_distance(&key, (void*)&query, GIST_LEAF(entry), &tinfo)); +} + +// Check if the query is consistent with the time zone data +Datum gbt_timetz_consistent(PG_FUNCTION_ARGS) +{ + // Get the entry from the argument + GISTENTRY* entry = (GISTENTRY*)PG_GETARG_POINTER(0); + // Get the query time zone from the argument + TimeTzADT* query = PG_GETARG_TIMETZADT_P(1); + // Get the strategy number from the argument + StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2); + + // Get a pointer to the recheck boolean from the argument + bool* recheck = (bool*)PG_GETARG_POINTER(4); + // Get the timeKEY object from the entry's key datum object + timeKEY* kkk = (timeKEY*)DatumGetPointer(entry->key); + // Initialize a temporary time object + TimeADT qqq; + // Initialize the key structure with the lower and upper bounds of the timeKEY object + GBT_NUMKEY_R key; + + /* All cases served by this function are inexact */ + *recheck = true; + +#ifdef HAVE_INT64_TIMESTAMP + qqq = query->time + (query->zone * INT64CONST(1000000)); +#else + qqq = (query->time + query->zone); +#endif + + key.lower = (GBT_NUMKEY*)&kkk->lower; + key.upper = (GBT_NUMKEY*)&kkk->upper; + + // Return if the query is consistent with the time zone data + PG_RETURN_BOOL(gbt_num_consistent(&key, (void*)&qqq, &strategy, GIST_LEAF(entry), &tinfo)); +} + +// Union the time data +Datum gbt_time_union(PG_FUNCTION_ARGS) +{ + // Get the entry vector from the argument + GistEntryVector* entryvec = (GistEntryVector*)PG_GETARG_POINTER(0); void* out = palloc(sizeof(timeKEY)); *(int*)PG_GETARG_POINTER(1) = sizeof(timeKEY); PG_RETURN_POINTER(gbt_num_union((GBT_NUMKEY*)out, entryvec, &tinfo)); } -Datum gbt_time_penalty(PG_FUNCTION_ARGS) -{ - timeKEY* origentry = (timeKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); - timeKEY* newentry = (timeKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); - float* result = (float*)PG_GETARG_POINTER(2); - Interval* intr = NULL; - double res; - double res2; - - intr = DatumGetIntervalP( - DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(newentry->upper), TimeADTGetDatumFast(origentry->upper))); - res = INTERVAL_TO_SEC(intr); - res = Max(res, 0); - - intr = DatumGetIntervalP( - DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(origentry->lower), TimeADTGetDatumFast(newentry->lower))); - res2 = INTERVAL_TO_SEC(intr); - res2 = Max(res2, 0); - - res += res2; - - *result = 0.0; - - if (res > 0) { - intr = DatumGetIntervalP(DirectFunctionCall2( - time_mi_time, TimeADTGetDatumFast(origentry->upper), TimeADTGetDatumFast(origentry->lower))); - *result += FLT_MIN; - *result += (float)(res / (res + INTERVAL_TO_SEC(intr))); - *result *= (FLT_MAX / (((GISTENTRY*)PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } - - PG_RETURN_POINTER(result); -} - -Datum gbt_time_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER( - gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); -} - -Datum gbt_time_same(PG_FUNCTION_ARGS) -{ - timeKEY* b1 = (timeKEY*)PG_GETARG_POINTER(0); - timeKEY* b2 = (timeKEY*)PG_GETARG_POINTER(1); - bool* result = (bool*)PG_GETARG_POINTER(2); - - *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); - PG_RETURN_POINTER(result); -} +// Calculate the penalty for the time data +Datum gbt_time_penalty(PG_FUNCTION_ARGS) +{ + // Get the original and new entries' timeKEY objects from the arguments + timeKEY* origentry = (timeKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(0))->key); + timeKEY* newentry = (timeKEY*)DatumGetPointer(((GISTENTRY*)PG_GETARG_POINTER(1))->key); + // Get a pointer to the result float from the argument + float* result = (float*)PG_GETARG_POINTER(2); + // Initialize an interval object + Interval* intr = NULL; + // Initialize result variables + double res; + double res2; + + // Calculate the time interval between the new and original entries' upper bounds + intr = DatumGetIntervalP( + DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(newentry->upper), TimeADTGetDatumFast(origentry->upper))); + // Convert the interval to seconds and take the maximum value as 0 + res = INTERVAL_TO_SEC(intr); + res = Max(res, 0); + + // Calculate the time interval between the new and original entries' lower bounds + intr = DatumGetIntervalP( + DirectFunctionCall2(time_mi_time, TimeADTGetDatumFast(origentry->lower), TimeADTGetDatumFast(newentry->lower))); + // Convert the interval to seconds and take the maximum value as 0 + res2 = INTERVAL_TO_SEC(intr); + res2 = Max(res2, 0); + + // Add the two intervals together + res += res2; + + // Initialize the result to 0.0 + *result = 0.0; + + // If the total interval is greater than 0, calculate the penalty + if (res > 0) { + // Calculate the time interval between the original entry's upper and lower bounds + intr = DatumGetIntervalP(DirectFunctionCall2( + time_mi_time, TimeADTGetDatumFast(origentry->upper), TimeADTGetDatumFast(origentry->lower))); + // Add a small value to the result + *result += FLT_MIN; + // Calculate the ratio of the total interval to the original entry's upper and lower bounds' interval + *result += (float)(res / (res + INTERVAL_TO_SEC(intr))); + // Scale the result by a maximum value divided by the number of attributes plus 1 + *result *= (FLT_MAX / (((GISTENTRY*)PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); + } + + // Return a pointer to the result float + PG_RETURN_POINTER(result); +} + +// Pick a split point for the time data +Datum gbt_time_picksplit(PG_FUNCTION_ARGS) +{ + // Return a pointer to the result of picking a split point for the time data + PG_RETURN_POINTER( + gbt_num_picksplit((GistEntryVector*)PG_GETARG_POINTER(0), (GIST_SPLITVEC*)PG_GETARG_POINTER(1), &tinfo)); +} + +// Check if two time data are the same +Datum gbt_time_same(PG_FUNCTION_ARGS) +{ + // Get the two timeKEY objects from the arguments + timeKEY* b1 = (timeKEY*)PG_GETARG_POINTER(0); + timeKEY* b2 = (timeKEY*)PG_GETARG_POINTER(1); + // Get a pointer to the result boolean from the argument + bool* result = (bool*)PG_GETARG_POINTER(2); + + // Check if the two time data are the same and store the result in the result boolean + *result = gbt_num_same((GBT_NUMKEY*)b1, (GBT_NUMKEY*)b2, &tinfo); + // Return a pointer to the result boolean + PG_RETURN_POINTER(result); +} \ No newline at end of file -- 2.34.1 From 6b9fcdb2c7efc44cc2ccd56352feea414f4b9958 Mon Sep 17 00:00:00 2001 From: 111yuzhiying <2965896660@qq.com> Date: Fri, 22 Sep 2023 11:58:35 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0tools=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/citext/citext.cpp | 58 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/contrib/citext/citext.cpp b/contrib/citext/citext.cpp index 3f318c50a..96894063e 100644 --- a/contrib/citext/citext.cpp +++ b/contrib/citext/citext.cpp @@ -240,26 +240,38 @@ Datum citext_ge(PG_FUNCTION_ARGS) * =================== */ -PG_FUNCTION_INFO_V1(citext_smaller); - -Datum citext_smaller(PG_FUNCTION_ARGS) -{ - text* left = PG_GETARG_TEXT_PP(0); - text* right = PG_GETARG_TEXT_PP(1); - text* result = NULL; - - result = (citextcmp(left, right, PG_GET_COLLATION()) < 0) ? left : right; - PG_RETURN_TEXT_P(result); -} - -PG_FUNCTION_INFO_V1(citext_larger); - -Datum citext_larger(PG_FUNCTION_ARGS) -{ - text* left = PG_GETARG_TEXT_PP(0); - text* right = PG_GETARG_TEXT_PP(1); - text* result = NULL; - - result = (citextcmp(left, right, PG_GET_COLLATION()) > 0) ? left : right; - PG_RETURN_TEXT_P(result); -} +// Declare a function named citext_smaller, which is an internal function of PostgreSQL, used to compare whether the first citext value is smaller than the second. +PG_FUNCTION_INFO_V1(citext_smaller); + +// Implement the citext_smaller function. This function takes two parameters (two text* pointers) and returns a text* value. +Datum citext_smaller(PG_FUNCTION_ARGS) +{ + // Get the first and second text* pointers from the function parameters and assign them to left and right respectively. + text* left = PG_GETARG_TEXT_PP(0); + text* right = PG_GETARG_TEXT_PP(1); + // Initialize a text* variable result, which will store the result of the comparison. + text* result = NULL; + + // Use the citextcmp function to compare left and right. If left is smaller than right, assign left to result; otherwise, assign right to result. + result = (citextcmp(left, right, PG_GET_COLLATION()) < 0) ? left : right; + // Return the result of the comparison. + PG_RETURN_TEXT_P(result); +} + +// Declare a function named citext_larger, which is an internal function of PostgreSQL, used to compare whether the first citext value is larger than the second. +PG_FUNCTION_INFO_V1(citext_larger); + +// Implement the citext_larger function. This function takes two parameters (two text* pointers) and returns a text* value. +Datum citext_larger(PG_FUNCTION_ARGS) +{ + // Get the first and second text* pointers from the function parameters and assign them to left and right respectively. + text* left = PG_GETARG_TEXT_PP(0); + text* right = PG_GETARG_TEXT_PP(1); + // Initialize a text* variable result, which will store the result of the comparison. + text* result = NULL; + + // Use the citextcmp function to compare left and right. If left is larger than right, assign left to result; otherwise, assign right to result. + result = (citextcmp(left, right, PG_GET_COLLATION()) > 0) ? left : right; + // Return the result of the comparison. + PG_RETURN_TEXT_P(result); +} \ No newline at end of file -- 2.34.1