Changeset: 6eeef613902a for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6eeef613902a Modified Files: sql/backends/monet5/sql_upgrades.c sql/scripts/97_comments.sql sql/server/rel_schema.c sql/test/Tests/comment-auth.stable.err sql/test/Tests/comment-auth.stable.out Branch: Mar2018 Log Message:
Fix COMMENT ON authorization The sys.comments table is now updated using table_funcs calls instead of making a call to the SQL function sys.comment_on(). However, the function must still return a non-NULL sql_rel so we CALL the newly created sys.no_op(). This is horrendously ugly but at least it makes the tests pass. diffs (175 lines): diff --git a/sql/backends/monet5/sql_upgrades.c b/sql/backends/monet5/sql_upgrades.c --- a/sql/backends/monet5/sql_upgrades.c +++ b/sql/backends/monet5/sql_upgrades.c @@ -1410,17 +1410,9 @@ sql_update_mar2018(Client c, mvc *sql) " remark VARCHAR(65000) NOT NULL\n" ");\n" "GRANT SELECT ON sys.comments TO PUBLIC;\n" - "CREATE PROCEDURE sys.comment_on(obj_id INTEGER, obj_remark VARCHAR(65000))\n" + "CREATE PROCEDURE sys.no_op()\n" "BEGIN\n" - " IF obj_id IS NOT NULL AND obj_id > 0 THEN\n" - " IF obj_remark IS NULL OR obj_remark = '' THEN\n" - " DELETE FROM sys.comments WHERE id = obj_id;\n" - " ELSEIF EXISTS (SELECT id FROM sys.comments WHERE id = obj_id) THEN\n" - " UPDATE sys.comments SET remark = obj_remark WHERE id = obj_id;\n" - " ELSE\n" - " INSERT INTO sys.comments VALUES (obj_id, obj_remark);\n" - " END IF;\n" - " END IF;\n" + " DECLARE dummy INTEGER;\n" "END;\n" "CREATE FUNCTION sys.function_type_keyword(ftype INT)\n" "RETURNS VARCHAR(20)\n" diff --git a/sql/scripts/97_comments.sql b/sql/scripts/97_comments.sql --- a/sql/scripts/97_comments.sql +++ b/sql/scripts/97_comments.sql @@ -11,17 +11,9 @@ CREATE TABLE sys.comments ( GRANT SELECT ON sys.comments TO PUBLIC; -CREATE PROCEDURE sys.comment_on(obj_id INTEGER, obj_remark VARCHAR(65000)) +CREATE PROCEDURE sys.no_op() BEGIN - IF obj_id IS NOT NULL AND obj_id > 0 THEN - IF obj_remark IS NULL OR obj_remark = '' THEN - DELETE FROM sys.comments WHERE id = obj_id; - ELSEIF EXISTS (SELECT id FROM sys.comments WHERE id = obj_id) THEN - UPDATE sys.comments SET remark = obj_remark WHERE id = obj_id; - ELSE - INSERT INTO sys.comments VALUES (obj_id, obj_remark); - END IF; - END IF; + DECLARE dummy INTEGER; END; -- do not grant to public 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 @@ -2228,48 +2228,47 @@ rel_find_designated_object(mvc *sql, sym static sql_rel * rel_comment_on(mvc *sql, sqlid obj_id, sql_schema *schema, char *remark) { - buffer *buf = NULL; - stream *s = NULL; - char *query = NULL; + sql_trans *tx; sql_schema *sys; - sql_rel *rel = NULL; + sql_table *comments; + sql_column *id_col, *remark_col; + oid rid; // Check authorization if (!mvc_schema_privs(sql, schema)) { return sql_error(sql, 02, SQLSTATE(42000) "COMMENT ON: insufficient privileges for user '%s' in schema '%s'", stack_get_string(sql, "current_user"), schema->base.name); } - buf = buffer_create(4000); - if (!buf) - goto wrap_up; - - s = buffer_wastream(buf, "comment_on_call"); - if (!s) - goto wrap_up; - - mnstr_printf(s, "CALL sys.comment_on(%d, ", obj_id); - if (!remark) { - mnstr_printf(s, "NULL"); + // Manually insert the rows to circumvent permission checks. + tx = sql->session->tr; + sys = find_sql_schema(tx, "sys"); + if (!sys) + return NULL; + comments = find_sql_table(sys, "comments"); + if (!comments) + return NULL; + id_col = find_sql_column(comments, "id"); + remark_col = find_sql_column(comments, "remark"); + if (!id_col || !remark_col) + return NULL; + rid = table_funcs.column_find_row(tx, id_col, &obj_id, NULL); + if (remark != NULL && *remark) { + if (rid != oid_nil) { + // have new remark and found old one, so update field + table_funcs.column_update_value(tx, remark_col, rid, remark); + } else { + // have new remark but found none so insert row + table_funcs.table_insert(tx, comments, &obj_id, remark); + } } else { - char *escaped = sql_escape_str(remark); - if (!escaped) - goto wrap_up; - mnstr_printf(s, "'%s'", escaped); - GDKfree(escaped); + if (rid != oid_nil) { + // have no remark but found one, so delete row + table_funcs.table_delete(tx, comments, rid); + } } - mnstr_printf(s, ");"); - query = buffer_get_buf(buf); - sys = mvc_bind_schema(sql, "sys"); - rel = rel_parse(sql, sys, query, m_normal); // correct mode? -wrap_up: - if (query) - free(query); - if (s) - mnstr_destroy(s); - if (buf) - buffer_destroy(buf); - return rel; + // There must be a better way to return a no-op sql_rel* + return rel_parse(sql, sys, "CALL sys.no_op();", m_normal); } sql_rel * diff --git a/sql/test/Tests/comment-auth.stable.err b/sql/test/Tests/comment-auth.stable.err --- a/sql/test/Tests/comment-auth.stable.err +++ b/sql/test/Tests/comment-auth.stable.err @@ -44,12 +44,8 @@ MAPI = (user_a) /var/tmp/mtest-36372/.s QUERY = COMMENT ON SCHEMA schema_b IS 'set by user_a'; ERROR = !COMMENT ON: insufficient privileges for user 'user_a' in schema 'schema_b' CODE = 42000 -MAPI = (user_a) /var/tmp/mtest-89089/.s.monetdb.33054 -QUERY = COMMENT ON SCHEMA schema_a IS 'set by user_a'; - -CODE = 42000 -# 14:17:02 > -# 14:17:02 > "Done." -# 14:17:02 > +# 16:46:51 > +# 16:46:51 > "Done." +# 16:46:51 > diff --git a/sql/test/Tests/comment-auth.stable.out b/sql/test/Tests/comment-auth.stable.out --- a/sql/test/Tests/comment-auth.stable.out +++ b/sql/test/Tests/comment-auth.stable.out @@ -76,16 +76,16 @@ Ready. #CREATE TABLE schema_a.tab_a(i INTEGER); #CREATE TABLE schema_b.tab_b(i INTEGER); -# 14:17:02 > -# 14:17:02 > Mtimeout -timeout 60 mclient -lsql -ftest -tnone -Eutf-8 -i -e --host=/var/tmp/mtest-36372 --port=31868 --database=mTests_sql_test < "/Users/joeri/extr/monet/MonetDB/sql/test/Tests/comment-auth-a.sql" -# 14:17:02 > +# 16:48:25 > +# 16:48:25 > Mtimeout -timeout 60 mclient -lsql -ftest -tnone -Eutf-8 -i -e --host=/var/tmp/mtest-70396 --port=35195 --database=mTests_sql_test < "/Users/joeri/extr/monet/MonetDB/sql/test/Tests/comment-auth-a.sql" +# 16:48:25 > SCHEMA schema_a 'set by super user' SCHEMA schema_b 'set by super user' -SCHEMA schema_a 'set by super user' +SCHEMA schema_a 'set by user_a' SCHEMA schema_b 'set by super user' -# 14:17:02 > -# 14:17:02 > "Done." -# 14:17:02 > +# 16:48:25 > +# 16:48:25 > "Done." +# 16:48:25 > _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list