1# mysql/json.py
2# Copyright (C) 2005-2019 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: http://www.opensource.org/licenses/mit-license.php
7
8from __future__ import absolute_import
9
10from ... import types as sqltypes
11
12
13class JSON(sqltypes.JSON):
14    """MySQL JSON type.
15
16    MySQL supports JSON as of version 5.7.  Note that MariaDB does **not**
17    support JSON at the time of this writing.
18
19    The :class:`.mysql.JSON` type supports persistence of JSON values
20    as well as the core index operations provided by :class:`.types.JSON`
21    datatype, by adapting the operations to render the ``JSON_EXTRACT``
22    function at the database level.
23
24    .. versionadded:: 1.1
25
26    """
27
28    pass
29
30
31class _FormatTypeMixin(object):
32    def _format_value(self, value):
33        raise NotImplementedError()
34
35    def bind_processor(self, dialect):
36        super_proc = self.string_bind_processor(dialect)
37
38        def process(value):
39            value = self._format_value(value)
40            if super_proc:
41                value = super_proc(value)
42            return value
43
44        return process
45
46    def literal_processor(self, dialect):
47        super_proc = self.string_literal_processor(dialect)
48
49        def process(value):
50            value = self._format_value(value)
51            if super_proc:
52                value = super_proc(value)
53            return value
54
55        return process
56
57
58class JSONIndexType(_FormatTypeMixin, sqltypes.JSON.JSONIndexType):
59    def _format_value(self, value):
60        if isinstance(value, int):
61            value = "$[%s]" % value
62        else:
63            value = '$."%s"' % value
64        return value
65
66
67class JSONPathType(_FormatTypeMixin, sqltypes.JSON.JSONPathType):
68    def _format_value(self, value):
69        return "$%s" % (
70            "".join(
71                [
72                    "[%s]" % elem if isinstance(elem, int) else '."%s"' % elem
73                    for elem in value
74                ]
75            )
76        )
77