summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2017-02-06 06:47:48 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2017-02-06 06:47:48 +0400
commitabf7582112645ef8decc549eb662a07072b5cd32 (patch)
tree1082c1f2c8e32120cee647e0cd0374bd67c37b37 /strings
parente51b015fc354ec40c8430d4f4ea6346bc9a8e07b (diff)
downloadmariadb-git-abf7582112645ef8decc549eb662a07072b5cd32.tar.gz
MDEV-11557 port MySQL-5.7 JSON tests to MariaDB.
Fixes for issues found.
Diffstat (limited to 'strings')
-rw-r--r--strings/json_lib.c110
1 files changed, 86 insertions, 24 deletions
diff --git a/strings/json_lib.c b/strings/json_lib.c
index 20dc1b3d718..cc3a8adf0aa 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -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 (!(sa->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);
+}
+