<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi! Thankyou for review!<br class=""><br class="">Please see my answers regarding extra code in grant/revoke and object_resolve<br class="">functions below.<br class="">The new diff is also below.<br class=""><br class=""><blockquote type="cite" class="">7 авг. 2018 г., в 19:38, Vladimir Davydov <<a href="mailto:vdavydov.dev@gmail.com" class="">vdavydov.dev@gmail.com</a>> написал(а):<br class=""><br class="">On Thu, Aug 02, 2018 at 01:55:58PM +0300, Serge Petrenko wrote:<br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">When granting or revoking a privilege on an entire entity, id 0 was used<br class="">to indicate the fact that we don't grant a privilege on a single object,<br class="">but on a whole entity. This caused confusion, because for entity USER,<br class="">for example, id 0 is a valid object id (user 'guest' uses it).<br class="">Any non-zero id dedicated to this cause obviously may be confused as well.<br class="">Fix this by creating separate schema_object_types for entities:<br class="">SC_ENTITY_SPACE, SC_ENTITY_USER, etc.<br class=""><br class="">Closes: #3574<br class="">Prerequisite: #3524<br class="">---<br class=""><a href="https://github.com/tarantool/tarantool/tree/sergepetrenko/gh-3574-whole-entity-types" class="">https://github.com/tarantool/tarantool/tree/sergepetrenko/gh-3574-whole-entity-types</a><br class="">https://github.com/tarantool/tarantool/issues/3574<br class=""><br class="">Changes in v2: <br class=""> - keep only old syntax for granting access<br class="">   to all entities<br class=""> - add an upgrade script to alter indices of spaces<br class="">   _priv and _vpriv to store 'scalar' in object_id field,<br class="">   and use an asterisk ('*') in object_id to indicate<br class="">   granting on an entire entity.<br class=""></blockquote><br class="">Hmm, I wonder what happens if someone creates an object (say space) and<br class="">names it "*» …<br class=""></blockquote>It is ok, when operating with a space named ‘*’, ‘*’ is in object_name, when operating<br class="">on a whole entity, ‘*’ is set internally in object_id field. So there are no conflicts here.<br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""> - keep the new entity types in priv_def and use them<br class="">   internally.<br class=""><br class="">src/box/<a href="http://alter.cc" class="">alter.cc</a>             |  27 ++++++++++++++++++++++++++-<br class="">src/box/bootstrap.snap       | Bin 1540 -> 1557 bytes<br class="">src/box/lua/schema.lua       |  41 ++++++++++++++++++++++++-----------------<br class="">src/box/lua/upgrade.lua      |  37 +++++++++++++++++++++++++++++++++++++<br class="">src/box/<a href="http://schema.cc" class="">schema.cc</a>            |  18 ++++++++++++++++++<br class="">src/box/schema.h             |  23 +++++++++++++----------<br class="">src/box/schema_def.c         |  39 +++++++++++++++++++++++++++++++--------<br class="">src/box/schema_def.h         |  28 ++++++++++++++++++++++------<br class="">src/box/<a href="http://user.cc" class="">user.cc</a>              |  27 +++++++++++++++------------<br class="">test/box-py/bootstrap.result |  14 +++++++-------<br class="">test/box/access.result       |   6 +++---<br class="">test/box/access_misc.result  |   8 ++++----<br class="">test/box/alter.result        |   8 ++++----<br class="">test/xlog/upgrade.result     |  14 +++++++-------<br class="">14 files changed, 211 insertions(+), 79 deletions(-)<br class=""><br class="">diff --git a/src/box/<a href="http://alter.cc" class="">alter.cc</a> b/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">index 3007a131d..6057b66c9 100644<br class="">--- a/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">+++ b/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">@@ -2529,6 +2529,31 @@ on_replace_dd_collation(struct trigger * /* trigger */, void *event)<br class=""><span class="Apple-tab-span" style="white-space:pre">  </span>}<br class="">}<br class=""><br class="">+void<br class="">+priv_def_try_fill(struct priv_def *priv, struct tuple *tuple)<br class=""></blockquote><br class="">This function should be static. Anyway, I don't think it's worth<br class="">factoring this code out, because it's pretty straightforward and<br class="">executed only in priv_def_create_form_tuple().<br class=""><br class=""></blockquote>I removed the function.<br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+{<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>const char *object_id = tuple_field(tuple, BOX_PRIV_FIELD_OBJECT_ID);<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>if (object_id == NULL) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>tnt_raise(ClientError, ER_NO_SUCH_FIELD,<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>  BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE);<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>}<br class=""></blockquote><br class="">Please use tuple_field_u32() and tuple_field_str() instead.<br class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>/*<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span> * When granting or revoking privileges on a whole entity we<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span> * pass an asterisk ('*') to object_id to indicate grant on every<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span> * object of that entity. So check for that first.<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span> */<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>if (mp_typeof(*object_id) == MP_STR) {<br class=""></blockquote><br class="">Shouldn't you check that the string is actually "*»?<br class=""></blockquote><br class="">Added a check<br class=""><br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>priv->object_id = 0;<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span>priv->object_type = schema_entity_type(priv->object_type);<br class=""></blockquote><br class="">This assumes that priv->object_type is initialized before<br class="">priv_def_try_fill(). IMO this makes the function protocol<br class="">rather abstruse. Another reason not to factor it out.<br class=""><br class=""></blockquote><br class="">Done.<br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>} else if (mp_typeof(*object_id) == MP_UINT) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span>priv->object_id = mp_decode_uint(&object_id);<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>} else {<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>tnt_raise(ClientError, ER_FIELD_TYPE,<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>  BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE,<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>  field_type_strs[FIELD_TYPE_UNSIGNED]);<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>}<br class="">+}<br class="">+<br class="">/**<br class=""> * Create a privilege definition from tuple.<br class=""> */<br class="">@@ -2539,8 +2564,8 @@ priv_def_create_from_tuple(struct priv_def *priv, struct tuple *tuple)<br class=""><span class="Apple-tab-span" style="white-space:pre">     </span>priv->grantee_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_UID);<br class=""><span class="Apple-tab-span" style="white-space:pre">   </span>const char *object_type =<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_TYPE);<br class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>priv->object_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span>priv->object_type = schema_object_type(object_type);<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>priv_def_try_fill(priv, tuple);<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>if (priv->object_type == SC_UNKNOWN) {<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>tnt_raise(ClientError, ER_UNKNOWN_SCHEMA_OBJECT,<br class=""><span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>  object_type);<br class="">diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua<br class="">index b9b8c9004..294dcf4d3 100644<br class="">--- a/src/box/lua/schema.lua<br class="">+++ b/src/box/lua/schema.lua<br class="">@@ -1809,9 +1809,9 @@ local function object_resolve(object_type, object_name)<br class="">        return 0<br class="">    end<br class="">    if object_type == 'space' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">-        end<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>if object_name == nil then<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>    return '*'<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>end<br class=""></blockquote><br class="">Bad indentation - we use spaces in Lua code, not tabs.<br class=""><br class=""></blockquote><br class="">Fixed.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">        local space = box.space[object_name]<br class="">        if  space == nil then<br class="">            box.error(box.error.NO_SUCH_SPACE, object_name)<br class="">@@ -1819,9 +1819,9 @@ local function object_resolve(object_type, object_name)<br class="">        return <a href="http://space.id" class="">space.id</a><br class="">    end<br class="">    if object_type == 'function' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">-        end<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>if object_name == nil then<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>    return '*'<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>end<br class=""></blockquote><br class="">Ditto<br class=""></blockquote><br class="">Fixed<br class=""><br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">        local _vfunc = box.space[box.schema.VFUNC_ID]<br class="">        local func<br class="">        if type(object_name) == 'string' then<br class="">@@ -1836,8 +1836,8 @@ local function object_resolve(object_type, object_name)<br class="">        end<br class="">    end<br class="">    if object_type == 'sequence' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">+        if object_name == nil then<br class="">+            return '*'<br class="">        end<br class="">        local seq = sequence_resolve(object_name)<br class="">        if seq == nil then<br class="">@@ -1846,6 +1846,9 @@ local function object_resolve(object_type, object_name)<br class="">        return seq<br class="">    end<br class="">    if object_type == 'role' then<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>if object_name == nil then<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>    return '*'<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>end<br class=""></blockquote><br class="">Ditto.<br class=""><br class=""></blockquote><br class="">Fixed<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">        local _vuser = box.space[box.schema.VUSER_ID]<br class="">        local role<br class="">        if type(object_name) == 'string' then<br class="">@@ -1867,6 +1870,9 @@ local function object_name(object_type, object_id)<br class="">    if object_type == 'universe' then<br class="">        return ""<br class="">    end<br class="">+    if object_id == '*' then<br class="">+        return '*'<br class="">+    end<br class="">    local space<br class="">    if object_type == 'space' then<br class="">        space = box.space._vspace<br class="">@@ -2079,9 +2085,8 @@ local function grant(uid, name, privilege, object_type,<br class="">        object_name = privilege<br class="">        privilege = 'execute'<br class="">    end<br class="">-    local privilege_hex = privilege_check(privilege, object_type)<br class="">-<br class="">    local oid = object_resolve(object_type, object_name)<br class="">+    local privilege_hex = privilege_check(privilege, object_type)<br class=""></blockquote><br class="">I don't understand why you need this.<br class=""></blockquote><br class="">Removed, no need to do this.<br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">    options = options or {}<br class="">    if options.grantor == nil then<br class="">        options.grantor = session.euid()<br class="">@@ -2106,10 +2111,10 @@ local function grant(uid, name, privilege, object_type,<br class="">        _priv:replace{options.grantor, uid, object_type, oid, privilege_hex}<br class="">    elseif not options.if_not_exists then<br class="">            if object_type == 'role' then<br class="">-                box.error(box.error.ROLE_GRANTED, name, object_name)<br class="">+                box.error(box.error.ROLE_GRANTED, name, object_name or '*')<br class="">            else<br class="">                box.error(box.error.PRIV_GRANTED, name, privilege,<br class="">-                          object_type, object_name)<br class="">+                          object_type, object_name or '*')<br class=""></blockquote><br class="">Instead you could set object_name to '*' in the beginning of<br class="">grant/revoke functions. This would make your patch shorter,<br class="">because you wouldn't have to do it here, nor in object_resolve.<br class=""><br class=""></blockquote><br class="">If I set object_name to ‘*’ the case of granting to an entity as a whole will<br class="">Be indistinguishable from granting to an object named ‘*’. So I have to handle<br class="">This case like I did. I changed the code in object_resolve a little bit to save some<br class="">Extra lines.<br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">            end<br class="">    end<br class="">end<br class="">@@ -2122,9 +2127,9 @@ local function revoke(uid, name, privilege, object_type, object_name, options)<br class="">        object_name = privilege<br class="">        privilege = 'execute'<br class="">    end<br class="">-    local privilege_hex = privilege_check(privilege, object_type)<br class="">    options = options or {}<br class="">    local oid = object_resolve(object_type, object_name)<br class="">+    local privilege_hex = privilege_check(privilege, object_type)<br class=""></blockquote><br class="">I don't understand why you need this.<br class=""></blockquote><br class="">Removed.<br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">    local _priv = box.space[box.schema.PRIV_ID]<br class="">    local _vpriv = box.space[box.schema.VPRIV_ID]<br class="">    local tuple = _vpriv:get{uid, object_type, oid}<br class="">@@ -2134,10 +2139,10 @@ local function revoke(uid, name, privilege, object_type, object_name, options)<br class="">            return<br class="">        end<br class="">        if object_type == 'role' then<br class="">-            box.error(box.error.ROLE_NOT_GRANTED, name, object_name)<br class="">+            box.error(box.error.ROLE_NOT_GRANTED, name, object_name or '*')<br class="">        else<br class="">            box.error(box.error.PRIV_NOT_GRANTED, name, privilege,<br class="">-                      object_type, object_name)<br class="">+                      object_type, object_name or '*')<br class="">        end<br class="">    end<br class="">    local old_privilege = tuple[5]<br class="">@@ -2153,13 +2158,14 @@ local function revoke(uid, name, privilege, object_type, object_name, options)<br class="">            return<br class="">        end<br class="">        box.error(box.error.PRIV_NOT_GRANTED, name, privilege,<br class="">-                  object_type, object_name)<br class="">+                  object_type, object_name or '*')<br class=""></blockquote><br class="">This hunk as well as the one above wouldn't be needed if you set<br class="">object_name to '*' in the beginning of the function (also, see my<br class="">comment to grant function).<br class=""></blockquote><br class="">Answered above.<br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">    end<br class="">    if privilege_hex ~= 0 then<br class="">        _priv:replace{grantor, uid, object_type, oid, privilege_hex}<br class="">    else<br class="">        _priv:delete{uid, object_type, oid}<br class="">    end<br class="">+<br class=""></blockquote><br class="">Extraneous change. Please remove.<br class=""></blockquote><br class="">Done<br class=""><br class=""><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">end<br class=""><br class="">local function drop(uid, opts)<br class="">@@ -2194,7 +2200,8 @@ local function drop(uid, opts)<br class="">    for k, tuple in pairs(privs) do<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span>-- we need an additional box.session.su() here, because of<br class=""><span class="Apple-tab-span" style="white-space:pre">     </span>-- unnecessary check for privilege PRIV_REVOKE in priv_def_check()<br class="">-        box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], tuple[4])<br class="">+        local oid = tuple[4] ~= '*' and tuple[4] or nil<br class="">+        box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], oid)<br class=""></blockquote><br class="">Why? The 'revoke' function should be able to interpret '*' correctly.<br class=""><br class=""></blockquote><br class="">No, answered above.<br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">    end<br class="">    box.space[box.schema.USER_ID]:delete{uid}<br class="">end<br class="">diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua<br class="">index 0293f6ef8..4acf20152 100644<br class="">--- a/src/box/lua/upgrade.lua<br class="">+++ b/src/box/lua/upgrade.lua<br class="">@@ -964,6 +964,42 @@ local function upgrade_to_1_10_0()<br class="">    create_vsequence_space()<br class="">end<br class=""><br class="">+--------------------------------------------------------------------------------<br class="">+--- Tarantool 1.10.1<br class="">+--------------------------------------------------------------------------------<br class="">+local function upgrade_space_priv_to_1_10_1()<br class="">+    local _priv = box.space._priv<br class="">+    local _vpriv = box.space._vpriv<br class="">+    local f = _priv:format()<br class="">+<br class="">+    f[4].type = 'scalar'<br class="">+    _priv:format(f)<br class="">+    f = _vpriv:format()<br class="">+    f[4].type = 'scalar'<br class="">+    _vpriv:format(f)<br class="">+    _priv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}<br class="">+    _vpriv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}<br class="">+    _priv.index.object:alter{parts={3, 'string', 4, 'scalar'}}<br class="">+    _vpriv.index.object:alter{parts={3, 'string', 4, 'scalar'}}<br class="">+end<br class="">+<br class="">+local function upgrade_privs_to_1_10_1()<br class=""></blockquote><br class="">No need to split this code in two functions.<br class=""></blockquote><blockquote type="cite" class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+    local _priv = box.space._priv<br class="">+<br class="">+    for _, priv in _priv:pairs() do<br class=""></blockquote><br class="">AFAICS interpretation of '0' as 'all objects of a kind' was added after<br class="">1.10.1 i.e. there was no Tarantool release that would use this feature.<br class="">So I guess you don't need to upgrade existing privileges, neither do you<br class="">need to preserve any code that handles '0' object id. Please consult<br class="">with Georgy and Kostja regarding this.<br class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+        if priv[4] == 0 then<br class="">+            if priv[3] ~= 'universe' and priv[3] ~= 'user' and priv[3] ~= 'role' then<br class=""></blockquote><br class="">Please rewrite it as<br class=""><br class=""> if priv[4] == 0 and priv[3] ~= 'universe' and ... then<br class=""><br class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+                _priv:delete{priv[2], priv[3], priv[4]}<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>_priv:insert{priv[1], priv[2], priv[3], '*', priv[5]}<br class=""></blockquote><br class="">Bad indentation - we use spaces in Lua code, not tabs.<br class=""><br class=""></blockquote><br class="">Removed the privilege upgrade function together with some leftover code handling <br class="">Id 0.<br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">+            end<br class="">+        end<br class="">+    end<br class="">+end<br class="">+<br class="">+local function upgrade_to_1_10_1()<br class="">+    upgrade_space_priv_to_1_10_1()<br class="">+    upgrade_privs_to_1_10_1()<br class="">+end<br class=""><br class="">local function get_version()<br class="">    local version = box.space._schema:get{'version'}<br class="">@@ -991,6 +1027,7 @@ local function upgrade(options)<br class="">        {version = mkversion(1, 7, 6), func = upgrade_to_1_7_6, auto = false},<br class="">        {version = mkversion(1, 7, 7), func = upgrade_to_1_7_7, auto = true},<br class="">        {version = mkversion(1, 10, 0), func = upgrade_to_1_10_0, auto = true},<br class="">+        {version = mkversion(1, 10, 1), func = upgrade_to_1_10_1, auto = true},<br class="">    }<br class=""><br class="">    for _, handler in ipairs(handlers) do<br class="">diff --git a/src/box/<a href="http://schema.cc" class="">schema.cc</a> b/src/box/schema.cc<br class="">index 433f52c08..02f55aaad 100644<br class="">--- a/src/box/schema.cc<br class="">+++ b/src/box/schema.cc<br class="">@@ -536,8 +536,26 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)<br class=""><span class="Apple-tab-span" style="white-space:pre">    </span>switch (type) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>case SC_UNIVERSE:<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "SPACE";<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "FUNCTION";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "SEQUENCE";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_ROLE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "ROLE";<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>case SC_ENTITY_USER:<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "USER";<br class=""></blockquote><br class="">Shouldn't it be "*»?<br class=""></blockquote>It should, indeed. Fixed.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span class="Apple-tab-span" style="white-space:pre">      </span>case SC_SPACE:<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>{<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>/*<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * Even though we have a separate type<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * for grants on entire entity, we have to<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * leave the check for an empty object_id in place,<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * because without it recover from an old version WAL <br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * fails even before the upgrade script is being run.<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> * Same applies to SC_FUNCTION and SC_SEQUENCE below.<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span> */<br class=""><span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>if (object_id == 0)<br class=""><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>return "SPACE";<br class=""><span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>struct space *space = space_by_id(object_id);<br class="">diff --git a/src/box/schema.h b/src/box/schema.h<br class="">index 0822262d0..f1735ff34 100644<br class="">--- a/src/box/schema.h<br class="">+++ b/src/box/schema.h<br class="">@@ -250,16 +250,19 @@ static inline<br class="">struct access *<br class="">entity_access_get(enum schema_object_type type)<br class="">{<br class="">-       switch (type) {<br class="">-       case SC_SPACE:<br class="">-               return entity_access.space;<br class="">-       case SC_FUNCTION:<br class="">-               return entity_access.function;<br class="">-       case SC_SEQUENCE:<br class="">-               return entity_access.sequence;<br class="">-       default:<br class="">-               return NULL;<br class="">-       }<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>switch (type) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>case SC_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_ENTITY_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>return entity_access.space;<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span>case SC_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return entity_access.function;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return entity_access.sequence;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>default:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>return NULL;<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>}<br class="">}<br class=""><br class="">#endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */<br class="">diff --git a/src/box/schema_def.c b/src/box/schema_def.c<br class="">index 97c074ab2..51d418e42 100644<br class="">--- a/src/box/schema_def.c<br class="">+++ b/src/box/schema_def.c<br class="">@@ -31,16 +31,39 @@<br class="">#include "schema_def.h"<br class=""><br class="">static const char *object_type_strs[] = {<br class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>/* [SC_UKNNOWN]         = */ "unknown",<br class="">-<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_UNIVERSE]        = */ "universe",<br class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_SPACE]           = */ "space",<br class="">-<span class="Apple-tab-span" style="white-space:pre">      </span>/* [SC_FUNCTION]        = */ "function",<br class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_USER]            = */ "user",<br class="">-<span class="Apple-tab-span" style="white-space:pre">  </span>/* [SC_ROLE]            = */ "role",<br class="">-<span class="Apple-tab-span" style="white-space:pre">  </span>/* [SC_SEQUENCE]        = */ "sequence",<br class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_COLLATION]       = */ "collation",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_UKNNOWN]<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "unknown",<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>/* [SC_UNIVERSE]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "universe",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_SPACE]<span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "space",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_ENTITY_SPACE]<span class="Apple-tab-span" style="white-space:pre">        </span>    = */ "all spaces",<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>/* [SC_FUNCTION]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "function",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_ENTITY_FUNCTION]<span class="Apple-tab-span" style="white-space:pre">     </span>    = */ "all functions",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_USER]<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "user",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ENTITY_USER]<span class="Apple-tab-span" style="white-space:pre"> </span>    = */ "all users",<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_ROLE]<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "role",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ENTITY_ROLE]<span class="Apple-tab-span" style="white-space:pre"> </span>    = */ "all roles",<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_SEQUENCE]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "sequence",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_ENTITY_SEQUENCE]<span class="Apple-tab-span" style="white-space:pre">     </span>    = */ "all sequences",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_COLLATION]<span class="Apple-tab-span" style="white-space:pre">   </span>    = */ "collation",<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_ENTITY_COLLATION]    = */ "all collations",<br class=""></blockquote><br class="">Why? I don't think that you need to report "all spaces" anywhere.<br class=""></blockquote><br class="">fixed.<br class=""><br class="">Here’s the new diff:<br class=""><br class=""> src/box/<a href="http://alter.cc" class="">alter.cc</a>             |  33 ++++++++++++++++++++++++++++++++-<br class=""> src/box/bootstrap.snap       | Bin 1540 -> 1557 bytes<br class=""> src/box/lua/schema.lua       |  43 ++++++++++++++++++++++---------------------<br class=""> src/box/lua/upgrade.lua      |  23 +++++++++++++++++++++++<br class=""> src/box/<a href="http://schema.cc" class="">schema.cc</a>            |  16 ++++++++++------<br class=""> src/box/schema.h             |  23 +++++++++++++----------<br class=""> src/box/schema_def.c         |  39 +++++++++++++++++++++++++++++++--------<br class=""> src/box/schema_def.h         |  28 ++++++++++++++++++++++------<br class=""> src/box/<a href="http://user.cc" class="">user.cc</a>              |  27 +++++++++++++++------------<br class=""> test/box-py/bootstrap.result |  14 +++++++-------<br class=""> test/box/access.result       |   6 +++---<br class=""> test/box/access_misc.result  |   8 ++++----<br class=""> test/box/alter.result        |   8 ++++----<br class=""> test/xlog/upgrade.result     |  14 +++++++-------<br class=""> 14 files changed, 193 insertions(+), 89 deletions(-)<br class=""><br class="">diff --git a/src/box/<a href="http://alter.cc" class="">alter.cc</a> b/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">index 3007a131d..7d65cab3a 100644<br class="">--- a/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">+++ b/src/box/<a href="http://alter.cc" class="">alter.cc</a><br class="">@@ -2537,10 +2537,41 @@ priv_def_create_from_tuple(struct priv_def *priv, struct tuple *tuple)<br class=""> {<br class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>priv->grantor_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_ID);<br class=""> <span class="Apple-tab-span" style="white-space:pre">      </span>priv->grantee_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_UID);<br class="">+<br class=""> <span class="Apple-tab-span" style="white-space:pre">       </span>const char *object_type =<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_TYPE);<br class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>priv->object_id = tuple_field_u32_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>priv->object_type = schema_object_type(object_type);<br class="">+<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>const char *object_id = tuple_field(tuple, BOX_PRIV_FIELD_OBJECT_ID);<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>if (object_id == NULL) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>    tnt_raise(ClientError, ER_NO_SUCH_FIELD,<br class="">+<span class="Apple-tab-span" style="white-space:pre">           </span>      BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE);<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>}<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/*<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span> * When granting or revoking privileges on a whole entity<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span> * we pass an asterisk ('*') to object_id to indicate<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span> * grant on every object of that entity.<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span> * So check for that first.<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span> */<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>if (mp_typeof(*object_id) == MP_STR) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">                </span>object_id = tuple_field_cstr_xc(tuple, BOX_PRIV_FIELD_OBJECT_ID);<br class="">+<span class="Apple-tab-span" style="white-space:pre">             </span>if(*object_id == '*' && strlen(object_id) == 1) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">                     </span>priv->object_id = 0;<br class="">+<span class="Apple-tab-span" style="white-space:pre">                       </span>priv->object_type = schema_entity_type(priv->object_type);<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>} else {<br class="">+<span class="Apple-tab-span" style="white-space:pre">                      </span>tnt_raise(ClientError, ER_FIELD_TYPE,<br class="">+<span class="Apple-tab-span" style="white-space:pre">                         </span>  BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE,<br class="">+<span class="Apple-tab-span" style="white-space:pre">                              </span>  field_type_strs[FIELD_TYPE_UNSIGNED]);<br class="">+<span class="Apple-tab-span" style="white-space:pre">            </span>}<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>} else if (mp_typeof(*object_id) == MP_UINT) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">                </span>priv->object_id = tuple_field_u32_xc(tuple,<br class="">+<span class="Apple-tab-span" style="white-space:pre">                                                </span>     BOX_PRIV_FIELD_OBJECT_ID);<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span>} else {<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>tnt_raise(ClientError, ER_FIELD_TYPE,<br class="">+<span class="Apple-tab-span" style="white-space:pre">                 </span>  BOX_PRIV_FIELD_OBJECT_ID + TUPLE_INDEX_BASE,<br class="">+<span class="Apple-tab-span" style="white-space:pre">                      </span>  field_type_strs[FIELD_TYPE_UNSIGNED]);<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>}<br class="">+<br class=""> <span class="Apple-tab-span" style="white-space:pre">  </span>if (priv->object_type == SC_UNKNOWN) {<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>tnt_raise(ClientError, ER_UNKNOWN_SCHEMA_OBJECT,<br class=""> <span class="Apple-tab-span" style="white-space:pre">                 </span>  object_type);<br class="">diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap<br class="">index b610828c9c9ae9a22acdd8c150c16c6838b7a273..da6961d1be7621fe9821623c7c2d57125e8ac7bc 100644<br class="">GIT binary patch<br class="">delta 1552<br class="">zcmV+r2JiWV43!L!7=JM>GBYwQXE`%5Ib$<nWMc|RZgX^DZewLSAZ0N(H8nRmV=XXd<br class="">zF*hwVWjJFkVlgvjEihy=V`616Vl-qkHVRflY;R+0Iv{&}3JTS_3%bn(ngGty8d0aE<br class="">z0000004TLD{QyvnEC6=>*h}EFr~oj`FvARU1MnJQi4e@o&wmVLh3G~crY-}4Qt)1A<br class="">zB2#HdNhp@x{7t9y{=-^iy?G~GRT*HEED-ei@Dn^G44RYT!B-?xN&&+Fx&Y1qV@|wy<br class="">z6m_Jn@7Frx341NeT$e$x{G;bbkGWq_9B~MwrUdvJKu^0mC)0U%u6xqfb3Hyc=uW3S<br class="">z?Yy*~VIJ-(N`EEV@r?j@mYTMGX?c^oS(oYGod@w`90IW?o~7muA2}mX0M&<$IO}p(<br class="">zf4&sYv(&5wsva}nU)$;MEH#TN5iEy0m!_+prRGbuYQ<Q1#lkEYO69^Y)ISUiiUp=t<br class="">zC>0okQ!15=OOySbmm=QXK9owS5|kbsI5j<pFj+#A<bTA{p5xH}*!A7AT`g}iJZp;q<br class="">zZa*(m3p`8BSuZbcKQF_xf+#w$E@QP&S5FE&OU<%B*MW5z3(smw@be+qmpn7j&(6bi<br class="">z4t2HV0FPP-q?QbLmYSt_Yv-+BSSX~f6!0uH^?h+1Um~{s3}1ZqeLFvQuFf=|{j%>m<br class="">z@5t{w$A3eAY2$e)R8<J*e6DdD-_^ohB@MWH-}BP;7}LqF7(2TzM;yY$&#@t$W%_kH<br class="">z9$%7&x;hfzS!$A(2E;oVI=}4a<;%;?_$pE>?lXx9syH+_Gd3aW42YQzE)T8_E)F-H<br class="">zZMkTx<ymTaw;U~*R7{GMf&o{c3QV2A(*~c@i+>4a(%@NY`j|3&7;fLG#dK@AP_j^}<br class="">zP;!~^J6oZkGC}22X(6$YN~9HQM=JH^bEJ+Wj3U%Z@+>t|M)c-`<Vzb_mpY#R-E$PB<br class="">z68(HF5MbZ$e*LnL=OE!wjv*E2foG|C>lf>C_fV+XIPfer%Uc*!XHsf;ldcAyrKaq~<br class="">zTz|`(6uRQYTqhKE{4`zxF)J9%3;Y*e!9Y}Om3pCY>tRqbsThdDE*Ta}CiN~&>g}76<br class="">z!4jk9%y>A~28QcJ%EhV0$D*{Nl2mw>nl_~poi;_)WA0d&u^?M<U+bo*s7Oh*@hmk*<br class="">z^!ff;)@2Y1&r<Wm(u(_9C-##iKP!s~oPR~~_fYj}UL1E0XYo~%x@vJBSVCtS?4Grf<br class="">z@GLby$YL|n#zmT&8l1t!jMuTP=pcEc^R-#cNb1fwio7!{#Iv85xz4|oot5G~aD->6<br class="">zNt2TTsE)CLA*jJzWK0dr004jhC;$-#M=54i4-$aDIEte%3SbZhL<l$vP80xu;D10^<br class="">zK@mhP7zBVEle%IQ1m-ef91jM-02ly+*uYMhP>(DFTh=t}nh{on7iA*E0z$QhnjhC8<br class="">zCtYIjZW*~2>%o=401{W2UfNK%SuRO#7z?U1OHmr$_k9#!4DKOfeHdDiLMUMhE_CY3<br class="">zQ}wM+3}S$xrp{sO0%D-Qg!Tg?N`D#c#11D%H1uMldybk2C_2GIa1@o`AvlV1g6&6a<br class="">zBm#;e0oq=kL|+Xk(;`Axi4jzulb=M-vXNUm0-}edv^<XF;UF|bEL;aGO3HyUXd&f5<br class="">z88k6w(AXZb_cg2b20{u-Z}C<nz{iAARh?|geYYKQ#VFi+XhmiG4;^%v=zqu$=*R1g<br class="">zez1GMebM(LHVMWg)roWz-LV|EY6+@Ey-NL+1I(uM&?2Z6(jNJW%xscWl(`{?w{V+H<br class="">z{3j}V(4Y_$d?5u8Nb<Kvi(X_xgWx*i-)Jo|L*giI$9)9W!7HhLCvO%PO>J)qU^;iT<br class="">zG&tlm=>j9yIEcC(gPg(fIe%Gp29&-BccznI$Z20Zp2%7_$W9>{;D>@m9ppFRLi`BZ<br class="">zxQFm2G$}GSoq&fM>MYyVZ?D8K%fMRllKy8xF*61u0i|dk(Um!gfT;c_$vzr)bR`hg<br class="">z8QidjRzibA!Kym`2j>)8MFY}}Gzpe5HBi$3iFF|fX;^3K2nxO;&<T@dg3AHb5UuS&<br class="">CN52^W<br class=""><br class="">delta 1534<br class="">zcmV<a1p)e%41^4j7=JJ=G%zh^V>dT4F*z~{Np5p=VQyn(Iv_b=V_`LAF*YqTV`gS8<br class="">zG-hTvEnzrjFfCy?W;Qf4VP!dGGGq!?Lu_wjYdRo%F*+bOeF_TIx(m9^1&9F7A|rpb<br class="">zr2qf`001bpFZ}>e{VM<lJ=RLl7I6XqUp$Ch%_7lYJ_Lj_@PFoXP~+we(A76EO7~<&<br class="">z)F3;RA|;uhw(`4WgTRw>I&<{eU?~Ai$VOI~v629dx2JaIm@kx4N&&zCxB$xlBK}6v<br class="">zM#}nreKVfmYggvF>;bcooE<&pjzw|&ydgCd;B)Xi4C|Up=iRyONm;Mu=<J|49rmyj<br class="">z!~XSg?^aVP(0>n31mId~$~K1OP2OJJrGIzc!y|v*5Q}mxHFpG|K|%#jeQ^A;E^l>*<br class="">z3*Bp}NefgxX1+gm^KmUTgDMc1Jsb?P)oZC4!mL!?OgGcvU!7uNP_0u4V%4c@$$Tde<br class="">z<JJuBKo=+bJ1@oWHsew%rA$(CR4!bhCq$aiEJ3j}Cx2ttc)M<~yh-n@9Ru2aUZxgY<br class="">zOU+j=F>OCDy|bcHe0;hLW1g*=6kJQqvOo9n=`!@rT1v3PA=sEaGtUmrgF1V*+HwF$<br class="">z%o|ck2Ck)MDdN~U>lpNk)Rh9)Qd8p>$FU`TvVVQ}JNw3+pEy`&7|(v!cb#wKcU}Xc<br class="">zztr*E^M9!-1a3aZxQyRo-mQ)X;JxvQVS5a1E-Z#;*X8(mp!hlb(b=Wn_TxWHa?e&p<br class="">z0<NVdiD5jvlVdHR&M*6U`SOA@wvN<F<4PlXstt_|t42g+g<yeLeOP%|b(q;~x1wEl<br class="">zEj90~M>ms_NyVg8C=MtXRLX=hZO}2jlujiL*MCw|r<8%iFyl-urCG}bk_A!)lFN(Z<br class="">z*9rxd2`ZdQ%ZOz}8m(9>QmHeYBvm9q6rtA9wbTrW=uAh+mpZa8Z9M*WuhEnWw8OPP<br class="">z0Ken?`duE+M1Fc0sWuO;rRJ>TPnWxUKDEZdwbU$UUQcC(VtJFR2G>&aT`%TX-lUJ$<br class="">zzkkQk8h`!+Ak42Gb5O~I9X_GL4xhR(RGq@`<8YEmeGLBa%Ed{YaV#4wH7X6(wXrob<br class="">zRx(mCOfa|?Bo}qm;#z9jPz5?Ii>k-mKV61Bw$iw6MNm)>lUj2vHAVFK{#e#!kBV!l<br class="">ziDGG`ab1f2WXaFUg5t{}`TM8d6EBXt_J3uuRg$)9X&lOg&M*+4wU)S+njl=^i<EJZ<br class="">zX2ppwLyQ}LBXiMF<cgb*y<$jG_{C2oetkYX_VcpV`IoM<QW}RMaV<4zXt3a^V}T&3<br class="">z(OhIq3CsWhfB+}}AqGb&W<?JYfWSD4qc93!7zRWLI0_9I0RX{)ke~>l77Rj$ynhqj<br class="">zxeG%W18Ui|uoin^FOJH&6BE><l!R4e54%@5i^3tJ2=RjuhoRy}$qP!PWxP;CvBe2+<br class="">zB`AQ$m7GU4)NS@llAFhZ>1-;h#Us!zr2@yPWOP}$xk=>TS*Ej6Q8ZgBx&}sXh}Wym<br class="">z;Yvs=Xm6s&oTIkS5VXc28)t^2+kc4qR4r1#;*gdpU~^0s$pG8pm?G)gVGer7p5*j@<br class="">zrQSOro_cGm&fR}<@b8h^=iXW!%4reE=RqJFW<g443Z&4$8`^`Azzc12c=p(Su(w)T<br class="">z1)jmCmtK6UOn@l~=HxoFllhK1;>sqt`1BcS0HC@As3ba#z^Ko9Pi8avYk$Oa!!S#&<br class="">zSx3_!A8xyrpfT#3Y0zk_Hi}Y>p%$pI61F+5M3N&%2xKJAC;$CDD}<6?=$#5uoTZ5Z<br class="">zCNj}EgB|fKv=$L@ag>MEJ_76DnN*W1Z`O`MZ9ptwx|K1yxMV1V1(Ltx%(4y7obk4E<br class="">zW?=^8GIQ=kv4A0`wS7N1*>`Z!opukPx!_g@c{8|RJi<`!QS!z#<&+X#nnV8V6uo^%<br class="">zFL^|hfwSZ-+|LAZ&d5i?Zt>-$tMH_1UnT!Yb{@SussOv@WfJ50JyfLCQd9Bw_N-dh<br class="">k2=V>Mm|$S01}gnuSl5<E4okR>OyKJnJxL~`9Mur5?b8(5ga7~l<br class=""><br class="">diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua<br class="">index b9b8c9004..361810c79 100644<br class="">--- a/src/box/lua/schema.lua<br class="">+++ b/src/box/lua/schema.lua<br class="">@@ -1801,17 +1801,19 @@ local function privilege_name(privilege)<br class=""> end<br class=""> <br class=""> local function object_resolve(object_type, object_name)<br class="">+    if object_name ~= nil and type(object_name) ~= 'string'<br class="">+            and type(object_name) ~= 'number' then<br class="">+        box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")<br class="">+    end<br class="">     if object_type == 'universe' then<br class="">-        if object_name ~= nil and type(object_name) ~= 'string'<br class="">-                and type(object_name) ~= 'number' then<br class="">-            box.error(box.error.ILLEGAL_PARAMS, "wrong object name type")<br class="">-        end<br class="">         return 0<br class="">     end<br class="">+    if (object_type == 'space' or object_type == 'function' or<br class="">+       object_type == 'sequence' or object_type == 'role') and<br class="">+       object_name == nil then<br class="">+        return '*'<br class="">+    end<br class="">     if object_type == 'space' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">-        end<br class="">         local space = box.space[object_name]<br class="">         if  space == nil then<br class="">             box.error(box.error.NO_SUCH_SPACE, object_name)<br class="">@@ -1819,9 +1821,6 @@ local function object_resolve(object_type, object_name)<br class="">         return <a href="http://space.id" class="">space.id</a><br class="">     end<br class="">     if object_type == 'function' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">-        end<br class="">         local _vfunc = box.space[box.schema.VFUNC_ID]<br class="">         local func<br class="">         if type(object_name) == 'string' then<br class="">@@ -1836,9 +1835,6 @@ local function object_resolve(object_type, object_name)<br class="">         end<br class="">     end<br class="">     if object_type == 'sequence' then<br class="">-        if object_name == nil or object_name == 0 then<br class="">-            return 0<br class="">-        end<br class="">         local seq = sequence_resolve(object_name)<br class="">         if seq == nil then<br class="">             box.error(box.error.NO_SUCH_SEQUENCE, object_name)<br class="">@@ -1867,6 +1863,9 @@ local function object_name(object_type, object_id)<br class="">     if object_type == 'universe' then<br class="">         return ""<br class="">     end<br class="">+    if object_id == '*' then<br class="">+        return '*'<br class="">+    end<br class="">     local space<br class="">     if object_type == 'space' then<br class="">         space = box.space._vspace<br class="">@@ -2106,10 +2105,10 @@ local function grant(uid, name, privilege, object_type,<br class="">         _priv:replace{options.grantor, uid, object_type, oid, privilege_hex}<br class="">     elseif not options.if_not_exists then<br class="">             if object_type == 'role' then<br class="">-                box.error(box.error.ROLE_GRANTED, name, object_name)<br class="">+                box.error(box.error.ROLE_GRANTED, name, object_name or '*')<br class="">             else<br class="">                 box.error(box.error.PRIV_GRANTED, name, privilege,<br class="">-                          object_type, object_name)<br class="">+                          object_type, object_name or '*')<br class="">             end<br class="">     end<br class=""> end<br class="">@@ -2134,10 +2133,10 @@ local function revoke(uid, name, privilege, object_type, object_name, options)<br class="">             return<br class="">         end<br class="">         if object_type == 'role' then<br class="">-            box.error(box.error.ROLE_NOT_GRANTED, name, object_name)<br class="">+            box.error(box.error.ROLE_NOT_GRANTED, name, object_name or '*')<br class="">         else<br class="">             box.error(box.error.PRIV_NOT_GRANTED, name, privilege,<br class="">-                      object_type, object_name)<br class="">+                      object_type, object_name or '*')<br class="">         end<br class="">     end<br class="">     local old_privilege = tuple[5]<br class="">@@ -2153,13 +2152,14 @@ local function revoke(uid, name, privilege, object_type, object_name, options)<br class="">             return<br class="">         end<br class="">         box.error(box.error.PRIV_NOT_GRANTED, name, privilege,<br class="">-                  object_type, object_name)<br class="">+                  object_type, object_name or '*')<br class="">     end<br class="">     if privilege_hex ~= 0 then<br class="">         _priv:replace{grantor, uid, object_type, oid, privilege_hex}<br class="">     else<br class="">         _priv:delete{uid, object_type, oid}<br class="">     end<br class="">+<br class=""> end<br class=""> <br class=""> local function drop(uid, opts)<br class="">@@ -2192,9 +2192,10 @@ local function drop(uid, opts)<br class="">     local privs = _vpriv.index.primary:select{uid}<br class=""> <br class="">     for k, tuple in pairs(privs) do<br class="">-<span class="Apple-tab-span" style="white-space:pre">      </span>-- we need an additional box.session.su() here, because of<br class="">-<span class="Apple-tab-span" style="white-space:pre">    </span>-- unnecessary check for privilege PRIV_REVOKE in priv_def_check()<br class="">-        box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], tuple[4])<br class="">+        -- we need an additional box.session.su() here, because of<br class="">+        -- unnecessary check for privilege PRIV_REVOKE in priv_def_check()<br class="">+        local oid = tuple[4] ~= '*' and tuple[4] or nil<br class="">+        box.session.su("admin", revoke, uid, uid, tuple[5], tuple[3], oid)<br class="">     end<br class="">     box.space[box.schema.USER_ID]:delete{uid}<br class=""> end<br class="">diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua<br class="">index 0293f6ef8..5dbc09bbb 100644<br class="">--- a/src/box/lua/upgrade.lua<br class="">+++ b/src/box/lua/upgrade.lua<br class="">@@ -964,6 +964,28 @@ local function upgrade_to_1_10_0()<br class="">     create_vsequence_space()<br class=""> end<br class=""> <br class="">+--------------------------------------------------------------------------------<br class="">+--- Tarantool 1.10.1<br class="">+--------------------------------------------------------------------------------<br class="">+local function upgrade_space_priv_to_1_10_1()<br class="">+    local _priv = box.space._priv<br class="">+    local _vpriv = box.space._vpriv<br class="">+    local f = _priv:format()<br class="">+<br class="">+    f[4].type = 'scalar'<br class="">+    _priv:format(f)<br class="">+    f = _vpriv:format()<br class="">+    f[4].type = 'scalar'<br class="">+    _vpriv:format(f)<br class="">+    _priv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}<br class="">+    _vpriv.index.primary:alter{parts={2, 'unsigned', 3, 'string', 4, 'scalar'}}<br class="">+    _priv.index.object:alter{parts={3, 'string', 4, 'scalar'}}<br class="">+    _vpriv.index.object:alter{parts={3, 'string', 4, 'scalar'}}<br class="">+end<br class="">+<br class="">+local function upgrade_to_1_10_1()<br class="">+    upgrade_space_priv_to_1_10_1()<br class="">+end<br class=""> <br class=""> local function get_version()<br class="">     local version = box.space._schema:get{'version'}<br class="">@@ -991,6 +1013,7 @@ local function upgrade(options)<br class="">         {version = mkversion(1, 7, 6), func = upgrade_to_1_7_6, auto = false},<br class="">         {version = mkversion(1, 7, 7), func = upgrade_to_1_7_7, auto = true},<br class="">         {version = mkversion(1, 10, 0), func = upgrade_to_1_10_0, auto = true},<br class="">+        {version = mkversion(1, 10, 1), func = upgrade_to_1_10_1, auto = true},<br class="">     }<br class=""> <br class="">     for _, handler in ipairs(handlers) do<br class="">diff --git a/src/box/<a href="http://schema.cc" class="">schema.cc</a> b/src/box/<a href="http://schema.cc" class="">schema.cc</a><br class="">index 433f52c08..9958e9016 100644<br class="">--- a/src/box/<a href="http://schema.cc" class="">schema.cc</a><br class="">+++ b/src/box/<a href="http://schema.cc" class="">schema.cc</a><br class="">@@ -536,10 +536,18 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)<br class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>switch (type) {<br class=""> <span class="Apple-tab-span" style="white-space:pre">  </span>case SC_UNIVERSE:<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">         </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_ROLE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">          </span>return "";<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>case SC_ENTITY_USER:<br class="">+<span class="Apple-tab-span" style="white-space:pre">          </span>return "";<br class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>case SC_SPACE:<br class=""> <span class="Apple-tab-span" style="white-space:pre">           </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">                     </span>if (object_id == 0)<br class="">-<span class="Apple-tab-span" style="white-space:pre">                           </span>return "SPACE";<br class=""> <span class="Apple-tab-span" style="white-space:pre">                        </span>struct space *space = space_by_id(object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">                    </span>if (space == NULL)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                               </span>break;<br class="">@@ -547,8 +555,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>case SC_FUNCTION:<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">                     </span>if (object_id == 0)<br class="">-<span class="Apple-tab-span" style="white-space:pre">                           </span>return "FUNCTION";<br class=""> <span class="Apple-tab-span" style="white-space:pre">                     </span>struct func *func = func_by_id(object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">                       </span>if (func == NULL)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                                </span>break;<br class="">@@ -556,8 +562,6 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SEQUENCE:<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">                     </span>if (object_id == 0)<br class="">-<span class="Apple-tab-span" style="white-space:pre">                           </span>return "SEQUENCE";<br class=""> <span class="Apple-tab-span" style="white-space:pre">                     </span>struct sequence *seq = sequence_by_id(object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">                        </span>if (seq == NULL)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                         </span>break;<br class="">diff --git a/src/box/schema.h b/src/box/schema.h<br class="">index 0822262d0..f1735ff34 100644<br class="">--- a/src/box/schema.h<br class="">+++ b/src/box/schema.h<br class="">@@ -250,16 +250,19 @@ static inline<br class=""> struct access *<br class=""> entity_access_get(enum schema_object_type type)<br class=""> {<br class="">-       switch (type) {<br class="">-       case SC_SPACE:<br class="">-               return entity_access.space;<br class="">-       case SC_FUNCTION:<br class="">-               return entity_access.function;<br class="">-       case SC_SEQUENCE:<br class="">-               return entity_access.sequence;<br class="">-       default:<br class="">-               return NULL;<br class="">-       }<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>switch (type) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>case SC_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_ENTITY_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">         </span>return entity_access.space;<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span>case SC_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>return entity_access.function;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>return entity_access.sequence;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>default:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>return NULL;<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>}<br class=""> }<br class=""> <br class=""> #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */<br class="">diff --git a/src/box/schema_def.c b/src/box/schema_def.c<br class="">index 97c074ab2..18ec6c8d2 100644<br class="">--- a/src/box/schema_def.c<br class="">+++ b/src/box/schema_def.c<br class="">@@ -31,16 +31,39 @@<br class=""> #include "schema_def.h"<br class=""> <br class=""> static const char *object_type_strs[] = {<br class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>/* [SC_UKNNOWN]         = */ "unknown",<br class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>/* [SC_UNIVERSE]        = */ "universe",<br class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>/* [SC_SPACE]           = */ "space",<br class="">-<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_FUNCTION]        = */ "function",<br class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>/* [SC_USER]            = */ "user",<br class="">-<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ROLE]            = */ "role",<br class="">-<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_SEQUENCE]        = */ "sequence",<br class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>/* [SC_COLLATION]       = */ "collation",<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>/* [SC_UKNNOWN]<span class="Apple-tab-span" style="white-space:pre">             </span>    = */ "unknown",<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>/* [SC_UNIVERSE]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "universe",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_SPACE]<span class="Apple-tab-span" style="white-space:pre">               </span>    = */ "space",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_ENTITY_SPACE]<span class="Apple-tab-span" style="white-space:pre">        </span>    = */ "space",<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>/* [SC_FUNCTION]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "function",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_ENTITY_FUNCTION]<span class="Apple-tab-span" style="white-space:pre">     </span>    = */ "function",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_USER]<span class="Apple-tab-span" style="white-space:pre">                </span>    = */ "user",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ENTITY_USER]<span class="Apple-tab-span" style="white-space:pre"> </span>    = */ "user",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ROLE]<span class="Apple-tab-span" style="white-space:pre">                </span>    = */ "role",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_ENTITY_ROLE]<span class="Apple-tab-span" style="white-space:pre"> </span>    = */ "role",<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>/* [SC_SEQUENCE]<span class="Apple-tab-span" style="white-space:pre">    </span>    = */ "sequence",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_ENTITY_SEQUENCE]<span class="Apple-tab-span" style="white-space:pre">     </span>    = */ "sequence",<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>/* [SC_COLLATION]<span class="Apple-tab-span" style="white-space:pre">   </span>    = */ "collation",<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>/* [SC_ENTITY_COLLATION]    = */ "collation",<br class=""> };<br class=""> <br class="">+enum schema_object_type<br class="">+schema_entity_type(enum schema_object_type type)<br class="">+{<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>switch(type) {<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>case SC_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_USER:<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>case SC_ROLE:<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>case SC_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_COLLATION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">            </span>return type + 1;<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>break;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>default:<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>unreachable();<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>}<br class="">+}<br class="">+<br class=""> enum schema_object_type<br class=""> schema_object_type(const char *name)<br class=""> {<br class="">diff --git a/src/box/schema_def.h b/src/box/schema_def.h<br class="">index 2edb8d37f..9b5bd6864 100644<br class="">--- a/src/box/schema_def.h<br class="">+++ b/src/box/schema_def.h<br class="">@@ -218,19 +218,35 @@ enum {<br class="">  *<br class="">  * Use 0 for unknown to use the same index consistently<br class="">  * even when there are more object types in the future.<br class="">+ *<br class="">+ * When adding new types please follow this rule:<br class="">+ * SC_ENTITY_NEW_OBJECT = SC_NEW_OBJECT + 1<br class="">+ * schema_entity_type() relies on this convention.<br class="">  */<br class=""> enum schema_object_type {<br class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>SC_UNKNOWN = 0,<br class=""> <span class="Apple-tab-span" style="white-space:pre">  </span>SC_UNIVERSE = 1,<br class=""> <span class="Apple-tab-span" style="white-space:pre"> </span>SC_SPACE = 2,<br class="">-<span class="Apple-tab-span" style="white-space:pre"> </span>SC_FUNCTION = 3,<br class="">-<span class="Apple-tab-span" style="white-space:pre">      </span>SC_USER = 4,<br class="">-<span class="Apple-tab-span" style="white-space:pre">  </span>SC_ROLE = 5,<br class="">-<span class="Apple-tab-span" style="white-space:pre">  </span>SC_SEQUENCE = 6,<br class="">-<span class="Apple-tab-span" style="white-space:pre">      </span>SC_COLLATION = 7,<br class="">-<span class="Apple-tab-span" style="white-space:pre">     </span>schema_object_type_MAX = 8<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>SC_ENTITY_SPACE = 3,<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>SC_FUNCTION = 4,<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>SC_ENTITY_FUNCTION = 5,<br class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>SC_USER = 6,<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>SC_ENTITY_USER = 7,<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span>SC_ROLE = 8,<br class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>SC_ENTITY_ROLE = 9,<br class="">+<span class="Apple-tab-span" style="white-space:pre">   </span>SC_SEQUENCE = 10,<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>SC_ENTITY_SEQUENCE = 11,<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>SC_COLLATION = 12,<br class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>SC_ENTITY_COLLATION = 13,<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>schema_object_type_MAX = 13<br class=""> };<br class=""> <br class="">+/**<br class="">+ * Given a object type, return an entity type it belongs to.<br class="">+ */<br class="">+enum schema_object_type<br class="">+schema_entity_type(enum schema_object_type type);<br class="">+<br class=""> enum schema_object_type<br class=""> schema_object_type(const char *name);<br class=""> <br class="">diff --git a/src/box/<a href="http://user.cc" class="">user.cc</a> b/src/box/<a href="http://user.cc" class="">user.cc</a><br class="">index fbf06566a..eec785652 100644<br class="">--- a/src/box/<a href="http://user.cc" class="">user.cc</a><br class="">+++ b/src/box/<a href="http://user.cc" class="">user.cc</a><br class="">@@ -207,12 +207,23 @@ access_find(struct priv_def *priv)<br class=""> <span class="Apple-tab-span" style="white-space:pre">         </span>access = universe.access;<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>break;<br class=""> <span class="Apple-tab-span" style="white-space:pre">   </span>}<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_SPACE:<br class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>{<br class="">+<span class="Apple-tab-span" style="white-space:pre">             </span>access = entity_access.space;<br class="">+<span class="Apple-tab-span" style="white-space:pre">         </span>break;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>}<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_FUNCTION:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>{<br class="">+<span class="Apple-tab-span" style="white-space:pre">             </span>access = entity_access.function;<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>break;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>}<br class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>case SC_ENTITY_SEQUENCE:<br class="">+<span class="Apple-tab-span" style="white-space:pre">      </span>{<br class="">+<span class="Apple-tab-span" style="white-space:pre">             </span>access = entity_access.sequence;<br class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>break;<br class="">+<span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SPACE:<br class=""> <span class="Apple-tab-span" style="white-space:pre">   </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>if (priv->object_id == 0) {<br class="">-<span class="Apple-tab-span" style="white-space:pre">                        </span>access = entity_access.space;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                 </span>break;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>struct space *space = space_by_id(priv->object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">           </span>if (space)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                       </span>access = space->access;<br class="">@@ -220,10 +231,6 @@ access_find(struct priv_def *priv)<br class=""> <span class="Apple-tab-span" style="white-space:pre">   </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>case SC_FUNCTION:<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>if (priv->object_id == 0) {<br class="">-<span class="Apple-tab-span" style="white-space:pre">                        </span>access = entity_access.function;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span>break;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>struct func *func = func_by_id(priv->object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">              </span>if (func)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                        </span>access = func->access;<br class="">@@ -231,10 +238,6 @@ access_find(struct priv_def *priv)<br class=""> <span class="Apple-tab-span" style="white-space:pre">    </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>case SC_SEQUENCE:<br class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>{<br class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>if (priv->object_id == 0) {<br class="">-<span class="Apple-tab-span" style="white-space:pre">                        </span>access = entity_access.sequence;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span>break;<br class="">-<span class="Apple-tab-span" style="white-space:pre">                </span>}<br class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>struct sequence *seq = sequence_by_id(priv->object_id);<br class=""> <span class="Apple-tab-span" style="white-space:pre">               </span>if (seq)<br class=""> <span class="Apple-tab-span" style="white-space:pre">                 </span>access = seq->access;<br class="">diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result<br class="">index 16c2027cf..1641c318e 100644<br class="">--- a/test/box-py/bootstrap.result<br class="">+++ b/test/box-py/bootstrap.result<br class="">@@ -5,7 +5,7 @@ box.space._schema:select{}<br class=""> ---<br class=""> - - ['cluster', '<cluster uuid>']<br class="">   - ['max_id', 511]<br class="">-  - ['version', 1, 10, 0]<br class="">+  - ['version', 1, 10, 1]<br class=""> ...<br class=""> box.space._cluster:select{}<br class=""> ---<br class="">@@ -58,10 +58,10 @@ box.space._space:select{}<br class="">         'type': 'string'}, {'name': 'auth', 'type': 'map'}]]<br class="">   - [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {<br class="">         'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},<br class="">       {'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',<br class="">         'type': 'string'}]]<br class="">   - [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',<br class="">@@ -104,13 +104,13 @@ box.space._index:select{}<br class="">   - [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]<br class="">   - [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]<br class="">   - [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">   - [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]<br class="">   - [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">diff --git a/test/box/access.result b/test/box/access.result<br class="">index f4669a4a3..687bbf579 100644<br class="">--- a/test/box/access.result<br class="">+++ b/test/box/access.result<br class="">@@ -504,7 +504,7 @@ box.space._priv:select{id}<br class=""> ...<br class=""> box.schema.user.grant('user', 'read', 'universe')<br class=""> ---<br class="">-- error: User 'user' already has read access on universe 'nil'<br class="">+- error: User 'user' already has read access on universe '*'<br class=""> ...<br class=""> box.space._priv:select{id}<br class=""> ---<br class="">@@ -690,7 +690,7 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe')<br class=""> ...<br class=""> box.schema.user.grant('guest', 'read,write,execute', 'universe')<br class=""> ---<br class="">-- error: User 'guest' already has read,write,execute access on universe 'nil'<br class="">+- error: User 'guest' already has read,write,execute access on universe '*'<br class=""> ...<br class=""> box.schema.user.grant('guest', 'read,write,execute', 'universe', '', { if_not_exists = true })<br class=""> ---<br class="">@@ -703,7 +703,7 @@ box.schema.user.revoke('guest', 'usage,session', 'universe')<br class=""> ...<br class=""> box.schema.user.revoke('guest', 'read,write,execute', 'universe')<br class=""> ---<br class="">-- error: User 'guest' does not have read,write,execute access on universe 'nil'<br class="">+- error: User 'guest' does not have read,write,execute access on universe '*'<br class=""> ...<br class=""> box.schema.user.revoke('guest', 'read,write,execute', 'universe', '', { if_exists = true })<br class=""> ---<br class="">diff --git a/test/box/access_misc.result b/test/box/access_misc.result<br class="">index 2d87fa2d5..7d6aa0a4b 100644<br class="">--- a/test/box/access_misc.result<br class="">+++ b/test/box/access_misc.result<br class="">@@ -436,7 +436,7 @@ box.schema.user.revoke('testuser', 'usage,session', 'universe')<br class=""> ...<br class=""> box.schema.user.revoke('testuser', 'read, write, execute', 'universe')<br class=""> ---<br class="">-- error: User 'testuser' does not have read, write, execute access on universe 'nil'<br class="">+- error: User 'testuser' does not have read, write, execute access on universe '*'<br class=""> ...<br class=""> box.schema.user.revoke('testuser', 'create', 'universe')<br class=""> ---<br class="">@@ -797,10 +797,10 @@ box.space._space:select()<br class="">         'type': 'string'}, {'name': 'auth', 'type': 'map'}]]<br class="">   - [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {<br class="">         'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},<br class="">       {'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',<br class="">         'type': 'string'}]]<br class="">   - [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',<br class="">@@ -853,7 +853,7 @@ box.schema.user.grant('tester', 'read', 'universe')<br class=""> -- error: the privilege is not granted<br class=""> box.schema.user.revoke('tester', 'create', 'universe')<br class=""> ---<br class="">-- error: User 'tester' does not have create access on universe 'nil'<br class="">+- error: User 'tester' does not have create access on universe '*'<br class=""> ...<br class=""> -- no error: if_exists clause<br class=""> box.schema.user.revoke('tester', 'create', 'universe', nil, { if_exists = true })<br class="">diff --git a/test/box/alter.result b/test/box/alter.result<br class="">index eb7014d8b..36bdb5fd3 100644<br class="">--- a/test/box/alter.result<br class="">+++ b/test/box/alter.result<br class="">@@ -214,13 +214,13 @@ _index:select{}<br class="">   - [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]<br class="">   - [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]<br class="">   - [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">   - [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]<br class="">   - [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">diff --git a/test/xlog/upgrade.result b/test/xlog/upgrade.result<br class="">index f02996bba..8f5b4ad26 100644<br class="">--- a/test/xlog/upgrade.result<br class="">+++ b/test/xlog/upgrade.result<br class="">@@ -36,7 +36,7 @@ box.space._schema:select()<br class=""> ---<br class=""> - - ['cluster', '<server_uuid>']<br class="">   - ['max_id', 513]<br class="">-  - ['version', 1, 10, 0]<br class="">+  - ['version', 1, 10, 1]<br class=""> ...<br class=""> box.space._space:select()<br class=""> ---<br class="">@@ -85,10 +85,10 @@ box.space._space:select()<br class="">         'type': 'string'}, {'name': 'auth', 'type': 'map'}]]<br class="">   - [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {<br class="">         'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [313, 1, '_vpriv', 'sysview', 0, {}, [{'name': 'grantor', 'type': 'unsigned'},<br class="">       {'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},<br class="">-      {'name': 'object_id', 'type': 'unsigned'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">+      {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]<br class="">   - [320, 1, '_cluster', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'uuid',<br class="">         'type': 'string'}]]<br class="">   - [330, 1, '_truncate', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'count',<br class="">@@ -134,13 +134,13 @@ box.space._index:select()<br class="">   - [305, 1, 'owner', 'tree', {'unique': false}, [[1, 'unsigned']]]<br class="">   - [305, 2, 'name', 'tree', {'unique': true}, [[2, 'string']]]<br class="">   - [312, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [312, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [312, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [313, 0, 'primary', 'tree', {'unique': true}, [[1, 'unsigned'], [2, 'string'],<br class="">-      [3, 'unsigned']]]<br class="">+      [3, 'scalar']]]<br class="">   - [313, 1, 'owner', 'tree', {'unique': false}, [[0, 'unsigned']]]<br class="">-  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'unsigned']]]<br class="">+  - [313, 2, 'object', 'tree', {'unique': false}, [[2, 'string'], [3, 'scalar']]]<br class="">   - [320, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">   - [320, 1, 'uuid', 'tree', {'unique': true}, [[1, 'string']]]<br class="">   - [330, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned']]]<br class="">-- <br class="">2.15.2 (Apple Git-101.1)<br class=""><br class=""><br class=""></body></html>