Changeset: b12d8cb111aa for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/b12d8cb111aa Added Files: sql/test/BugTracker-2026/Tests/7700-alter-user-optimizer.test Modified Files: ChangeLog clients/Tests/MAL-signatures-hge.test clients/Tests/MAL-signatures.test sql/backends/monet5/sql.c sql/backends/monet5/sql_cat.c sql/backends/monet5/sql_user.c sql/common/sql_backend.c sql/common/sql_backend.h sql/server/rel_schema.c sql/server/rel_semantic.c sql/server/sql_parser.y sql/server/sql_privileges.c sql/server/sql_privileges.h sql/test/BugTracker-2026/Tests/All Branch: default Log Message:
Implement request #7700 Add capability to change the default OPTIMIZER for a USER via: ALTER USER user_id OPTIMIZER 'minimal_pipe'; diffs (truncated from 342 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ # ChangeLog file for devel # This file is updated with Maddlog +* Wed May 6 2026 Martin van Dinther <[email protected]> +- Added capability to change the OPTIMIZER setting for a USER via: + ALTER USER user_id OPTIMIZER 'minimal_pipe'; + * Sat May 2 2026 Lucas Pereira <[email protected]> - Set default to 'no' of monetdbd discovery property. diff --git a/clients/Tests/MAL-signatures-hge.test b/clients/Tests/MAL-signatures-hge.test --- a/clients/Tests/MAL-signatures-hge.test +++ b/clients/Tests/MAL-signatures-hge.test @@ -50890,7 +50890,7 @@ SQLalter_table Catalog operation alter_table sqlcatalog alter_user -pattern sqlcatalog.alter_user(X_0:str, X_1:str, X_2:int, X_3:str, X_4:str, X_5:str, X_6:str, X_7:lng, X_8:int):void +pattern sqlcatalog.alter_user(X_0:str, X_1:str, X_2:int, X_3:str, X_4:str, X_5:str, X_6:str, X_7:lng, X_8:int, X_9:str):void SQLalter_user Catalog operation alter_user sqlcatalog diff --git a/clients/Tests/MAL-signatures.test b/clients/Tests/MAL-signatures.test --- a/clients/Tests/MAL-signatures.test +++ b/clients/Tests/MAL-signatures.test @@ -39270,7 +39270,7 @@ SQLalter_table Catalog operation alter_table sqlcatalog alter_user -pattern sqlcatalog.alter_user(X_0:str, X_1:str, X_2:int, X_3:str, X_4:str, X_5:str, X_6:str, X_7:lng, X_8:int):void +pattern sqlcatalog.alter_user(X_0:str, X_1:str, X_2:int, X_3:str, X_4:str, X_5:str, X_6:str, X_7:lng, X_8:int, X_9:str):void SQLalter_user Catalog operation alter_user sqlcatalog diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c --- a/sql/backends/monet5/sql.c +++ b/sql/backends/monet5/sql.c @@ -6437,7 +6437,7 @@ static mel_func sql_init_funcs[] = { pattern("sqlcatalog", "create_user", SQLcreate_user, false, "Catalog operation create_user", args(0,10, arg("sname",str),arg("passwrd",str),arg("enc",int),arg("schema",str),arg("schemapath",str),arg("fullname",str), arg("max_memory", lng), arg("max_workers", int), arg("optimizer", str), arg("default_role", str))), pattern("sqlcatalog", "drop_user", SQLdrop_user, false, "Catalog operation drop_user", args(0,2, arg("sname",str),arg("action",int))), pattern("sqlcatalog", "drop_user", SQLdrop_user, false, "Catalog operation drop_user", args(0,3, arg("sname",str),arg("auth",str),arg("action",int))), - pattern("sqlcatalog", "alter_user", SQLalter_user, false, "Catalog operation alter_user", args(0,9, arg("sname",str),arg("passwrd",str),arg("enc",int),arg("schema",str),arg("schemapath",str),arg("oldpasswrd",str),arg("role",str),arg("max_memory",lng),arg("max_workers",int))), + pattern("sqlcatalog", "alter_user", SQLalter_user, false, "Catalog operation alter_user", args(0,10, arg("sname",str),arg("passwrd",str),arg("enc",int),arg("schema",str),arg("schemapath",str),arg("oldpasswrd",str),arg("role",str),arg("max_memory",lng),arg("max_workers",int),arg("optimizer",str))), pattern("sqlcatalog", "rename_user", SQLrename_user, false, "Catalog operation rename_user", args(0,3, arg("sname",str),arg("newnme",str),arg("action",int))), pattern("sqlcatalog", "create_role", SQLcreate_role, false, "Catalog operation create_role", args(0,3, arg("sname",str),arg("role",str),arg("grator",int))), pattern("sqlcatalog", "drop_role", SQLdrop_role, false, "Catalog operation drop_role", args(0,3, arg("auth",str),arg("role",str),arg("action",int))), diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c --- a/sql/backends/monet5/sql_cat.c +++ b/sql/backends/monet5/sql_cat.c @@ -1877,9 +1877,10 @@ SQLalter_user(Client cntxt, MalBlkPtr mb char *role = SaveArgReference(stk, pci, 7); lng max_memory = *getArgReference_lng(stk, pci, 8); int max_workers = *getArgReference_int(stk, pci, 9); + char *optimizer = SaveArgReference(stk, pci, 10); initcontext(); - msg = sql_alter_user(sql, sname, passwd, enc, schema, schema_path, oldpasswd, role, max_memory, max_workers); + msg = sql_alter_user(sql, sname, passwd, enc, schema, schema_path, oldpasswd, role, max_memory, max_workers, optimizer); return msg; } diff --git a/sql/backends/monet5/sql_user.c b/sql/backends/monet5/sql_user.c --- a/sql/backends/monet5/sql_user.c +++ b/sql/backends/monet5/sql_user.c @@ -303,7 +303,7 @@ monet5_create_user(ptr _mvc, str user, s if (!optimizer) optimizer = default_optimizer; if (!isOptimizerPipe(optimizer)) { - throw(MAL, "sql.create_user", SQLSTATE(42000) "Optimizer pipe %s unknown", optimizer); + throw(MAL, "sql.create_user", SQLSTATE(42000) "Optimizer pipe '%s' unknown", optimizer); } @@ -455,8 +455,8 @@ monet5_schema_has_user(ptr _mvc, sql_sch } static int -monet5_alter_user(ptr _mvc, str user, str passwd, bool enc, sqlid schema_id, str schema_path, str oldpasswd, sqlid - role_id, lng max_memory, int max_workers) +monet5_alter_user(ptr _mvc, str user, str passwd, bool enc, sqlid schema_id, str schema_path, str oldpasswd, + sqlid role_id, lng max_memory, int max_workers, str optimizer) { mvc *m = (mvc *) _mvc; Client c = MCgetClient(m->clientid); @@ -469,7 +469,7 @@ monet5_alter_user(ptr _mvc, str user, st sql_table *info = find_sql_table(m->session->tr, sys, "db_user_info"); sql_column *users_name = find_sql_column(info, "name"); - if (schema_id || schema_path || role_id || max_memory > -1 || max_workers > -1) { + if (schema_id || schema_path || role_id || max_memory > -1 || max_workers > -1 || optimizer) { rid = store->table_api.column_find_row(m->session->tr, users_name, user, NULL); // user should be checked here since the way `ALTER USER ident ...` stmt is if (is_oid_nil(rid)) { @@ -613,6 +613,21 @@ monet5_alter_user(ptr _mvc, str user, st } } + if (optimizer) { + sql_column *users_optimizer = find_sql_column(info, "optimizer"); + + if (!isOptimizerPipe(optimizer)) { + (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed. Optimizer pipe '%s' unknown", optimizer); + return FALSE; + } + + if ((res = store->table_api.column_update_value(m->session->tr, users_optimizer, rid, optimizer))) { + (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s", + res == LOG_CONFLICT ? " due to conflict with another transaction" : ""); + return FALSE; + } + } + return TRUE; } diff --git a/sql/common/sql_backend.c b/sql/common/sql_backend.c --- a/sql/common/sql_backend.c +++ b/sql/common/sql_backend.c @@ -78,10 +78,10 @@ backend_schema_has_user(ptr mvc, sql_sch int backend_alter_user(ptr mvc, str user, str passwd, bool enc, - sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers) + sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers, char *optimizer) { if (be_funcs.fauser != NULL) - return(be_funcs.fauser(mvc, user, passwd, enc, schema_id, schema_path, oldpasswd, role_id, max_memory, max_workers)); + return(be_funcs.fauser(mvc, user, passwd, enc, schema_id, schema_path, oldpasswd, role_id, max_memory, max_workers, optimizer)); return(FALSE); } diff --git a/sql/common/sql_backend.h b/sql/common/sql_backend.h --- a/sql/common/sql_backend.h +++ b/sql/common/sql_backend.h @@ -22,7 +22,7 @@ typedef int (*drop_user_fptr) (ptr mvc, typedef oid (*find_user_fptr) (ptr mvc, char *user); typedef void (*create_privileges_fptr) (ptr mvc, sql_schema *s, const char *initpasswd); typedef int (*schema_has_user_fptr) (ptr mvc, sql_schema *s); -typedef int (*alter_user_fptr) (ptr mvc, str user, str passwd, bool enc, sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers); +typedef int (*alter_user_fptr) (ptr mvc, str user, str passwd, bool enc, sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers, str optimizer); typedef int (*rename_user_fptr) (ptr mvc, str olduser, str newuser); typedef void* (*schema_user_dependencies) (ptr mvc, int schema_id); typedef void (*create_function) (ptr mvc, str name, sql_rel *rel, sql_table *t); @@ -56,7 +56,7 @@ extern int backend_drop_user(ptr mvc, c extern oid backend_find_user(ptr mp, char *user); extern void backend_create_privileges(ptr mvc, sql_schema *s, const char *initpasswd); extern int backend_schema_has_user(ptr mvc, sql_schema *s); -extern int backend_alter_user(ptr mvc, str user, str passwd, bool enc, sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers); +extern int backend_alter_user(ptr mvc, str user, str passwd, bool enc, sqlid schema_id, char *schema_path, str oldpasswd, sqlid role_id, lng max_memory, int max_workers, char *optimizer); extern int backend_rename_user(ptr mvc, str olduser, str newuser); extern void* backend_schema_user_dependencies(ptr trans, sqlid schema_id); extern int backend_resolve_function(ptr trans, sql_func *f, const char *fimp, bool *side_effect); diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c --- a/sql/server/rel_schema.c +++ b/sql/server/rel_schema.c @@ -2589,7 +2589,7 @@ rel_create_user(allocator *sa, char *use } static sql_rel * -rel_alter_user(allocator *sa, char *user, char *passwd, int enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers) +rel_alter_user(allocator *sa, char *user, char *passwd, int enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers, char *optimizer) { sql_rel *rel = rel_create(sa); list *exps = new_exp_list(sa); @@ -2605,6 +2605,7 @@ rel_alter_user(allocator *sa, char *user append(exps, exp_atom_clob(sa, role)); append(exps, exp_atom_lng(sa, max_memory)); append(exps, exp_atom_int(sa, max_workers)); + append(exps, exp_atom_clob(sa, optimizer)); rel->l = NULL; rel->r = NULL; @@ -3303,7 +3304,7 @@ rel_schemas(sql_query *query, symbol *s) dlist *l = s->data.lval; char *username = l->h->data.sval; dnode *a = l->h->next->data.lval->h; - int if_exists = l->h->next->next->next->next->next->data.i_val; + int if_exists = l->h->next->next->next->next->next->next->data.i_val; if (if_exists == 1 && username != NULL && is_oid_nil(backend_find_user(sql, username))) { /* user does not exist, but IF EXISTS is specified, so we are done */ @@ -3317,7 +3318,8 @@ rel_schemas(sql_query *query, symbol *s) a->next->next->next->next->data.sval, /* old passwd */ l->h->next->next->data.sval, /* default role */ l->h->next->next->next->data.l_val, /* max_memory */ - l->h->next->next->next->next->data.i_val /* max_workers */ + l->h->next->next->next->next->data.i_val, /* max_workers */ + l->h->next->next->next->next->next->data.sval /* optimizer */ ); } break; case SQL_RENAME_USER: { diff --git a/sql/server/rel_semantic.c b/sql/server/rel_semantic.c --- a/sql/server/rel_semantic.c +++ b/sql/server/rel_semantic.c @@ -26,7 +26,8 @@ sql_rel * rel_parse(mvc *m, sql_schema *s, const char *query, char emode) { if (mvc_highwater(m)) - return sql_error(m, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); + return sql_error(m, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); + sql_rel *rel = NULL; buffer *b; bstream *bs; diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y --- a/sql/server/sql_parser.y +++ b/sql/server/sql_parser.y @@ -1487,10 +1487,10 @@ alter_statement: append_int(l, $3); $$ = _symbol_create_list(SQL_SET_TABLE_SCHEMA, l ); } - | ALTER USER if_exists column_id opt_with_encrypted_password user_schema opt_schema_path opt_default_role opt_max_memory_max_workers + | ALTER USER if_exists column_id opt_with_encrypted_password user_schema opt_schema_path opt_default_role opt_max_memory_max_workers opt_optimizer { dlist *l = L(), *p = L(); - if (!$5 && !$6 && !$7 && !$8 && $9[0] < 0 && $9[1] < 0) { + if (!$5 && !$6 && !$7 && !$8 && $9[0] < 0 && $9[1] < 0 && !$10) { yyerror(m, "ALTER USER: At least one property should be updated"); YYABORT; } @@ -1504,6 +1504,7 @@ alter_statement: append_string(l, $8); append_lng(l, $9[0]); append_int(l, (int)$9[1]); + append_string(l, $10); append_int(l, $3); $$ = _symbol_create_list( SQL_ALTER_USER, l ); } @@ -1529,6 +1530,7 @@ alter_statement: append_string(l, NULL); append_lng(l, -1); append_int(l, -1); + append_string(l, NULL); append_int(l, FALSE); $$ = _symbol_create_list( SQL_ALTER_USER, l ); } @@ -3739,7 +3741,7 @@ assignment: opt_assignment_commalist: '(' assignment_commalist ')' { $$ = $2; } - | /* empty */ { $$ = NULL; } + | /* empty */ { $$ = NULL; } ; opt_where_clause: diff --git a/sql/server/sql_privileges.c b/sql/server/sql_privileges.c --- a/sql/server/sql_privileges.c +++ b/sql/server/sql_privileges.c @@ -1015,7 +1015,7 @@ sql_drop_user(mvc *sql, char *user) } char * -sql_alter_user(mvc *sql, char *user, char *passwd, bool enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers) +sql_alter_user(mvc *sql, char *user, char *passwd, bool enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers, char *optimizer) { sql_schema *s = NULL; sqlid schema_id = 0; @@ -1048,7 +1048,7 @@ sql_alter_user(mvc *sql, char *user, cha if (!isNew(s) && sql_trans_add_dependency(sql->session->tr, s->base.id, ddl) != LOG_OK) throw(SQL, "sql.alter_user", SQLSTATE(HY013) MAL_MALLOC_FAIL); } - if (backend_alter_user(sql, user, passwd, enc, schema_id, schema_path, oldpasswd, role_id, max_memory, max_workers) == FALSE) + if (backend_alter_user(sql, user, passwd, enc, schema_id, schema_path, oldpasswd, role_id, max_memory, max_workers, optimizer) == FALSE) throw(SQL,"sql.alter_user", SQLSTATE(M0M27) "%s", sql->errstr); /* the default role must explicitly granted to the new user */ diff --git a/sql/server/sql_privileges.h b/sql/server/sql_privileges.h --- a/sql/server/sql_privileges.h +++ b/sql/server/sql_privileges.h @@ -45,7 +45,7 @@ extern int sql_schema_has_user(mvc *m, s extern char * sql_create_user(mvc *sql, char *user, char *passwd, bool enc, char *fullname, char *schema, char *schema_path, lng max_memory, int max_workers, char *optimizer, char *default_role); extern char * sql_drop_user(mvc *sql, char *user); -extern char * sql_alter_user(mvc *sql, char *user, char *passwd, bool enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers); +extern char * sql_alter_user(mvc *sql, char *user, char *passwd, bool enc, char *schema, char *schema_path, char *oldpasswd, char *role, lng max_memory, int max_workers, char *optimizer); extern char * sql_rename_user(mvc *sql, char *olduser, char *newuser); #endif /*_SQL_PRIV_H_ */ diff --git a/sql/test/BugTracker-2026/Tests/7700-alter-user-optimizer.test b/sql/test/BugTracker-2026/Tests/7700-alter-user-optimizer.test new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2026/Tests/7700-alter-user-optimizer.test @@ -0,0 +1,47 @@ +statement ok +CREATE USER test WITH PASSWORD 'me' NAME 'tester' OPTIMIZER 'default_pipe' + +query TT nosort +SELECT name, optimizer FROM sys.users WHERE name = 'test' +---- +test +default_pipe + +statement ok +ALTER USER test OPTIMIZER 'minimal_pipe' + +query TT nosort _______________________________________________ checkin-list mailing list -- [email protected] To unsubscribe send an email to [email protected]
