tarantool/graphql

Add support of returning gaped arrays for kind=types.list()

no1seman opened this issue · 0 comments

Image user have the following space format:
['string', 'string', 'string', 'string', 'string', 'string', 'string', 'string'], all fields except furst one is nullaple, PK on first field and imagine that the actual tuple in this space is the following: ['1', 'b', 'a', null, null, null, 'c']. From the point of view of the Tarantool, this is fully valid tuple.

An imagine that user needs to return this tuple in kind=types.list(types.string).

In current version user can't do this because:

  • 1.4.0 doesn't support gapped arrays (ipairs is used which iterates until first nil)
  • util.is_array() may hang on some combinations of keys (see closed issue: #51)

Here is a little test:

diff --git a/graphql/execute.lua b/graphql/execute.lua
index 8622736..fe1d1bd 100644
--- a/graphql/execute.lua
+++ b/graphql/execute.lua
@@ -208,7 +208,7 @@ local function completeValue(fieldType, result, subSelections, context, opts)
 
     local innerType = fieldType.ofType
     local values = {}
-    for i, value in ipairs(result) do
+    for i, value in pairs(result) do
       values[i] = completeValue(innerType, value, subSelections, context)
     end
 
diff --git a/test/integration/graphql_test.lua b/test/integration/graphql_test.lua
index 6462450..d8e563a 100644
--- a/test/integration/graphql_test.lua
+++ b/test/integration/graphql_test.lua
@@ -2147,3 +2147,39 @@ function g.test_non_finite_float()
             query_schema, nil, nil, {variables = variables})
     end
 end
+
+function g.test_is_array_invalid()
+    local query = [[
+       query ($x: [String]) { test(arg: $x) }
+   ]]
+
+   local function callback(_, args)
+        setmetatable(args.arg, {__serialize='array'})
+        return args.arg
+   end
+
+   local query_schema = {
+       ['test'] = {
+           kind = types.list(types.string),
+           arguments = {
+               arg = types.list(types.string),
+           },
+           resolve = callback,
+       }
+   }
+
+   local test_values = {
+       {[3] = 'a', [1] = 'b', [6] = 'c'},
+       {[3] = 'a', [1] = 'b', [7] = 'c'}, -- got error: Variable "x" for a List must be an array, got map
+   }
+
+   for _, v in ipairs(test_values) do
+       local variables = {x = v}
+       local res = check_request(query, query_schema, nil, nil, {variables = variables})
+       t.assert_type(res, 'table')
+
+       print(json.encode(res.test))
+       print(json.encode(v))
+       t.assert_equals(json.encode(res.test), json.encode(v))
+   end
+end

Seems that this case must be fixed anyway.