/* * GUC array: one invalid guc + non-userset guc * return ArrayType contain non-userset guc, ignore invalid guc */ void test__GUCArrayReset__invalid_guc(void **state) { ArrayType *in; ArrayType *out; Datum d; List *guc_list; int elems; build_guc_variables(); will_return(superuser, false); /* construct text array */ elems = 2; guc_list = list_make2("invalid_guc=true", "gp_log_format=text"); in = create_guc_array(guc_list, elems); out = GUCArrayReset(in); assert_not_null(out); assert_int_equal(ARR_DIMS(out)[0], 1); d = PointerGetDatum(ARR_DATA_PTR(out)); assert_int_equal(strlen("gp_log_format=text"), VARLEN(d)); assert_memory_equal(VARDATA(d), "gp_log_format=text", VARLEN(d)); list_free(guc_list); pfree(in); pfree(out); }
/* * GUC array: mix of PGC_USERSET, PGC_POSTMASTER, PGC_SUSET * return ArrayType contains non-PGC_USERSET */ void test__GUCArrayReset__mix_guc(void **state) { ArrayType *in; ArrayType *out; Datum d; List *guc_list; int elems; build_guc_variables(); will_return(superuser, false); /* construct text array */ elems = 4; guc_list = list_make4("password_encryption=on", "log_error_verbosity=verbose", "application_name=mixtest", "allow_system_table_mods=dml"); in = create_guc_array(guc_list, elems); out = GUCArrayReset(in); assert_not_null(out); assert_int_equal(ARR_DIMS(out)[0], 1); d = PointerGetDatum(ARR_DATA_PTR(out)); assert_int_equal(strlen("log_error_verbosity=verbose"), VARLEN(d)); assert_memory_equal(VARDATA(d), "log_error_verbosity=verbose", VARLEN(d)); list_free(guc_list); pfree(in); pfree(out); }
/* * Test GUCArrayReset * * superuser: return NULL */ void test__GUCArrayReset__superuser(void **state) { ArrayType *in; ArrayType *out; will_return(superuser, true); in = construct_empty_array(TEXTOID); assert_not_null(in); out = GUCArrayReset(in); assert_null(out); pfree(in); }
/* * GUC array: all non-PGC_USERSET, return the same array */ void test__GUCArrayReset__all_non_userset_guc(void **state) { ArrayType *in; ArrayType *out; Datum d; List *guc_list; bool isnull; int i; int elems; build_guc_variables(); will_return(superuser, false); /* construct text array */ elems = 3; guc_list = list_make3("log_error_verbosity=terse", "gp_log_format=csv", "maintenance_mode=true"); in = create_guc_array(guc_list, elems); out = GUCArrayReset(in); assert_not_null(out); assert_int_equal(ARR_DIMS(out)[0], elems); /* check element 1 */ i = 1; d = array_ref(out, 1, &i, -1, TEXT_TYPLEN, TEXT_TYPBYVAL, TEXT_TYPALIGN, &isnull); assert_false(isnull); assert_int_equal(strlen("log_error_verbosity=terse"), VARLEN(d)); assert_memory_equal(VARDATA(d), "log_error_verbosity=terse", VARLEN(d)); /* check element 2 */ i = 2; d = array_ref(out, 1, &i, -1, TEXT_TYPLEN, TEXT_TYPBYVAL, TEXT_TYPALIGN, &isnull); assert_false(isnull); assert_int_equal(strlen("gp_log_format=csv"), VARLEN(d)); assert_memory_equal(VARDATA(d), "gp_log_format=csv", VARLEN(d)); /* check element 3 */ i = 3; d = array_ref(out, 1, &i, -1, TEXT_TYPLEN, TEXT_TYPBYVAL, TEXT_TYPALIGN, &isnull); assert_false(isnull); assert_int_equal(strlen("maintenance_mode=true"), VARLEN(d)); assert_memory_equal(VARDATA(d), "maintenance_mode=true", VARLEN(d)); list_free(guc_list); pfree(in); pfree(out); }
/* * GUC array: all PGC_USERSET, return NULL */ void test__GUCArrayReset__all_userset_guc(void **state) { ArrayType *in; List *guc_list; int elems; build_guc_variables(); will_return(superuser, false); /* construct text array */ elems = 3; guc_list = list_make3("application_name=unittest", "password_encryption=off", "backslash_quote=off"); in = create_guc_array(guc_list, elems); assert_null(GUCArrayReset(in)); list_free(guc_list); pfree(in); }
/* * GUC array: 2-dim array * return NULL */ void test__GUCArrayReset__md_array(void **state) { ArrayType *in; List *guc_list; int elems; int ndims; build_guc_variables(); will_return(superuser, false); /* construct 2-dimension text array */ elems = 2; ndims = 2; guc_list = list_make4("gp_log_format=text", "allow_system_table_mods=ddl", "password_encryption=on", "log_error_verbosity=verbose"); in = create_md_guc_array(guc_list, elems, ndims); assert_null(GUCArrayReset(in)); list_free(guc_list); pfree(in); }
/* * NULL array input: return NULL */ void test__GUCArrayReset__NULL_array(void **state) { assert_null(GUCArrayReset(NULL)); }
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) { char *valuestr; HeapTuple tuple; Relation rel; ScanKeyData scankey[2]; SysScanDesc scan; valuestr = ExtractSetVariableArgs(setstmt); /* Get the old tuple, if any. */ rel = heap_open(DbRoleSettingRelationId, RowExclusiveLock); ScanKeyInit(&scankey[0], Anum_pg_db_role_setting_setdatabase, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(databaseid)); ScanKeyInit(&scankey[1], Anum_pg_db_role_setting_setrole, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(roleid)); scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true, NULL, 2, scankey); tuple = systable_getnext(scan); /* * There are three cases: * * - in RESET ALL, request GUC to reset the settings array and update the * catalog if there's anything left, delete it otherwise * * - in other commands, if there's a tuple in pg_db_role_setting, update * it; if it ends up empty, delete it * * - otherwise, insert a new___ pg_db_role_setting tuple, but only if the * command is not RESET */ if (setstmt->kind == VAR_RESET_ALL) { if (HeapTupleIsValid(tuple)) { ArrayType *new___ = NULL; Datum datum; bool isnull; datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig, RelationGetDescr(rel), &isnull); if (!isnull) new___ = GUCArrayReset(DatumGetArrayTypeP(datum)); if (new___) { Datum repl_val[Natts_pg_db_role_setting]; bool repl_null[Natts_pg_db_role_setting]; bool repl_repl[Natts_pg_db_role_setting]; HeapTuple newtuple; memset(repl_repl, false, sizeof(repl_repl)); repl_val[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(new___); repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl); simple_heap_update(rel, &tuple->t_self, newtuple); /* Update indexes */ CatalogUpdateIndexes(rel, newtuple); } else simple_heap_delete(rel, &tuple->t_self); } } else if (HeapTupleIsValid(tuple)) { Datum repl_val[Natts_pg_db_role_setting]; bool repl_null[Natts_pg_db_role_setting]; bool repl_repl[Natts_pg_db_role_setting]; HeapTuple newtuple; Datum datum; bool isnull; ArrayType *a; memset(repl_repl, false, sizeof(repl_repl)); repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; /* Extract old value of setconfig */ datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig, RelationGetDescr(rel), &isnull); a = isnull ? NULL : DatumGetArrayTypeP(datum); /* Update (valuestr is NULL in RESET cases) */ if (valuestr) a = GUCArrayAdd(a, setstmt->name, valuestr); else a = GUCArrayDelete(a, setstmt->name); if (a) { repl_val[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a); newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl); simple_heap_update(rel, &tuple->t_self, newtuple); /* Update indexes */ CatalogUpdateIndexes(rel, newtuple); } else simple_heap_delete(rel, &tuple->t_self); } else if (valuestr) { /* non-null valuestr means it's not RESET, so insert a new___ tuple */ HeapTuple newtuple; Datum values[Natts_pg_db_role_setting]; bool nulls[Natts_pg_db_role_setting]; ArrayType *a; memset(nulls, false, sizeof(nulls)); a = GUCArrayAdd(NULL, setstmt->name, valuestr); values[Anum_pg_db_role_setting_setdatabase - 1] = ObjectIdGetDatum(databaseid); values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid); values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a); newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); simple_heap_insert(rel, newtuple); /* Update indexes */ CatalogUpdateIndexes(rel, newtuple); } InvokeObjectPostAlterHookArg(DbRoleSettingRelationId, databaseid, 0, roleid, false); systable_endscan(scan); /* Close pg_db_role_setting, but keep lock till commit */ heap_close(rel, NoLock); }