From 4a08a9a366d93962fd8088750337a2fcab1956f8 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Sun, 5 Apr 2015 22:38:06 +0300
Subject: [PATCH] gh-637: 'if_not_exists' option for box.schema.*.create()

Implement box.schema.user.create(name, { if_not_exists = true })
box.schema.role.create(name, { if_not_exists = true })
box.schema.func.create(name, { if_not_exists = true })

Add tests.

Fixes gh-637.
---
 src/box/lua/schema.lua   | 25 ++++++++++++++++++-------
 test/box/access.result   |  9 +++++++++
 test/box/access.test.lua |  3 +++
 test/box/role.result     | 27 +++++++++++++++++++++++++++
 test/box/role.test.lua   |  9 +++++++++
 5 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 7511ee82e1..3299532e59 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1004,12 +1004,16 @@ end
 
 box.schema.func = {}
 box.schema.func.create = function(name, opts)
+    opts = opts or {}
     local _func = box.space[box.schema.FUNC_ID]
     local func = _func.index.name:get{name}
     if func then
+        if not opts.if_not_exists then
             box.error(box.error.FUNCTION_EXISTS, name)
+        end
+        return
     end
-    check_param_table(opts, { setuid = 'boolean' })
+    check_param_table(opts, { setuid = 'boolean', if_not_exists = 'boolean' })
     opts = update_param_table(opts, { setuid = false })
     opts.setuid = opts.setuid and 1 or 0
     _func:auto_increment{session.uid(), name, opts.setuid}
@@ -1073,11 +1077,13 @@ end
 
 box.schema.user.create = function(name, opts)
     local uid = user_or_role_resolve(name)
+    opts = opts or {}
+    check_param_table(opts, { password = 'string', if_not_exists = 'boolean' })
     if uid then
-        box.error(box.error.USER_EXISTS, name)
-    end
-    if opts == nil then
-        opts = {}
+        if not opts.if_not_exists then
+            box.error(box.error.USER_EXISTS, name)
+        end
+        return
     end
     auth_mech_list = {}
     if opts.password then
@@ -1259,10 +1265,15 @@ box.schema.role.exists = function(name)
     end
 end
 
-box.schema.role.create = function(name)
+box.schema.role.create = function(name, opts)
+    opts = opts or {}
+    check_param_table(opts, { if_not_exists = 'boolean' })
     local uid = user_or_role_resolve(name)
     if uid then
-        box.error(box.error.ROLE_EXISTS, name)
+        if not opts.if_not_exists then
+            box.error(box.error.ROLE_EXISTS, name)
+        end
+        return
     end
     local _user = box.space[box.schema.USER_ID]
     _user:auto_increment{session.uid(), name, 'role'}
diff --git a/test/box/access.result b/test/box/access.result
index df27752714..28d22005a5 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -640,3 +640,12 @@ box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'read,write,execute', 'universe', '', { if_exists = true })
 ---
 ...
+box.schema.func.create('dummy', { if_not_exists = true })
+---
+...
+box.schema.func.create('dummy', { if_not_exists = true })
+---
+...
+box.schema.func.drop('dummy')
+---
+...
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index 2700b7e5be..ec0e5193d6 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -250,3 +250,6 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe', '', { if_not_ex
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'read,write,execute', 'universe', '', { if_exists = true })
+box.schema.func.create('dummy', { if_not_exists = true })
+box.schema.func.create('dummy', { if_not_exists = true })
+box.schema.func.drop('dummy')
diff --git a/test/box/role.result b/test/box/role.result
index 5e4ef6d6c0..f11af5c62a 100644
--- a/test/box/role.result
+++ b/test/box/role.result
@@ -799,3 +799,30 @@ box.schema.role.exists(0)
 ---
 - false
 ...
+box.schema.role.create('public', { if_not_exists = true})
+---
+...
+box.schema.user.create('admin', { if_not_exists = true})
+---
+...
+box.schema.user.create('guest', { if_not_exists = true})
+---
+...
+box.schema.user.create('test', { if_not_exists = true})
+---
+...
+box.schema.user.create('test', { if_not_exists = true})
+---
+...
+box.schema.role.drop('test', { if_not_exists = true})
+---
+...
+box.schema.role.create('test', { if_not_exists = true})
+---
+...
+box.schema.role.create('test', { if_not_exists = true})
+---
+...
+box.schema.user.drop('test', { if_not_exists = true})
+---
+...
diff --git a/test/box/role.test.lua b/test/box/role.test.lua
index 6036c3d587..6d3014edd5 100644
--- a/test/box/role.test.lua
+++ b/test/box/role.test.lua
@@ -317,3 +317,12 @@ box.schema.role.exists('admin')
 box.schema.role.exists(3)
 -- user id 
 box.schema.role.exists(0)
+box.schema.role.create('public', { if_not_exists = true})
+box.schema.user.create('admin', { if_not_exists = true})
+box.schema.user.create('guest', { if_not_exists = true})
+box.schema.user.create('test', { if_not_exists = true})
+box.schema.user.create('test', { if_not_exists = true})
+box.schema.role.drop('test', { if_not_exists = true})
+box.schema.role.create('test', { if_not_exists = true})
+box.schema.role.create('test', { if_not_exists = true})
+box.schema.user.drop('test', { if_not_exists = true})
-- 
GitLab