Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
abf75821
Commit
abf75821
authored
Feb 06, 2017
by
Alexey Botchkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-11557 port MySQL-5.7 JSON tests to MariaDB.
Fixes for issues found.
parent
e51b015f
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
637 additions
and
218 deletions
+637
-218
include/json_lib.h
include/json_lib.h
+6
-1
mysql-test/r/func_json.result
mysql-test/r/func_json.result
+67
-18
mysql-test/suite/json/r/json_no_table.result
mysql-test/suite/json/r/json_no_table.result
+149
-160
mysql-test/t/func_json.test
mysql-test/t/func_json.test
+20
-0
sql/item_create.cc
sql/item_create.cc
+72
-0
sql/item_jsonfunc.cc
sql/item_jsonfunc.cc
+211
-15
sql/item_jsonfunc.h
sql/item_jsonfunc.h
+26
-0
strings/json_lib.c
strings/json_lib.c
+86
-24
No files found.
include/json_lib.h
View file @
abf75821
...
...
@@ -409,7 +409,12 @@ int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs,
int
json_get_path_next
(
json_engine_t
*
je
,
json_path_t
*
p
);
int
json_path_compare
(
const
json_path_t
*
a
,
const
json_path_t
*
b
);
int
json_path_parts_compare
(
const
json_path_step_t
*
a
,
const
json_path_step_t
*
a_end
,
const
json_path_step_t
*
b
,
const
json_path_step_t
*
b_end
,
enum
json_value_types
vt
);
int
json_path_compare
(
const
json_path_t
*
a
,
const
json_path_t
*
b
,
enum
json_value_types
vt
);
#ifdef __cplusplus
...
...
mysql-test/r/func_json.result
View file @
abf75821
...
...
@@ -57,7 +57,7 @@ json_array_append('["a", "b"]', '$', FALSE)
["a", "b", false]
select json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2);
json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2)
{"k1":
1, "k2":
["a", "b", 2]}
{"k1":
1, "k2":
["a", "b", 2]}
select json_array_append('["a", ["b", "c"], "d"]', '$[0]', 2);
json_array_append('["a", ["b", "c"], "d"]', '$[0]', 2)
[["a", 2], ["b", "c"], "d"]
...
...
@@ -190,10 +190,10 @@ json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY")
NULL
select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2");
json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2")
["asd", [2,3]]
["asd", [2,
3]]
select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2");
json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2")
[5, [2,3]]
[5, [2,
3]]
select json_extract('{"key0":true, "key1":"qwe"}', "$.key1");
json_extract('{"key0":true, "key1":"qwe"}', "$.key1")
"qwe"
...
...
@@ -205,7 +205,7 @@ json_extract('[10, 20, [30, 40]]', '$[2][*]')
[30, 40]
select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]');
json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]')
[{"a":3}, 30, 40]
[{"a":
3}, 30, 40]
select json_extract('1', '$');
json_extract('1', '$')
1
...
...
@@ -220,29 +220,29 @@ json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a')
[[3, 4]]
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word');
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word')
{"a":
1, "b":{"c":1, "k1":"word"}, "d":
[1, 2]}
{"a":
1, "b": {"c": 1, "k1": "word"}, "d":
[1, 2]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3);
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3)
{"a":
1, "b":{"c":1}, "d":
[1, 2, 3]}
{"a":
1, "b": {"c": 1}, "d":
[1, 2, 3]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2);
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2)
{"a":
[1, 2], "b":{"c":1}, "d":
[1, 2]}
{"a":
[1, 2], "b": {"c": 1}, "d":
[1, 2]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word');
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word')
{"a":
1, "b":{"c":1}, "d":
[1, 2]}
{"a":
1, "b": {"c": 1}, "d":
[1, 2]}
select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]')
{
"a": 10, "b": [2, 3], "c":
"[true, false]"}
{
"a": 10, "b": [2, 3], "c":
"[true, false]"}
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]')
{
"a": 10, "b": [2, 3]}
{"a": 10, "b": [2, 3]}
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]');
json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]')
{
"a": 10, "b": "[true, false]"}
{"a": 10, "b": "[true, false]"}
set @j = '["a", ["b", "c"], "d"]';
select json_remove(@j, '$[0]');
json_remove(@j, '$[0]')
[
["b", "c"], "d"]
[["b", "c"], "d"]
select json_remove(@j, '$[1]');
json_remove(@j, '$[1]')
["a", "d"]
...
...
@@ -323,7 +323,7 @@ Warnings:
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_merge' at position 1
select json_merge('{"a":"b"}','{"c":"d"}');
json_merge('{"a":"b"}','{"c":"d"}')
{"a":
"b", "c":
"d"}
{"a":
"b", "c":
"d"}
SELECT JSON_MERGE('[1, 2]', '{"id": 47}');
JSON_MERGE('[1, 2]', '{"id": 47}')
[1, 2, {"id": 47}]
...
...
@@ -485,15 +485,13 @@ json_set('{"a":12}', '$[0]', 100)
100
select json_set('{"a":12}', '$[0].a', 100);
json_set('{"a":12}', '$[0].a', 100)
{"a":100}
{"a":
100}
select json_set('{"a":12}', '$[0][0].a', 100);
json_set('{"a":12}', '$[0][0].a', 100)
{"a":100}
{"a":
100}
select json_set('{"a":12}', '$[0][1].a', 100);
json_set('{"a":12}', '$[0][1].a', 100)
NULL
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set'
{"a": 12}
select json_value('{"\\"key1":123}', '$."\\"key1"');
json_value('{"\\"key1":123}', '$."\\"key1"')
123
...
...
@@ -503,3 +501,54 @@ json_value('{"\\"key1\\"":123}', '$."\\"key1\\""')
select json_value('{"key 1":123}', '$."key 1"');
json_value('{"key 1":123}', '$."key 1"')
123
select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]");
json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]")
1
select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]");
json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]")
0
select json_extract( '[1]', '$[0][0]' );
json_extract( '[1]', '$[0][0]' )
1
select json_extract( '[1]', '$[1][0]' );
json_extract( '[1]', '$[1][0]' )
NULL
select json_extract( '[1]', '$**[0]' );
json_extract( '[1]', '$**[0]' )
[1]
select json_extract( '[1]', '$**[0][0]' );
json_extract( '[1]', '$**[0][0]' )
[1]
select json_insert('1', '$[0]', 4);
json_insert('1', '$[0]', 4)
1
select json_replace('1', '$[0]', 4);
json_replace('1', '$[0]', 4)
4
select json_set('1', '$[0]', 4);
json_set('1', '$[0]', 4)
4
select json_set('1', '$[1]', 4);
json_set('1', '$[1]', 4)
[1, 4]
select json_replace('1', '$[1]', 4);
json_replace('1', '$[1]', 4)
1
SELECT json_insert('[]', '$[0][0]', 100);
json_insert('[]', '$[0][0]', 100)
[]
SELECT json_insert('1', '$[0][0]', 100);
json_insert('1', '$[0][0]', 100)
1
SELECT json_replace('1', '$[0][0]', 100);
json_replace('1', '$[0][0]', 100)
100
SELECT json_replace('[]', '$[0][0]', 100);
json_replace('[]', '$[0][0]', 100)
[]
SELECT json_set('[]', '$[0][0]', 100);
json_set('[]', '$[0][0]', 100)
[]
SELECT json_set('[]', '$[0][0][0]', 100);
json_set('[]', '$[0][0][0]', 100)
[]
mysql-test/suite/json/r/json_no_table.result
View file @
abf75821
This diff is collapsed.
Click to expand it.
mysql-test/t/func_json.test
View file @
abf75821
...
...
@@ -200,3 +200,23 @@ select json_set('{"a":12}', '$[0][1].a', 100);
select
json_value
(
'{"\\"key1":123}'
,
'$."\\"key1"'
);
select
json_value
(
'{"\\"key1\\"":123}'
,
'$."\\"key1\\""'
);
select
json_value
(
'{"key 1":123}'
,
'$."key 1"'
);
select
json_contains_path
(
'{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}'
,
'one'
,
"$**.a[2]"
);
select
json_contains_path
(
'{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}'
,
'one'
,
"$**.a[3]"
);
select
json_extract
(
'[1]'
,
'$[0][0]'
);
select
json_extract
(
'[1]'
,
'$[1][0]'
);
select
json_extract
(
'[1]'
,
'$**[0]'
);
select
json_extract
(
'[1]'
,
'$**[0][0]'
);
select
json_insert
(
'1'
,
'$[0]'
,
4
);
select
json_replace
(
'1'
,
'$[0]'
,
4
);
select
json_set
(
'1'
,
'$[0]'
,
4
);
select
json_set
(
'1'
,
'$[1]'
,
4
);
select
json_replace
(
'1'
,
'$[1]'
,
4
);
SELECT
json_insert
(
'[]'
,
'$[0][0]'
,
100
);
SELECT
json_insert
(
'1'
,
'$[0][0]'
,
100
);
SELECT
json_replace
(
'1'
,
'$[0][0]'
,
100
);
SELECT
json_replace
(
'[]'
,
'$[0][0]'
,
100
);
SELECT
json_set
(
'[]'
,
'$[0][0]'
,
100
);
SELECT
json_set
(
'[]'
,
'$[0][0][0]'
,
100
);
sql/item_create.cc
View file @
abf75821
...
...
@@ -1762,6 +1762,46 @@ class Create_func_json_valid : public Create_func_arg1
};
class
Create_func_json_compact
:
public
Create_func_arg1
{
public:
virtual
Item
*
create_1_arg
(
THD
*
thd
,
Item
*
arg1
);
static
Create_func_json_compact
s_singleton
;
protected:
Create_func_json_compact
()
{}
virtual
~
Create_func_json_compact
()
{}
};
class
Create_func_json_loose
:
public
Create_func_arg1
{
public:
virtual
Item
*
create_1_arg
(
THD
*
thd
,
Item
*
arg1
);
static
Create_func_json_loose
s_singleton
;
protected:
Create_func_json_loose
()
{}
virtual
~
Create_func_json_loose
()
{}
};
class
Create_func_json_detailed
:
public
Create_func_arg2
{
public:
virtual
Item
*
create_2_arg
(
THD
*
thd
,
Item
*
arg1
,
Item
*
arg2
);
static
Create_func_json_detailed
s_singleton
;
protected:
Create_func_json_detailed
()
{}
virtual
~
Create_func_json_detailed
()
{}
};
class
Create_func_json_type
:
public
Create_func_arg1
{
public:
...
...
@@ -5003,6 +5043,35 @@ Create_func_json_exists::create_2_arg(THD *thd, Item *arg1, Item *arg2)
}
Create_func_json_detailed
Create_func_json_detailed
::
s_singleton
;
Item
*
Create_func_json_detailed
::
create_2_arg
(
THD
*
thd
,
Item
*
arg1
,
Item
*
arg2
)
{
return
new
(
thd
->
mem_root
)
Item_func_json_format
(
thd
,
arg1
,
arg2
);
}
Create_func_json_loose
Create_func_json_loose
::
s_singleton
;
Item
*
Create_func_json_loose
::
create_1_arg
(
THD
*
thd
,
Item
*
arg1
)
{
return
new
(
thd
->
mem_root
)
Item_func_json_format
(
thd
,
arg1
,
Item_func_json_format
::
LOOSE
);
}
Create_func_json_compact
Create_func_json_compact
::
s_singleton
;
Item
*
Create_func_json_compact
::
create_1_arg
(
THD
*
thd
,
Item
*
arg1
)
{
return
new
(
thd
->
mem_root
)
Item_func_json_format
(
thd
,
arg1
,
Item_func_json_format
::
COMPACT
);
}
Create_func_json_valid
Create_func_json_valid
::
s_singleton
;
Item
*
...
...
@@ -6728,14 +6797,17 @@ static Native_func_registry func_array[] =
{
{
C_STRING_WITH_LEN
(
"JSON_ARRAY"
)
},
BUILDER
(
Create_func_json_array
)},
{
{
C_STRING_WITH_LEN
(
"JSON_ARRAY_APPEND"
)
},
BUILDER
(
Create_func_json_array_append
)},
{
{
C_STRING_WITH_LEN
(
"JSON_ARRAY_INSERT"
)
},
BUILDER
(
Create_func_json_array_insert
)},
{
{
C_STRING_WITH_LEN
(
"JSON_COMPACT"
)
},
BUILDER
(
Create_func_json_compact
)},
{
{
C_STRING_WITH_LEN
(
"JSON_CONTAINS"
)
},
BUILDER
(
Create_func_json_contains
)},
{
{
C_STRING_WITH_LEN
(
"JSON_CONTAINS_PATH"
)
},
BUILDER
(
Create_func_json_contains_path
)},
{
{
C_STRING_WITH_LEN
(
"JSON_DEPTH"
)
},
BUILDER
(
Create_func_json_depth
)},
{
{
C_STRING_WITH_LEN
(
"JSON_DETAILED"
)
},
BUILDER
(
Create_func_json_detailed
)},
{
{
C_STRING_WITH_LEN
(
"JSON_EXISTS"
)
},
BUILDER
(
Create_func_json_exists
)},
{
{
C_STRING_WITH_LEN
(
"JSON_EXTRACT"
)
},
BUILDER
(
Create_func_json_extract
)},
{
{
C_STRING_WITH_LEN
(
"JSON_INSERT"
)
},
BUILDER
(
Create_func_json_insert
)},
{
{
C_STRING_WITH_LEN
(
"JSON_KEYS"
)
},
BUILDER
(
Create_func_json_keys
)},
{
{
C_STRING_WITH_LEN
(
"JSON_LENGTH"
)
},
BUILDER
(
Create_func_json_length
)},
{
{
C_STRING_WITH_LEN
(
"JSON_LOOSE"
)
},
BUILDER
(
Create_func_json_loose
)},
{
{
C_STRING_WITH_LEN
(
"JSON_MERGE"
)
},
BUILDER
(
Create_func_json_merge
)},
{
{
C_STRING_WITH_LEN
(
"JSON_QUERY"
)
},
BUILDER
(
Create_func_json_query
)},
{
{
C_STRING_WITH_LEN
(
"JSON_QUOTE"
)
},
BUILDER
(
Create_func_json_quote
)},
...
...
sql/item_jsonfunc.cc
View file @
abf75821
...
...
@@ -113,6 +113,100 @@ static int st_append_escaped(String *s, const String *a)
}
static
int
json_nice
(
json_engine_t
*
je
,
String
*
nice_js
,
Item_func_json_format
::
formats
mode
)
{
int
depth
=
0
;
const
char
*
comma
,
*
colon
;
uint
comma_len
,
colon_len
;
int
first_value
=
1
;
DBUG_ASSERT
(
je
->
s
.
cs
==
nice_js
->
charset
());
if
(
mode
==
Item_func_json_format
::
LOOSE
)
{
comma
=
", "
;
comma_len
=
2
;
colon
=
"
\"
: "
;
colon_len
=
3
;
}
else
{
comma
=
","
;
comma_len
=
1
;
colon
=
"
\"
:"
;
colon_len
=
2
;
}
do
{
switch
(
je
->
state
)
{
case
JST_KEY
:
{
const
uchar
*
key_start
=
je
->
s
.
c_str
;
const
uchar
*
key_end
;
while
(
json_read_keyname_chr
(
je
)
==
0
)
key_end
=
je
->
s
.
c_str
;
if
(
je
->
s
.
error
)
goto
error
;
if
(
!
first_value
)
nice_js
->
append
(
comma
,
comma_len
);
nice_js
->
append
(
"
\"
"
,
1
);
append_simple
(
nice_js
,
key_start
,
key_end
-
key_start
);
nice_js
->
append
(
colon
,
colon_len
);
}
/* now we have key value to handle, so no 'break'. */
DBUG_ASSERT
(
je
->
state
==
JST_VALUE
);
goto
handle_value
;
case
JST_VALUE
:
if
(
!
first_value
)
nice_js
->
append
(
comma
,
comma_len
);
handle_value:
if
(
json_read_value
(
je
))
goto
error
;
if
(
json_value_scalar
(
je
))
{
if
(
append_simple
(
nice_js
,
je
->
value_begin
,
je
->
value_end
-
je
->
value_begin
))
goto
error
;
first_value
=
0
;
}
else
{
nice_js
->
append
((
je
->
value_type
==
JSON_VALUE_OBJECT
)
?
"{"
:
"["
,
1
);
first_value
=
1
;
depth
++
;
}
break
;
case
JST_OBJ_END
:
case
JST_ARRAY_END
:
depth
--
;
nice_js
->
append
((
je
->
state
==
JST_OBJ_END
)
?
"}"
:
"]"
,
1
);
first_value
=
0
;
break
;
default:
break
;
};
}
while
(
json_scan_next
(
je
)
==
0
);
return
je
->
s
.
error
;
error:
return
1
;
}
#define report_json_error(js, je, n_param) \
report_json_error_ex(js, je, func_name(), n_param, \
Sql_condition::WARN_LEVEL_WARN)
...
...
@@ -554,11 +648,11 @@ void Item_func_json_extract::fix_length_and_dec()
static
bool
path_exact
(
const
json_path_with_flags
*
paths_list
,
int
n_paths
,
const
json_path_t
*
p
)
const
json_path_t
*
p
,
enum
json_value_types
vt
)
{
for
(;
n_paths
>
0
;
n_paths
--
,
paths_list
++
)
{
if
(
json_path_compare
(
&
paths_list
->
p
,
p
)
==
0
)
if
(
json_path_compare
(
&
paths_list
->
p
,
p
,
vt
)
==
0
)
return
TRUE
;
}
return
FALSE
;
...
...
@@ -566,11 +660,11 @@ static bool path_exact(const json_path_with_flags *paths_list, int n_paths,
static
bool
path_ok
(
const
json_path_with_flags
*
paths_list
,
int
n_paths
,
const
json_path_t
*
p
)
const
json_path_t
*
p
,
enum
json_value_types
vt
)
{
for
(;
n_paths
>
0
;
n_paths
--
,
paths_list
++
)
{
if
(
json_path_compare
(
&
paths_list
->
p
,
p
)
>=
0
)
if
(
json_path_compare
(
&
paths_list
->
p
,
p
,
vt
)
>=
0
)
return
TRUE
;
}
return
FALSE
;
...
...
@@ -624,7 +718,7 @@ String *Item_func_json_extract::val_str(String *str)
while
(
json_get_path_next
(
&
je
,
&
p
)
==
0
)
{
if
(
!
path_exact
(
paths
,
arg_count
-
1
,
&
p
))
if
(
!
path_exact
(
paths
,
arg_count
-
1
,
&
p
,
je
.
value_type
))
continue
;
value
=
je
.
value_begin
;
...
...
@@ -661,10 +755,18 @@ String *Item_func_json_extract::val_str(String *str)
goto
return_null
;
}
if
(
possible_multiple_values
&&
str
->
append
(
"]"
))
if
(
possible_multiple_values
&&
str
->
append
(
"]"
,
1
))
goto
error
;
/* Out of memory. */
return
str
;
js
=
str
;
json_scan_start
(
&
je
,
js
->
charset
(),(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
tmp_js
.
length
(
0
);
tmp_js
.
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
&
tmp_js
,
Item_func_json_format
::
LOOSE
))
goto
error
;
return
&
tmp_js
;
error:
report_json_error
(
js
,
&
je
,
0
);
...
...
@@ -1153,7 +1255,7 @@ longlong Item_func_json_contains_path::val_int()
json_path_with_flags
*
c_path
=
paths
;
for
(;
n_path
>
0
;
n_path
--
,
c_path
++
)
{
if
(
json_path_compare
(
&
c_path
->
p
,
&
p
)
>=
0
)
if
(
json_path_compare
(
&
c_path
->
p
,
&
p
,
je
.
value_type
)
>=
0
)
{
if
(
mode_one
)
{
...
...
@@ -1424,7 +1526,14 @@ String *Item_func_json_array_append::val_str(String *str)
}
}
return
js
;
json_scan_start
(
&
je
,
js
->
charset
(),(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
str
,
Item_func_json_format
::
LOOSE
))
goto
js_error
;
return
str
;
js_error:
report_json_error
(
js
,
&
je
,
0
);
...
...
@@ -1558,7 +1667,14 @@ String *Item_func_json_array_insert::val_str(String *str)
}
}
return
js
;
json_scan_start
(
&
je
,
js
->
charset
(),(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
str
,
Item_func_json_format
::
LOOSE
))
goto
js_error
;
return
str
;
js_error:
report_json_error
(
js
,
&
je
,
0
);
...
...
@@ -1690,8 +1806,15 @@ String *Item_func_json_merge::val_str(String *str)
}
}
json_scan_start
(
&
je1
,
js1
->
charset
(),(
const
uchar
*
)
js1
->
ptr
(),
(
const
uchar
*
)
js1
->
ptr
()
+
js1
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js1
->
charset
());
if
(
json_nice
(
&
je1
,
str
,
Item_func_json_format
::
LOOSE
))
goto
error_return
;
null_value
=
0
;
return
js1
;
return
str
;
error_return:
if
(
je1
.
s
.
error
)
...
...
@@ -1970,6 +2093,7 @@ String *Item_func_json_insert::val_str(String *str)
{
if
(
je
.
s
.
error
)
goto
js_error
;
continue
;
}
if
(
json_read_value
(
&
je
))
...
...
@@ -1986,7 +2110,16 @@ String *Item_func_json_insert::val_str(String *str)
int
do_array_autowrap
;
if
(
mode_insert
)
do_array_autowrap
=
!
mode_replace
||
lp
->
n_item
;
{
if
(
mode_replace
)
do_array_autowrap
=
lp
->
n_item
>
0
;
else
{
if
(
lp
->
n_item
==
0
)
continue
;
do_array_autowrap
=
1
;
}
}
else
{
if
(
lp
->
n_item
)
...
...
@@ -2124,7 +2257,14 @@ String *Item_func_json_insert::val_str(String *str)
}
}
return
js
;
json_scan_start
(
&
je
,
js
->
charset
(),(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
str
,
Item_func_json_format
::
LOOSE
))
goto
js_error
;
return
str
;
js_error:
report_json_error
(
js
,
&
je
,
0
);
...
...
@@ -2300,7 +2440,14 @@ String *Item_func_json_remove::val_str(String *str)
}
}
return
js
;
json_scan_start
(
&
je
,
js
->
charset
(),(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
str
,
Item_func_json_format
::
LOOSE
))
goto
js_error
;
return
str
;
js_error:
report_json_error
(
js
,
&
je
,
0
);
...
...
@@ -2540,7 +2687,7 @@ String *Item_func_json_search::val_str(String *str)
{
if
(
json_value_scalar
(
&
je
))
{
if
((
arg_count
<
5
||
path_ok
(
paths
,
arg_count
-
4
,
&
p
))
&&
if
((
arg_count
<
5
||
path_ok
(
paths
,
arg_count
-
4
,
&
p
,
je
.
value_type
))
&&
compare_json_value_wild
(
&
je
,
s_str
)
!=
0
)
{
++
n_path_found
;
...
...
@@ -2609,3 +2756,52 @@ String *Item_json_typecast::val_str(String *str)
return
vs
;
}
const
char
*
Item_func_json_format
::
func_name
()
const
{
switch
(
fmt
)
{
case
COMPACT
:
return
"json_compact"
;
case
LOOSE
:
return
"json_loose"
;
case
DETAILED
:
return
"json_detailed"
;
default:
DBUG_ASSERT
(
0
);
};
return
""
;
}
void
Item_func_json_format
::
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
args
[
0
]
->
max_length
;
}
String
*
Item_func_json_format
::
val_str
(
String
*
str
)
{
String
*
js
=
args
[
0
]
->
val_str
(
&
tmp_js
);
json_engine_t
je
;
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
json_scan_start
(
&
je
,
js
->
charset
(),
(
const
uchar
*
)
js
->
ptr
(),
(
const
uchar
*
)
js
->
ptr
()
+
js
->
length
());
str
->
length
(
0
);
str
->
set_charset
(
js
->
charset
());
if
(
json_nice
(
&
je
,
str
,
fmt
))
{
null_value
=
1
;
report_json_error
(
js
,
&
je
,
0
);
return
0
;
}
return
str
;
}
sql/item_jsonfunc.h
View file @
abf75821
...
...
@@ -427,4 +427,30 @@ class Item_json_typecast: public Item_str_func
};
class
Item_func_json_format
:
public
Item_str_func
{
public:
enum
formats
{
NONE
,
COMPACT
,
LOOSE
,
DETAILED
};
protected:
formats
fmt
;
String
tmp_js
;
public:
Item_func_json_format
(
THD
*
thd
,
Item
*
js
,
formats
format
)
:
Item_str_func
(
thd
,
js
),
fmt
(
format
)
{}
Item_func_json_format
(
THD
*
thd
,
Item
*
js
,
Item
*
tabsize
)
:
Item_str_func
(
thd
,
js
,
tabsize
),
fmt
(
DETAILED
)
{}
const
char
*
func_name
()
const
;
void
fix_length_and_dec
();
String
*
val_str
(
String
*
str
);
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_func_json_format
>
(
thd
,
mem_root
,
this
);
}
};
#endif
/* ITEM_JSONFUNC_INCLUDED */
strings/json_lib.c
View file @
abf75821
...
...
@@ -1001,6 +1001,7 @@ enum json_path_states {
PS_LAX
,
/* Parse the 'lax' keyword. */
PS_PT
,
/* New path's step begins. */
PS_AR
,
/* Parse array step. */
PS_SAR
,
/* space after the '['. */
PS_AWD
,
/* Array wildcard. */
PS_Z
,
/* '0' (as an array item number). */
PS_INT
,
/* Parse integer (as an array item number). */
...
...
@@ -1041,7 +1042,10 @@ static int json_path_transitions[N_PATH_STATES][N_PATH_CLASSES]=
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_NOT_JSON_CHR
,
JE_BAD_CHR
},
/* AR */
{
JE_EOS
,
JE_SYN
,
PS_AWD
,
JE_SYN
,
PS_PT
,
JE_SYN
,
PS_Z
,
PS_INT
,
JE_SYN
,
JE_SYN
,
PS_AR
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
PS_INT
,
JE_SYN
,
JE_SYN
,
PS_SAR
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_NOT_JSON_CHR
,
JE_BAD_CHR
},
/* SAR */
{
JE_EOS
,
JE_SYN
,
PS_AWD
,
JE_SYN
,
PS_PT
,
JE_SYN
,
PS_Z
,
PS_INT
,
JE_SYN
,
JE_SYN
,
PS_SAR
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_NOT_JSON_CHR
,
JE_BAD_CHR
},
/* AWD */
{
JE_EOS
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
PS_PT
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
PS_AS
,
JE_SYN
,
JE_SYN
,
JE_SYN
,
...
...
@@ -1722,45 +1726,103 @@ int json_get_path_next(json_engine_t *je, json_path_t *p)
}
int
json_path_compare
(
const
json_path_t
*
a
,
const
json_path_t
*
b
)
int
json_path_parts_compare
(
const
json_path_step_t
*
a
,
const
json_path_step_t
*
a_end
,
const
json_path_step_t
*
b
,
const
json_path_step_t
*
b_end
,
enum
json_value_types
vt
)
{
const
json_path_step_t
*
sa
=
a
->
steps
+
1
;
const
json_path_step_t
*
sb
=
b
->
steps
+
1
;
if
(
a
->
last_step
-
sa
>
b
->
last_step
-
sb
)
return
-
2
;
int
res
,
res2
;
while
(
sa
<=
a
->
last_step
)
while
(
a
<=
a_end
)
{
if
(
sb
>
b
->
last_step
)
if
(
b
>
b_end
)
{
while
(
vt
!=
JSON_VALUE_ARRAY
&&
(
a
->
type
&
JSON_PATH_ARRAY_WILD
)
==
JSON_PATH_ARRAY
&&
a
->
n_item
==
0
)
{
if
(
++
a
>
a_end
)
return
0
;
}
return
-
2
;
}
DBUG_ASSERT
((
b
->
type
&
(
JSON_PATH_WILD
|
JSON_PATH_DOUBLE_WILD
))
==
0
);
if
(
!
((
sa
->
type
&
sb
->
type
)
&
JSON_PATH_KEY_OR_ARRAY
))
goto
step_failed
;
if
(
sa
->
type
&
JSON_PATH_ARRAY
)
if
(
a
->
type
&
JSON_PATH_ARRAY
)
{
if
(
!
(
sa
->
type
&
JSON_PATH_WILD
)
&&
sa
->
n_item
!=
sb
->
n_item
)
if
(
b
->
type
&
JSON_PATH_ARRAY
)
{
if
((
a
->
type
&
JSON_PATH_WILD
)
||
a
->
n_item
==
b
->
n_item
)
goto
step_fits
;
goto
step_failed
;
}
if
(
a
->
n_item
==
0
)
goto
step_fits_autowrap
;
goto
step_failed
;
}
else
/* JSON_PATH_KEY */
{
if
(
!
(
sa
->
type
&
JSON_PATH_WILD
)
&&
(
sa
->
key_end
-
sa
->
key
!=
sb
->
key_end
-
sb
->
key
||
memcmp
(
sa
->
key
,
sb
->
key
,
sa
->
key_end
-
sa
->
key
)
!=
0
))
if
(
!
(
b
->
type
&
JSON_PATH_KEY
))
goto
step_failed
;
if
(
!
(
a
->
type
&
JSON_PATH_WILD
)
&&
(
a
->
key_end
-
a
->
key
!=
b
->
key_end
-
b
->
key
||
memcmp
(
a
->
key
,
b
->
key
,
a
->
key_end
-
a
->
key
)
!=
0
))
goto
step_failed
;
}
sb
++
;
sa
++
;
continue
;
goto
step_fits
;
}
step_failed:
if
(
!
(
s
a
->
type
&
JSON_PATH_DOUBLE_WILD
))
if
(
!
(
a
->
type
&
JSON_PATH_DOUBLE_WILD
))
return
-
1
;
sb
++
;
b
++
;
continue
;
step_fits:
b
++
;
if
(
!
(
a
->
type
&
JSON_PATH_DOUBLE_WILD
))
{
a
++
;
continue
;
}
/* Double wild handling needs recursions. */
res
=
json_path_parts_compare
(
a
+
1
,
a_end
,
b
,
b_end
,
vt
);
if
(
res
==
0
)
return
0
;
res2
=
json_path_parts_compare
(
a
,
a_end
,
b
,
b_end
,
vt
);
return
(
res2
>=
0
)
?
res2
:
res
;
step_fits_autowrap:
if
(
!
(
a
->
type
&
JSON_PATH_DOUBLE_WILD
))
{
a
++
;
continue
;
}
/* Double wild handling needs recursions. */
res
=
json_path_parts_compare
(
a
+
1
,
a_end
,
b
+
1
,
b_end
,
vt
);
if
(
res
==
0
)
return
0
;
res2
=
json_path_parts_compare
(
a
,
a_end
,
b
+
1
,
b_end
,
vt
);
return
(
res2
>=
0
)
?
res2
:
res
;
}
return
sb
<=
b
->
last_step
;
return
b
<=
b_end
;
}
int
json_path_compare
(
const
json_path_t
*
a
,
const
json_path_t
*
b
,
enum
json_value_types
vt
)
{
return
json_path_parts_compare
(
a
->
steps
+
1
,
a
->
last_step
,
b
->
steps
+
1
,
b
->
last_step
,
vt
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment