Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/utils/mogrify.py
469 views
1
#!/usr/bin/env python3
2
from typing import Any
3
from typing import Dict
4
from typing import Optional
5
from typing import Sequence
6
from typing import Union
7
8
from ..mysql import converters
9
from ..mysql.constants import SERVER_STATUS
10
11
12
Encoders = converters.Encoders
13
14
15
def escape(
16
obj: Any,
17
charset: str = 'utf8',
18
mapping: Optional[Encoders] = None,
19
server_status: int = 0,
20
binary_prefix: bool = False,
21
) -> str:
22
"""
23
Escape whatever value is passed.
24
25
Non-standard, for internal use; do not use this in your applications.
26
27
"""
28
dtype = type(obj)
29
if dtype is str or isinstance(obj, str):
30
return "'{}'".format(escape_string(obj, server_status=server_status))
31
if dtype is bytes or dtype is bytearray or isinstance(obj, (bytes, bytearray)):
32
return _quote_bytes(
33
obj,
34
server_status=server_status,
35
binary_prefix=binary_prefix,
36
)
37
if mapping is None:
38
mapping = converters.encoders
39
return converters.escape_item(obj, charset, mapping=mapping)
40
41
42
def literal(
43
obj: Any,
44
charset: str = 'utf8',
45
encoders: Optional[Encoders] = None,
46
server_status: int = 0,
47
binary_prefix: bool = False,
48
) -> str:
49
"""
50
Alias for escape().
51
52
Non-standard, for internal use; do not use this in your applications.
53
54
"""
55
return escape(
56
obj, charset=charset, mapping=encoders,
57
server_status=server_status, binary_prefix=binary_prefix,
58
)
59
60
61
def escape_string(
62
s: str,
63
server_status: int = 0,
64
) -> str:
65
"""Escape a string value."""
66
if server_status & SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES:
67
return s.replace("'", "''")
68
return converters.escape_string(s)
69
70
71
def _quote_bytes(
72
s: bytes,
73
server_status: int = 0,
74
binary_prefix: bool = False,
75
) -> str:
76
if server_status & SERVER_STATUS.SERVER_STATUS_NO_BACKSLASH_ESCAPES:
77
if binary_prefix:
78
return "_binary X'{}'".format(s.hex())
79
return "X'{}'".format(s.hex())
80
return converters.escape_bytes(s)
81
82
83
def _escape_args(
84
args: Union[Sequence[Any], Dict[str, Any], None],
85
charset: str = 'utf8',
86
encoders: Optional[Encoders] = None,
87
server_status: int = 0,
88
binary_prefix: bool = False,
89
) -> Any:
90
if encoders is None:
91
encoders = converters.encoders
92
93
if isinstance(args, (tuple, list)):
94
return tuple(
95
literal(
96
arg, charset=charset, encoders=encoders,
97
server_status=server_status,
98
binary_prefix=binary_prefix,
99
) for arg in args
100
)
101
102
elif isinstance(args, dict):
103
return {
104
key: literal(
105
val, charset=charset, encoders=encoders,
106
server_status=server_status,
107
binary_prefix=binary_prefix,
108
) for (key, val) in args.items()
109
}
110
111
# If it's not a dictionary let's try escaping it anyways.
112
# Worst case it will throw a Value error
113
return escape(
114
args, charset=charset, mapping=encoders,
115
server_status=server_status, binary_prefix=binary_prefix,
116
)
117
118
119
def mogrify(
120
query: Union[str, bytes],
121
args: Union[Sequence[Any], Dict[str, Any], None] = None,
122
charset: str = 'utf8',
123
encoders: Optional[Encoders] = None,
124
server_status: int = 0,
125
binary_prefix: bool = False,
126
) -> Union[str, bytes]:
127
"""
128
Returns the exact string sent to the database by calling the execute() method.
129
130
This method follows the extension to the DB API 2.0 followed by Psycopg.
131
132
Parameters
133
----------
134
query : str
135
Query to mogrify.
136
args : Sequence[Any] or Dict[str, Any] or Any, optional
137
Parameters used with query. (optional)
138
139
Returns
140
-------
141
str : The query with argument binding applied.
142
143
"""
144
if args:
145
query = query % _escape_args(
146
args, charset=charset,
147
encoders=encoders,
148
server_status=server_status,
149
binary_prefix=binary_prefix,
150
)
151
return query
152
153