diff --git a/0018-update-get_parent_limits-stored-procedure.patch b/0018-update-get_parent_limits-stored-procedure.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c0681231a6754181c1f1d193bfd0278fbd13616 --- /dev/null +++ b/0018-update-get_parent_limits-stored-procedure.patch @@ -0,0 +1,517 @@ +From 9f7774907e18d2446ab1e9693c6ec0837afa3cab Mon Sep 17 00:00:00 2001 +From: motodiary +Date: Fri, 17 May 2024 14:07:07 +0800 +Subject: [PATCH] update 'get_parent_limits' stored procedure + +--- + src/database/pgsql_common.c | 3 +- + .../pgsql/accounting_storage_pgsql.c | 359 +++++++++++------- + .../accounting_storage/pgsql/as_pgsql_assoc.c | 21 +- + 3 files changed, 225 insertions(+), 158 deletions(-) + +diff --git a/src/database/pgsql_common.c b/src/database/pgsql_common.c +index 8191f9e..d301c00 100755 +--- a/src/database/pgsql_common.c ++++ b/src/database/pgsql_common.c +@@ -1295,6 +1295,7 @@ extern int pgsql_db_create_table(pgsql_conn_t *pgsql_conn, char *table_name, + } + xstrcat(query, ending); + ++ debug4("%s table_name %s query %s", __func__, table_name, query); + if (pgsql_db_query(pgsql_conn, query) == SLURM_ERROR) { + xfree(query); + return SLURM_ERROR; +@@ -1416,7 +1417,7 @@ extern pgsql_row pgsql_fetch_row(pgsql_res_t* result) + + RETCODE pg_ret = SQLFetch(result->stmt); + SQLRETURN ret = 0; +- debug4("%s SQLFetch ret %d", __func__, pg_ret); ++ + if(pg_ret != SQL_NO_DATA){ + pgsql_row row = (pgsql_row)malloc(result->sNumCols * sizeof(char*)); + if(row == NULL){ +diff --git a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c +index e0e1e4e..20f65f0 100755 +--- a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c ++++ b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c +@@ -580,142 +580,211 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + * get_parent_limits_select in as_pgsql_assoc.c + */ + char* get_parent_proc = +- "CREATE OR REPLACE FUNCTION get_parent_limits(\n \ +- my_table text,\n \ +- acct text,\n \ +- cluster text,\n \ +- without_limits int\n \ +- )\n \ +- RETURNS void AS $$\n \ +- DECLARE\n \ +- s text;\n \ +- par_id int;\n \ +- mj int;\n \ +- mja int;\n \ +- mpt int;\n \ +- msj int;\n \ +- mwpj int;\n \ +- mtpj text;\n \ +- mtpn text;\n \ +- mtmpj text;\n \ +- mtrm text;\n \ +- prio int;\n \ +- def_qos_id int;\n \ +- qos text;\n \ +- delta_qos text;\n \ +- my_acct text;\n \ +- my_acct_new text;\n \ +- BEGIN\n \ +- par_id := NULL;\n \ +- mj := NULL;\n \ +- mja := NULL;\n \ +- mpt := NULL;\n \ +- msj := NULL;\n \ +- mwpj := NULL;\n \ +- mtpj := '';\n \ +- mtpn := '';\n \ +- mtmpj := '';\n \ +- mtrm := '';\n \ +- prio := NULL;\n \ +- def_qos_id := NULL;\n \ +- qos := '';\n \ +- delta_qos := '';\n \ +- my_acct := acct;\n \ +- \n \ +- IF without_limits = 1 THEN\n \ +- mj := 0;\n \ +- msj := 0;\n \ +- mwpj := 0;\n \ +- prio := 0;\n \ +- def_qos_id := 0;\n \ +- qos := '1';\n \ +- END IF;\n \ +- \n \ +- LOOP\n \ +- s := 'SELECT';\n \ +- \n \ +- IF par_id IS NULL THEN\n \ +- s := CONCAT(s, '@par_id := id_assoc,');\n \ +- END IF;\n \ +- \n \ +- IF mj IS NULL THEN\n \ +- s := CONCAT(s, '@mj := max_jobs,');\n \ +- END IF;\n \ +- IF mja IS NULL THEN\n \ +- \n \ +- s := CONCAT(s, '@mja := max_jobs_accrue,');\n \ +- END IF;\n \ +- \n \ +- IF mpt IS NULL THEN\n \ +- s := CONCAT(s, '@mpt := min_prio_thresh,');\n \ +- END IF;\n \ +- \n \ +- IF msj IS NULL THEN\n \ +- s := CONCAT(s, '@msj := max_submit_jobs,');\n \ +- END IF;\n \ +- \n \ +- IF mwpj IS NULL THEN\n \ +- s := CONCAT(s, '@mwpj := max_wall_pj,');\n \ +- END IF;\n \ +- \n \ +- IF prio IS NULL THEN\n \ +- s := CONCAT(s, '@prio := priority,');\n \ +- END IF;\n \ +- \n \ +- IF def_qos_id IS NULL THEN\n \ +- s := CONCAT(s, '@def_qos_id := def_qos_id,');\n \ +- END IF;\n \ +- \n \ +- IF qos = '' THEN\n \ +- s := CONCAT(s, '@qos := qos,\n \ +- @delta_qos := REPLACE(CONCAT(delta_qos, @delta_qos), '',,'', '',''),');\n \ +- END IF;\n \ +- \n \ +- s := CONCAT(s, '\n \ +- @mtpj := CONCAT(@mtpj,\n \ +- '',''\n \ +- CASE WHEN @mtpj != '''' AND max_tres_pj != '''' THEN\n \ +- ELSE\n \ +- ''''\n \ +- END,\n \ +- max_tres_pj),\n \ +- \n \ +- @mtpn := CONCAT(@mtpn,\n \ +- CASE WHEN @mtpn != '''' AND max_tres_pn != '''' THEN\n \ +- '',''\n \ +- ELSE\n \ +- ''''\n \ +- END,\n \ +- max_tres_pn),\n \ +- \n \ +- @mtmpj := CONCAT(@mtmpj,\n \ +- CASE WHEN @mtmpj != '''' AND max_tres_mins_pj != '''' THEN\n \ +- '',''\n \ +- ELSE\n \ +- ''''\n \ +- END,\n \ +- max_tres_mins_pj),\n \ +- \n \ +- @mtrm := CONCAT(@mtrm,\n \ +- CASE WHEN @mtrm != '''' AND max_tres_run_mins != '''' THEN\n \ +- '',''\n \ +- ELSE\n \ +- ''''\n \ +- END,\n \ +- max_tres_run_mins),\n \ +- \n \ +- @my_acct_new := parent_acct\n \ +- FROM ' || cluster || '_' || my_table || '\n \ +- WHERE acct = ''' OR my_acct OR ''' AND user = ''''');\n \ +- \n \ +- EXECUTE s;\n \ +- \n \ +- my_acct := my_acct_new;\n \ +- \n \ +- EXIT WHEN without_limits OR my_acct = '';\n \ +- END LOOP;\n \ +- END;\n \ +- $$ LANGUAGE plpgsql;"; ++ "CREATE OR REPLACE FUNCTION get_parent_limits( \n\ ++ my_table text, acct text, cluster text, without_limits int) \n\ ++ RETURNS TABLE (out_par_id int, out_mj int, out_mja int , out_mpt int, out_msj int, out_mwpj int, out_mtpj text, out_mtpn text, out_mtmpj text, out_mtrm text, out_def_qos_id int, out_qos text, out_delta_qos text, out_prio int) \n\ ++ AS $$ \n\ ++ DECLARE \n\ ++ par_id int; \n\ ++ mj int; \n\ ++ mja int; \n\ ++ mpt int; \n\ ++ msj int; \n\ ++ mwpj int; \n\ ++ mtpj text; \n\ ++ mtpn text; \n\ ++ mtmpj text; \n\ ++ mtrm text; \n\ ++ prio int; \n\ ++ def_qos_id int; \n\ ++ qos text; \n\ ++ delta_qos text; \n\ ++ my_acct text := acct; \n\ ++ my_acct_new text; \n\ ++ s text; \n\ ++ BEGIN \n\ ++ par_id := NULL; \n\ ++ mj := NULL; \n\ ++ mja := NULL; \n\ ++ mpt := NULL; \n\ ++ msj := NULL; \n\ ++ mwpj := NULL; \n\ ++ mtpj := ''; \n\ ++ mtpn := ''; \n\ ++ mtmpj := ''; \n\ ++ mtrm := ''; \n\ ++ prio := NULL; \n\ ++ def_qos_id := NULL; \n\ ++ qos := ''; \n\ ++ delta_qos := ''; \n\ ++ \n\ ++ IF without_limits = 1 THEN \n\ ++ mj := 0; \n\ ++ msj := 0; \n\ ++ mwpj := 0; \n\ ++ prio := 0; \n\ ++ def_qos_id := 0; \n\ ++ qos := '1'; \n\ ++ END IF; \n\ ++ \n\ ++ LOOP \n\ ++ s := 'SELECT '; \n\ ++ \n\ ++ IF par_id IS NULL THEN \n\ ++ s := s || 'id_assoc, '; \n\ ++ ELSE \n\ ++ s := s || par_id || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mj IS NULL THEN \n\ ++ s := s || 'max_jobs, '; \n\ ++ ELSE \n\ ++ s := s || mj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mja IS NULL THEN \n\ ++ s := s || 'max_jobs_accrue, '; \n\ ++ ELSE \n\ ++ s := s || mja || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mpt IS NULL THEN \n\ ++ s := s || 'min_prio_thresh, '; \n\ ++ ELSE \n\ ++ s := s || mpt || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF msj IS NULL THEN \n\ ++ s := s || 'max_submit_jobs, '; \n\ ++ ELSE \n\ ++ s := s || msj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mwpj IS NULL THEN \n\ ++ s := s || 'max_wall_pj, '; \n\ ++ ELSE \n\ ++ s := s || mwpj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF prio IS NULL THEN \n\ ++ s := s || 'priority, '; \n\ ++ ELSE \n\ ++ s := s || prio || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF def_qos_id IS NULL THEN \n\ ++ s := s || 'def_qos_id, '; \n\ ++ ELSE \n\ ++ s := s || def_qos_id || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF qos = '' THEN \n\ ++ s := s || 'qos, delta_qos, '; \n\ ++ ELSE \n\ ++ s := s || qos || ', ' || delta_qos || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ s := s || \n\ ++ 'CONCAT(max_tres_pj), ' || \n\ ++ 'CONCAT(max_tres_pn), ' || \n\ ++ 'CONCAT(max_tres_mins_pj), ' || \n\ ++ 'CONCAT(max_tres_run_mins), ' || \n\ ++ 'parent_acct' || \n\ ++ ' FROM ' || \n\ ++ cluster || '_' || my_table || \n\ ++ ' WHERE acct = ''' || my_acct || ''' AND \"user\" = ''' || ''''; \n\ ++ \n\ ++ EXECUTE s INTO par_id, mj, mja, mpt, msj, mwpj, mtpj, mtpn, mtmpj, mtrm, my_acct_new; \n\ ++ \n\ ++ EXIT WHEN without_limits = 0 OR my_acct = ''; \n\ ++ END LOOP; \n\ ++ \n\ ++ IF without_limits = 1 THEN \n\ ++ mj := 0; \n\ ++ msj := 0; \n\ ++ mwpj := 0; \n\ ++ prio := 0; \n\ ++ def_qos_id := 0; \n\ ++ qos := '1'; \n\ ++ END IF; \n\ ++ \n\ ++ LOOP \n\ ++ s := 'SELECT '; \n\ ++ \n\ ++ IF par_id IS NULL THEN \n\ ++ s := s || 'id_assoc, '; \n\ ++ ELSE \n\ ++ s := s || par_id || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mj IS NULL THEN \n\ ++ s := s || 'max_jobs, '; \n\ ++ ELSE \n\ ++ s := s || mj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mja IS NULL THEN \n\ ++ s := s || 'max_jobs_accrue, '; \n\ ++ ELSE \n\ ++ s := s || mja || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mpt IS NULL THEN \n\ ++ s := s || 'min_prio_thresh, '; \n\ ++ ELSE \n\ ++ s := s || mpt || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF msj IS NULL THEN \n\ ++ s := s || 'max_submit_jobs, '; \n\ ++ ELSE \n\ ++ s := s || msj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF mwpj IS NULL THEN \n\ ++ s := s || 'max_wall_pj, '; \n\ ++ ELSE \n\ ++ s := s || mwpj || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF prio IS NULL THEN \n\ ++ s := s || 'priority, '; \n\ ++ ELSE \n\ ++ s := s || prio || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF def_qos_id IS NULL THEN \n\ ++ s := s || 'def_qos_id, '; \n\ ++ ELSE \n\ ++ s := s || def_qos_id || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ IF qos = '' THEN \n\ ++ s := s || 'qos, delta_qos, '; \n\ ++ ELSE \n\ ++ s := s || qos || ', ' || delta_qos || ', '; \n\ ++ END IF; \n\ ++ \n\ ++ s := s || \n\ ++ 'CONCAT(max_tres_pj), ' || \n\ ++ 'CONCAT(max_tres_pn), ' || \n\ ++ 'CONCAT(max_tres_mins_pj), ' || \n\ ++ 'CONCAT(max_tres_run_mins), ' || \n\ ++ 'parent_acct' || \n\ ++ ' FROM ' || \n\ ++ cluster || '_' || my_table || \n\ ++ ' WHERE acct = ''' || my_acct || ''' AND \"user\" = ''' || ''''; \n\ ++ \n\ ++ EXECUTE s INTO par_id, mj, mja, mpt, msj, mwpj, mtpj, mtpn, mtmpj, mtrm, def_qos_id, qos, delta_qos, prio; \n\ ++ \n\ ++ EXIT WHEN without_limits = 0 OR my_acct = ''; \n\ ++ END LOOP; \n\ ++ \n\ ++ RETURN QUERY select par_id, mj, mja, mpt, msj, mwpj, mtpj, mtpn, mtmpj, mtrm, def_qos_id, qos, delta_qos, prio; \n\ ++ \n\ ++ END; \n\ ++ \n\ ++ $$LANGUAGE plpgsql;"; + + char* get_coord_qos = + "CREATE OR REPLACE FUNCTION get_coord_qos(my_table text, acct text, cluster text, coord text) \n \ +@@ -791,7 +860,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + return SLURM_ERROR; + + ending = xstrdup_printf(", primary key (id)); CREATE UNIQUE INDEX IF NOT EXISTS %s_udx ON %s " +- "(substr(type, 1, 42), substr(name, 1, 42));", tres_table, tres_table); ++ "\"type\", \"name\");", tres_table, tres_table); + xstrfmtcat(ending, "CREATE SEQUENCE IF NOT EXISTS %s_id_seq MINVALUE 1001 START WITH 1001;" + "ALTER TABLE %s ALTER COLUMN id SET DEFAULT nextval('%s_id_seq'::regclass);", + tres_table, tres_table, tres_table); +@@ -935,7 +1004,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + return SLURM_ERROR; + + ending = xstrdup_printf(", primary key (id));" +- "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (name, server, type);", ++ "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (\"name\", server, \"type\");", + res_table, res_table); + if (pgsql_db_create_table(pgsql_conn, res_table, + res_table_fields, ending) == SLURM_ERROR) { +@@ -945,7 +1014,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + xfree(ending); + + ending = xstrdup_printf(", primary key (res_id, cluster));" +- "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (res_id, substr(cluster, 1, 42));", ++ "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (res_id, cluster);", + clus_res_table, clus_res_table); + if (pgsql_db_create_table(pgsql_conn, clus_res_table, + clus_res_table_fields, ending) == SLURM_ERROR) { +@@ -955,7 +1024,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + xfree(ending); + + ending = xstrdup_printf(", primary key (id));" +- "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (substr(name, 1, 42));", ++ "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (\"name\");", + qos_table, qos_table); + if (pgsql_db_create_table(pgsql_conn, qos_table, + qos_table_fields, ending) == SLURM_ERROR) { +@@ -983,7 +1052,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + "description) " + "VALUES (%ld, %ld, '%s', " + "'Added as default') " +- "ON CONFLICT (substr(name, 1, 42)) DO UPDATE " ++ "ON CONFLICT (\"name\") DO UPDATE " + "SET deleted = 0;", + qos_table, now, now, qos); + +@@ -1003,7 +1072,7 @@ static int _as_pgsql_acct_check_tables(pgsql_conn_t *pgsql_conn) + "(creation_time, mod_time, name, description) " + "VALUES (%ld, %ld, 'normal', " + "'Normal QOS default') " +- "ON CONFLICT (substr(name, 1, 42)) DO UPDATE " ++ "ON CONFLICT (\"name\") DO UPDATE " + "SET deleted = 0;", + qos_table, now, now); + +@@ -1160,7 +1229,7 @@ extern int create_cluster_assoc_table( + + ending = xstrdup_printf(", primary key (id_assoc));" + "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s " +- "(substr(\"user\", 1, 42), substr(acct, 1, 42), substr(\"partition\", 1, 42));" ++ "(\"user\", acct, \"partition\");" + "CREATE INDEX IF NOT EXISTS %s_lft_idx ON %s (lft);" + "CREATE INDEX IF NOT EXISTS %s_acct_idx ON %s (acct);", + table_prefix, table_name, table_prefix, table_name, table_prefix, table_name); +@@ -1432,7 +1501,7 @@ extern int create_cluster_tables(pgsql_conn_t *pgsql_conn, char *cluster_name) + + ending = xstrdup_printf(", primary key (node_name, time_start));" + "CREATE INDEX IF NOT EXISTS %s_rollup_idx ON %s " +- "(substr(node_name, 1, 42), time_start, time_end, state);", ++ "(node_name, time_start, time_end, state);", + table_prefix, table_name); + if (pgsql_db_create_table(pgsql_conn, table_name, + event_table_fields, ending) == SLURM_ERROR) { +@@ -1530,7 +1599,7 @@ extern int create_cluster_tables(pgsql_conn_t *pgsql_conn, char *cluster_name) + cluster_name, wckey_table); + + ending = xstrdup_printf(", primary key (id_wckey));" +- "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (substr(wckey_name, 1, 42), substr(\"user\", 1, 42));", ++ "CREATE UNIQUE INDEX IF NOT EXISTS %s_udex ON %s (wckey_name, \"user\");", + table_prefix, table_name); + if (pgsql_db_create_table(pgsql_conn, table_name, + wckey_table_fields, ending) == SLURM_ERROR) { +diff --git a/src/plugins/accounting_storage/pgsql/as_pgsql_assoc.c b/src/plugins/accounting_storage/pgsql/as_pgsql_assoc.c +index eb0eb9c..b613738 100755 +--- a/src/plugins/accounting_storage/pgsql/as_pgsql_assoc.c ++++ b/src/plugins/accounting_storage/pgsql/as_pgsql_assoc.c +@@ -735,10 +735,9 @@ static int _set_assoc_limits_for_add( + else + return SLURM_SUCCESS; + +- query = xstrdup_printf("call get_parent_limits('%s', " +- "'%s', '%s', %u); %s", +- assoc_table, parent, assoc->cluster, 0, +- get_parent_limits_select); ++ query = xstrdup_printf("select * from get_parent_limits('%s'::text, " ++ "'%s'::text, '%s'::text, %u::integer);", ++ assoc_table, parent, assoc->cluster, 0); + debug4("%d(%s:%d) query\n%s", + pgsql_conn->conn, THIS_FILE, __LINE__, query); + result = pgsql_db_query_ret(pgsql_conn, query, 1); +@@ -1472,11 +1471,10 @@ static int _process_modify_assoc_results(pgsql_conn_t *pgsql_conn, + /* If there is a variable cleared here we need to make + sure we get the parent's information, if any. */ + query = xstrdup_printf( +- "call get_parent_limits('%s', " +- "'%s', '%s', %u); %s", ++ "select * from get_parent_limits('%s'::text, " ++ "'%s'::text, '%s'::text, %u::integer);", + assoc_table, account, +- cluster_name, 0, +- get_parent_limits_select); ++ cluster_name, 0); + debug4("%d(%s:%d) query\n%s", + pgsql_conn->conn, THIS_FILE, __LINE__, query); + result2 = pgsql_db_query_ret(pgsql_conn, query, 1); +@@ -2129,12 +2127,11 @@ static int _cluster_get_assocs(pgsql_conn_t *pgsql_conn, + || xstrcmp(parent_acct, last_acct) + || xstrcmp(cluster_name, last_cluster))) { + query = xstrdup_printf( +- "call get_parent_limits('%s', " +- "'%s', '%s', %u); %s", ++ "select * from get_parent_limits('%s'::text, " ++ "'%s'::text, '%s'::text, %u::integer);", + assoc_table, parent_acct, + cluster_name, +- without_parent_limits, +- get_parent_limits_select); ++ without_parent_limits); + debug4("%d(%s:%d) query\n%s", + pgsql_conn->conn, THIS_FILE, __LINE__, query); + result2 = pgsql_db_query_ret(pgsql_conn, query, 1); +-- +2.33.0 + diff --git a/slurm.spec b/slurm.spec index 42da0fbb557e5e33743e00bf2b348f3a60ce5bbc..677e98128e2399e0df4ed46c17f3b9753e2e472c 100644 --- a/slurm.spec +++ b/slurm.spec @@ -1,6 +1,6 @@ Name: slurm Version: 21.08.8 -%define rel 20 +%define rel 21 Release: %{rel}%{?dist} Summary: Slurm Workload Manager @@ -33,6 +33,7 @@ Patch14: 0014-remove-FOR-UPDATE-in-sql.patch Patch15: 0015-fix-partition-conflict-in-tables.patch Patch16: 0016-resume-autocommit-off-option.patch Patch17: 0017-update-jobcomp_table-field.patch +Patch18: 0018-update-get_parent_limits-stored-procedure.patch # build options .rpmmacros options change to default action # ==================== ==================== ======================== @@ -725,6 +726,9 @@ rm -rf %{buildroot} %systemd_postun_with_restart slurmdbd.service %changelog +* Fri May 17 2024 Xing Liu - 21.08.8-21 +- update 'get_parent_limits' stored procedure + * Fri May 17 2024 Xing Liu - 21.08.8-20 - update jobcomp_table field