Skip to content

Commit fdfad1a

Browse files
committed
add ${} logic.
1 parent 34ab8bd commit fdfad1a

File tree

5 files changed

+65
-8
lines changed

5 files changed

+65
-8
lines changed

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,34 @@ INSERT INTO fruits (name, category, price) VALUES ('Bob', 'B', 200)
3030
refer to [test_mybatis.py](https://github.com/ralgond/mybatis-py/blob/main/test/test_mybatis.py)[test2.xml](https://github.com/ralgond/mybatis-py/blob/main/mapper/test.xml)
3131

3232
## Dynamic SQL
33+
### ${}和#{}的区别
34+
#{}是一个占位符,为prepared statement而存在,在MapperManager处理后会变成字符'?';
35+
${}表示简单的字符串替换。下面一个例子能说明它的区别:
36+
```python
37+
from mybatis import *
38+
39+
mm = MapperManager()
40+
41+
'''
42+
test.xml的内容如下:
43+
44+
<?xml version="1.0" encoding="UTF-8"?>
45+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
46+
<mapper>
47+
<select id="testStringReplace">
48+
SELECT * from fruits_${date} where id=#{id}
49+
</select>
50+
</mapper>
51+
'''
52+
mm.read_mapper_xml_file("mapper/test.xml")
53+
54+
sql, param_list = mm.select("testStringReplace", {'id':1, 'date':"20241204"})
55+
print(sql, param_list)
56+
```
57+
结果是
58+
```bash
59+
SELECT * from fruits_20241204 where id=? [1]
60+
```
61+
可以看见${date}被替换成"20241204",而#{id}替换成了'?',同时param_list中只有一个参数值为1。
62+
63+
基于安全性的考虑,为了防止SQL注入,建议只要能使用#{}就不要使用${},除非你有足够的把握。

example.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ def main():
3939
# sql, param_list = mm.select("testTrim", {'names': [1, 2, 3, 4]})
4040
# print(sql, param_list)
4141

42-
sql, param_list = mm.update("testSet", {'category': "banana", "price": 500, "name":"a"})
42+
# sql, param_list = mm.update("testSet", {'category': "banana", "price": 500, "name":"a"})
43+
# print(sql, param_list)
44+
45+
sql, param_list = mm.select("testStringReplace", {'id':1, 'date':"20241204"})
4346
print(sql, param_list)
4447

4548
# cur.execute(sql, param_list, multi=True)
@@ -49,7 +52,7 @@ def main():
4952
# res = cur.fetchall()
5053
# print(res)
5154

52-
print(globals()['A'])
55+
# print(globals()['A'])
5356

5457
if __name__ == "__main__":
5558
main()

mapper/test.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,8 @@
147147
WHERE
148148
name = #{name}
149149
</update>
150+
151+
<select id="testStringReplace">
152+
SELECT * from fruits_${date} where id=#{id}
153+
</select>
150154
</mapper>

mybatis/mapper_manager.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class MapperManager:
66
def __init__(self):
77
self.id_2_element_map = {}
88
self.param_pattern = re.compile(r"#{([a-zA-Z0-9_\-]+)}")
9+
self.replace_pattern = re.compile(r"\${([a-zA-Z0-9_\-]+)}")
910

1011
def read_mapper_xml_file(self, mapper_xml_file_path):
1112
root = et.parse(mapper_xml_file_path).getroot()
@@ -211,6 +212,16 @@ def _to_prepared_statement(self, ret, param) -> Tuple[str, list]:
211212

212213
return (ret, ret_param)
213214

215+
def _to_replace(self, ret, param) -> str:
216+
matches = self.replace_pattern.findall(ret)
217+
for match in matches:
218+
value = ""
219+
if match in param:
220+
value = param[match]
221+
ret = ret.replace("${"+match+"}", value)
222+
return ret
223+
224+
214225
def select(self, id: str, params: dict) -> Tuple[str, list]:
215226
if id not in self.id_2_element_map:
216227
raise Exception("Missing id")
@@ -226,7 +237,9 @@ def select(self, id: str, params: dict) -> Tuple[str, list]:
226237
ret += self.parse_element(child, param0)
227238
ret += child.tail
228239

229-
return self._to_prepared_statement(ret, params)
240+
sql, sql_param = self._to_prepared_statement(ret, params)
241+
sql = self._to_replace(sql, params)
242+
return (sql, sql_param)
230243

231244
def update(self, id: str, params: dict) -> Tuple[str, list]:
232245
if id not in self.id_2_element_map:
@@ -243,7 +256,9 @@ def update(self, id: str, params: dict) -> Tuple[str, list]:
243256
ret += self.parse_element(child, param0)
244257
ret += child.tail
245258

246-
return self._to_prepared_statement(ret, params)
259+
sql, sql_param = self._to_prepared_statement(ret, params)
260+
sql = self._to_replace(sql, params)
261+
return (sql, sql_param)
247262

248263
def delete(self, id: str, params: dict) -> Tuple[str, list]:
249264
if id not in self.id_2_element_map:
@@ -260,7 +275,9 @@ def delete(self, id: str, params: dict) -> Tuple[str, list]:
260275
ret += self.parse_element(child, param0)
261276
ret += child.tail
262277

263-
return self._to_prepared_statement(ret, params)
278+
sql, sql_param = self._to_prepared_statement(ret, params)
279+
sql = self._to_replace(sql, params)
280+
return (sql, sql_param)
264281

265282
def insert(self, id: str, params: dict) -> Tuple[str, list]:
266283
if id not in self.id_2_element_map:
@@ -277,4 +294,6 @@ def insert(self, id: str, params: dict) -> Tuple[str, list]:
277294
ret += self.parse_element(child, param0)
278295
ret += child.tail
279296

280-
return self._to_prepared_statement(ret, params)
297+
sql, sql_param = self._to_prepared_statement(ret, params)
298+
sql = self._to_replace(sql, params)
299+
return (sql, sql_param)

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='mybatis',
5-
version='0.0.1',
5+
version='0.0.2',
66
description='A python ORM like mybatis.',
77
long_description=open('README.md').read(),
88
long_description_content_type='text/markdown', # 如果你使用的是Markdown格式的README
@@ -31,4 +31,4 @@
3131
license='Apache-2.0',
3232
test_require=['pytest'],
3333
tests_require=['pytest'],
34-
)
34+
)

0 commit comments

Comments
 (0)