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

Reply via email to