singlestoredb 1.16.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- singlestoredb/__init__.py +75 -0
- singlestoredb/ai/__init__.py +2 -0
- singlestoredb/ai/chat.py +139 -0
- singlestoredb/ai/embeddings.py +128 -0
- singlestoredb/alchemy/__init__.py +90 -0
- singlestoredb/apps/__init__.py +3 -0
- singlestoredb/apps/_cloud_functions.py +90 -0
- singlestoredb/apps/_config.py +72 -0
- singlestoredb/apps/_connection_info.py +18 -0
- singlestoredb/apps/_dashboards.py +47 -0
- singlestoredb/apps/_process.py +32 -0
- singlestoredb/apps/_python_udfs.py +100 -0
- singlestoredb/apps/_stdout_supress.py +30 -0
- singlestoredb/apps/_uvicorn_util.py +36 -0
- singlestoredb/auth.py +245 -0
- singlestoredb/config.py +484 -0
- singlestoredb/connection.py +1487 -0
- singlestoredb/converters.py +950 -0
- singlestoredb/docstring/__init__.py +33 -0
- singlestoredb/docstring/attrdoc.py +126 -0
- singlestoredb/docstring/common.py +230 -0
- singlestoredb/docstring/epydoc.py +267 -0
- singlestoredb/docstring/google.py +412 -0
- singlestoredb/docstring/numpydoc.py +562 -0
- singlestoredb/docstring/parser.py +100 -0
- singlestoredb/docstring/py.typed +1 -0
- singlestoredb/docstring/rest.py +256 -0
- singlestoredb/docstring/tests/__init__.py +1 -0
- singlestoredb/docstring/tests/_pydoctor.py +21 -0
- singlestoredb/docstring/tests/test_epydoc.py +729 -0
- singlestoredb/docstring/tests/test_google.py +1007 -0
- singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
- singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
- singlestoredb/docstring/tests/test_parser.py +248 -0
- singlestoredb/docstring/tests/test_rest.py +547 -0
- singlestoredb/docstring/tests/test_util.py +70 -0
- singlestoredb/docstring/util.py +141 -0
- singlestoredb/exceptions.py +120 -0
- singlestoredb/functions/__init__.py +16 -0
- singlestoredb/functions/decorator.py +201 -0
- singlestoredb/functions/dtypes.py +1793 -0
- singlestoredb/functions/ext/__init__.py +1 -0
- singlestoredb/functions/ext/arrow.py +375 -0
- singlestoredb/functions/ext/asgi.py +2133 -0
- singlestoredb/functions/ext/json.py +420 -0
- singlestoredb/functions/ext/mmap.py +413 -0
- singlestoredb/functions/ext/rowdat_1.py +724 -0
- singlestoredb/functions/ext/timer.py +89 -0
- singlestoredb/functions/ext/utils.py +218 -0
- singlestoredb/functions/signature.py +1578 -0
- singlestoredb/functions/typing/__init__.py +41 -0
- singlestoredb/functions/typing/numpy.py +20 -0
- singlestoredb/functions/typing/pandas.py +2 -0
- singlestoredb/functions/typing/polars.py +2 -0
- singlestoredb/functions/typing/pyarrow.py +2 -0
- singlestoredb/functions/utils.py +421 -0
- singlestoredb/fusion/__init__.py +11 -0
- singlestoredb/fusion/graphql.py +213 -0
- singlestoredb/fusion/handler.py +916 -0
- singlestoredb/fusion/handlers/__init__.py +0 -0
- singlestoredb/fusion/handlers/export.py +525 -0
- singlestoredb/fusion/handlers/files.py +690 -0
- singlestoredb/fusion/handlers/job.py +660 -0
- singlestoredb/fusion/handlers/models.py +250 -0
- singlestoredb/fusion/handlers/stage.py +502 -0
- singlestoredb/fusion/handlers/utils.py +324 -0
- singlestoredb/fusion/handlers/workspace.py +956 -0
- singlestoredb/fusion/registry.py +249 -0
- singlestoredb/fusion/result.py +399 -0
- singlestoredb/http/__init__.py +27 -0
- singlestoredb/http/connection.py +1267 -0
- singlestoredb/magics/__init__.py +34 -0
- singlestoredb/magics/run_personal.py +137 -0
- singlestoredb/magics/run_shared.py +134 -0
- singlestoredb/management/__init__.py +9 -0
- singlestoredb/management/billing_usage.py +148 -0
- singlestoredb/management/cluster.py +462 -0
- singlestoredb/management/export.py +295 -0
- singlestoredb/management/files.py +1102 -0
- singlestoredb/management/inference_api.py +105 -0
- singlestoredb/management/job.py +887 -0
- singlestoredb/management/manager.py +373 -0
- singlestoredb/management/organization.py +226 -0
- singlestoredb/management/region.py +169 -0
- singlestoredb/management/utils.py +423 -0
- singlestoredb/management/workspace.py +1927 -0
- singlestoredb/mysql/__init__.py +177 -0
- singlestoredb/mysql/_auth.py +298 -0
- singlestoredb/mysql/charset.py +214 -0
- singlestoredb/mysql/connection.py +2032 -0
- singlestoredb/mysql/constants/CLIENT.py +38 -0
- singlestoredb/mysql/constants/COMMAND.py +32 -0
- singlestoredb/mysql/constants/CR.py +78 -0
- singlestoredb/mysql/constants/ER.py +474 -0
- singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
- singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
- singlestoredb/mysql/constants/FLAG.py +15 -0
- singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
- singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
- singlestoredb/mysql/constants/__init__.py +0 -0
- singlestoredb/mysql/converters.py +271 -0
- singlestoredb/mysql/cursors.py +896 -0
- singlestoredb/mysql/err.py +92 -0
- singlestoredb/mysql/optionfile.py +20 -0
- singlestoredb/mysql/protocol.py +450 -0
- singlestoredb/mysql/tests/__init__.py +19 -0
- singlestoredb/mysql/tests/base.py +126 -0
- singlestoredb/mysql/tests/conftest.py +37 -0
- singlestoredb/mysql/tests/test_DictCursor.py +132 -0
- singlestoredb/mysql/tests/test_SSCursor.py +141 -0
- singlestoredb/mysql/tests/test_basic.py +452 -0
- singlestoredb/mysql/tests/test_connection.py +851 -0
- singlestoredb/mysql/tests/test_converters.py +58 -0
- singlestoredb/mysql/tests/test_cursor.py +141 -0
- singlestoredb/mysql/tests/test_err.py +16 -0
- singlestoredb/mysql/tests/test_issues.py +514 -0
- singlestoredb/mysql/tests/test_load_local.py +75 -0
- singlestoredb/mysql/tests/test_nextset.py +88 -0
- singlestoredb/mysql/tests/test_optionfile.py +27 -0
- singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
- singlestoredb/mysql/times.py +23 -0
- singlestoredb/notebook/__init__.py +16 -0
- singlestoredb/notebook/_objects.py +213 -0
- singlestoredb/notebook/_portal.py +352 -0
- singlestoredb/py.typed +0 -0
- singlestoredb/pytest.py +352 -0
- singlestoredb/server/__init__.py +0 -0
- singlestoredb/server/docker.py +452 -0
- singlestoredb/server/free_tier.py +267 -0
- singlestoredb/tests/__init__.py +0 -0
- singlestoredb/tests/alltypes.sql +307 -0
- singlestoredb/tests/alltypes_no_nulls.sql +208 -0
- singlestoredb/tests/empty.sql +0 -0
- singlestoredb/tests/ext_funcs/__init__.py +702 -0
- singlestoredb/tests/local_infile.csv +3 -0
- singlestoredb/tests/test.ipynb +18 -0
- singlestoredb/tests/test.sql +680 -0
- singlestoredb/tests/test2.ipynb +18 -0
- singlestoredb/tests/test2.sql +1 -0
- singlestoredb/tests/test_basics.py +1332 -0
- singlestoredb/tests/test_config.py +318 -0
- singlestoredb/tests/test_connection.py +3103 -0
- singlestoredb/tests/test_dbapi.py +27 -0
- singlestoredb/tests/test_exceptions.py +45 -0
- singlestoredb/tests/test_ext_func.py +1472 -0
- singlestoredb/tests/test_ext_func_data.py +1101 -0
- singlestoredb/tests/test_fusion.py +1527 -0
- singlestoredb/tests/test_http.py +288 -0
- singlestoredb/tests/test_management.py +1599 -0
- singlestoredb/tests/test_plugin.py +33 -0
- singlestoredb/tests/test_results.py +171 -0
- singlestoredb/tests/test_types.py +132 -0
- singlestoredb/tests/test_udf.py +737 -0
- singlestoredb/tests/test_udf_returns.py +459 -0
- singlestoredb/tests/test_vectorstore.py +51 -0
- singlestoredb/tests/test_xdict.py +333 -0
- singlestoredb/tests/utils.py +141 -0
- singlestoredb/types.py +373 -0
- singlestoredb/utils/__init__.py +0 -0
- singlestoredb/utils/config.py +950 -0
- singlestoredb/utils/convert_rows.py +69 -0
- singlestoredb/utils/debug.py +13 -0
- singlestoredb/utils/dtypes.py +205 -0
- singlestoredb/utils/events.py +65 -0
- singlestoredb/utils/mogrify.py +151 -0
- singlestoredb/utils/results.py +585 -0
- singlestoredb/utils/xdict.py +425 -0
- singlestoredb/vectorstore.py +192 -0
- singlestoredb/warnings.py +5 -0
- singlestoredb-1.16.1.dist-info/METADATA +165 -0
- singlestoredb-1.16.1.dist-info/RECORD +183 -0
- singlestoredb-1.16.1.dist-info/WHEEL +5 -0
- singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
- singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
- singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
- sqlx/__init__.py +4 -0
- sqlx/magic.py +113 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
|
|
3
|
+
import singlestoredb.mysql as sv
|
|
4
|
+
from singlestoredb.connection import build_params
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
DBNAME_BASE = 'singlestoredb__test_%s_%s_%s_%s_' % \
|
|
8
|
+
(
|
|
9
|
+
*platform.python_version_tuple()[:2],
|
|
10
|
+
platform.system(), platform.machine(),
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def pytest_sessionstart() -> None:
|
|
15
|
+
params = build_params()
|
|
16
|
+
conn = sv.connect( # type: ignore
|
|
17
|
+
host=params['host'], user=params['user'],
|
|
18
|
+
passwd=params['password'], port=params['port'],
|
|
19
|
+
buffered=params['buffered'],
|
|
20
|
+
)
|
|
21
|
+
cur = conn.cursor()
|
|
22
|
+
cur.execute(f'CREATE DATABASE IF NOT EXISTS {DBNAME_BASE}1')
|
|
23
|
+
cur.execute(f'CREATE DATABASE IF NOT EXISTS {DBNAME_BASE}2')
|
|
24
|
+
conn.close()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def pytest_sessionfinish() -> None:
|
|
28
|
+
params = build_params()
|
|
29
|
+
conn = sv.connect( # type: ignore
|
|
30
|
+
host=params['host'], user=params['user'],
|
|
31
|
+
passwd=params['password'], port=params['port'],
|
|
32
|
+
buffered=params['buffered'],
|
|
33
|
+
)
|
|
34
|
+
cur = conn.cursor()
|
|
35
|
+
cur.execute(f'DROP DATABASE {DBNAME_BASE}1')
|
|
36
|
+
cur.execute(f'DROP DATABASE {DBNAME_BASE}2')
|
|
37
|
+
conn.close()
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
import datetime
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
import singlestoredb.mysql.cursors as cursors
|
|
8
|
+
from singlestoredb.mysql.tests import base
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestDictCursor(base.PyMySQLTestCase):
|
|
12
|
+
|
|
13
|
+
bob = {'name': 'bob', 'age': 21, 'DOB': datetime.datetime(1990, 2, 6, 23, 4, 56)}
|
|
14
|
+
jim = {'name': 'jim', 'age': 56, 'DOB': datetime.datetime(1955, 5, 9, 13, 12, 45)}
|
|
15
|
+
fred = {'name': 'fred', 'age': 100, 'DOB': datetime.datetime(1911, 9, 12, 1, 1, 1)}
|
|
16
|
+
|
|
17
|
+
cursor_type = cursors.DictCursor
|
|
18
|
+
|
|
19
|
+
def setUp(self):
|
|
20
|
+
super(TestDictCursor, self).setUp()
|
|
21
|
+
self.conn = conn = self.connect(cursorclass=self.cursor_type)
|
|
22
|
+
c = conn.cursor()
|
|
23
|
+
|
|
24
|
+
# create a table ane some data to query
|
|
25
|
+
with warnings.catch_warnings():
|
|
26
|
+
warnings.filterwarnings('ignore')
|
|
27
|
+
c.execute('drop table if exists dictcursor')
|
|
28
|
+
# include in filterwarnings since for unbuffered dict cursor warning
|
|
29
|
+
# for lack of table will only be propagated at start of next execute() call
|
|
30
|
+
c.execute(
|
|
31
|
+
"""CREATE TABLE dictcursor (name char(20), age int , DOB datetime)""",
|
|
32
|
+
)
|
|
33
|
+
data = [
|
|
34
|
+
('bob', 21, '1990-02-06 23:04:56'),
|
|
35
|
+
('jim', 56, '1955-05-09 13:12:45'),
|
|
36
|
+
('fred', 100, '1911-09-12 01:01:01'),
|
|
37
|
+
]
|
|
38
|
+
c.executemany('insert into dictcursor values (%s,%s,%s)', data)
|
|
39
|
+
|
|
40
|
+
def tearDown(self):
|
|
41
|
+
c = self.conn.cursor()
|
|
42
|
+
c.execute('drop table dictcursor')
|
|
43
|
+
super(TestDictCursor, self).tearDown()
|
|
44
|
+
|
|
45
|
+
def _ensure_cursor_expired(self, cursor):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def test_DictCursor(self):
|
|
49
|
+
bob, jim, fred = self.bob.copy(), self.jim.copy(), self.fred.copy()
|
|
50
|
+
# all assert test compare to the structure as would come out from MySQLdb
|
|
51
|
+
conn = self.conn
|
|
52
|
+
c = conn.cursor()
|
|
53
|
+
|
|
54
|
+
# try an update which should return no rows
|
|
55
|
+
c.execute("update dictcursor set age=20 where name='bob'")
|
|
56
|
+
bob['age'] = 20
|
|
57
|
+
# pull back the single row dict for bob and check
|
|
58
|
+
c.execute("SELECT * from dictcursor where name='bob'")
|
|
59
|
+
r = c.fetchone()
|
|
60
|
+
self.assertEqual(bob, r, 'fetchone via DictCursor failed')
|
|
61
|
+
self._ensure_cursor_expired(c)
|
|
62
|
+
|
|
63
|
+
# same again, but via fetchall => tuple)
|
|
64
|
+
c.execute("SELECT * from dictcursor where name='bob'")
|
|
65
|
+
r = c.fetchall()
|
|
66
|
+
self.assertEqual(
|
|
67
|
+
[bob], r, 'fetch a 1 row result via fetchall failed via DictCursor',
|
|
68
|
+
)
|
|
69
|
+
# same test again but iterate over the
|
|
70
|
+
c.execute("SELECT * from dictcursor where name='bob'")
|
|
71
|
+
for r in c:
|
|
72
|
+
self.assertEqual(
|
|
73
|
+
bob, r, 'fetch a 1 row result via iteration failed via DictCursor',
|
|
74
|
+
)
|
|
75
|
+
# get all 3 row via fetchall
|
|
76
|
+
c.execute('SELECT * from dictcursor ORDER BY name')
|
|
77
|
+
r = c.fetchall()
|
|
78
|
+
self.assertEqual([bob, fred, jim], r, 'fetchall failed via DictCursor')
|
|
79
|
+
# same test again but do a list comprehension
|
|
80
|
+
c.execute('SELECT * from dictcursor ORDER BY name')
|
|
81
|
+
r = list(c)
|
|
82
|
+
self.assertEqual([bob, fred, jim], r, 'DictCursor should be iterable')
|
|
83
|
+
# get all 2 row via fetchmany
|
|
84
|
+
c.execute('SELECT * from dictcursor ORDER BY name')
|
|
85
|
+
r = c.fetchmany(2)
|
|
86
|
+
self.assertEqual([bob, fred], r, 'fetchmany failed via DictCursor')
|
|
87
|
+
self._ensure_cursor_expired(c)
|
|
88
|
+
|
|
89
|
+
@pytest.mark.skip('Custom cursors are only available when creating a connection')
|
|
90
|
+
def test_custom_dict(self):
|
|
91
|
+
class MyDict(dict):
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
class MyDictCursor(self.cursor_type):
|
|
95
|
+
dict_type = MyDict
|
|
96
|
+
|
|
97
|
+
keys = ['name', 'age', 'DOB']
|
|
98
|
+
bob = MyDict([(k, self.bob[k]) for k in keys])
|
|
99
|
+
jim = MyDict([(k, self.jim[k]) for k in keys])
|
|
100
|
+
fred = MyDict([(k, self.fred[k]) for k in keys])
|
|
101
|
+
|
|
102
|
+
cur = self.conn.cursor(MyDictCursor)
|
|
103
|
+
cur.execute("SELECT * FROM dictcursor WHERE name='bob'")
|
|
104
|
+
r = cur.fetchone()
|
|
105
|
+
self.assertEqual(bob, r, 'fetchone() returns MyDictCursor')
|
|
106
|
+
self._ensure_cursor_expired(cur)
|
|
107
|
+
|
|
108
|
+
cur.execute('SELECT * FROM dictcursor ORDER BY name')
|
|
109
|
+
r = cur.fetchall()
|
|
110
|
+
self.assertEqual([bob, fred, jim], r, 'fetchall failed via MyDictCursor')
|
|
111
|
+
|
|
112
|
+
cur.execute('SELECT * FROM dictcursor ORDER BY name')
|
|
113
|
+
r = list(cur)
|
|
114
|
+
self.assertEqual([bob, fred, jim], r, 'list failed via MyDictCursor')
|
|
115
|
+
|
|
116
|
+
cur.execute('SELECT * FROM dictcursor ORDER BY name')
|
|
117
|
+
r = cur.fetchmany(2)
|
|
118
|
+
self.assertEqual([bob, fred], r, 'list failed via MyDictCursor')
|
|
119
|
+
self._ensure_cursor_expired(cur)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class TestSSDictCursor(TestDictCursor):
|
|
123
|
+
cursor_type = cursors.SSDictCursor
|
|
124
|
+
|
|
125
|
+
def _ensure_cursor_expired(self, cursor):
|
|
126
|
+
list(cursor.fetchall_unbuffered())
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == '__main__':
|
|
130
|
+
import unittest
|
|
131
|
+
|
|
132
|
+
unittest.main()
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
import singlestoredb.mysql as sv
|
|
6
|
+
from singlestoredb.mysql.tests import base
|
|
7
|
+
import singlestoredb.mysql.cursors as cursors
|
|
8
|
+
from singlestoredb.mysql.constants import CLIENT
|
|
9
|
+
except Exception:
|
|
10
|
+
# For local testing from top-level directory, without installing
|
|
11
|
+
sys.path.append('../../..')
|
|
12
|
+
import singlestoredb.mysql as sv # noqa: F401
|
|
13
|
+
from singlestoredb.mysql.tests import base
|
|
14
|
+
import singlestoredb.mysql.cursors as cursors
|
|
15
|
+
from singlestoredb.mysql.constants import CLIENT
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TestSSCursor(base.PyMySQLTestCase):
|
|
19
|
+
|
|
20
|
+
def test_SSCursor(self):
|
|
21
|
+
# affected_rows = 18446744073709551615
|
|
22
|
+
affected_rows = -1
|
|
23
|
+
|
|
24
|
+
conn = self.connect(
|
|
25
|
+
client_flag=CLIENT.MULTI_STATEMENTS,
|
|
26
|
+
cursorclass=cursors.SSCursor,
|
|
27
|
+
)
|
|
28
|
+
data = [
|
|
29
|
+
('America', '', 'America/Jamaica'),
|
|
30
|
+
('America', '', 'America/Los_Angeles'),
|
|
31
|
+
('America', '', 'America/Lima'),
|
|
32
|
+
('America', '', 'America/New_York'),
|
|
33
|
+
('America', '', 'America/Menominee'),
|
|
34
|
+
('America', '', 'America/Havana'),
|
|
35
|
+
('America', '', 'America/El_Salvador'),
|
|
36
|
+
('America', '', 'America/Costa_Rica'),
|
|
37
|
+
('America', '', 'America/Denver'),
|
|
38
|
+
('America', '', 'America/Detroit'),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
cursor = conn.cursor()
|
|
42
|
+
|
|
43
|
+
cursor.execute('DROP TABLE IF EXISTS tz_data')
|
|
44
|
+
|
|
45
|
+
# Create table
|
|
46
|
+
cursor.execute(
|
|
47
|
+
'CREATE TABLE tz_data ('
|
|
48
|
+
'region VARCHAR(64),'
|
|
49
|
+
'zone VARCHAR(64),'
|
|
50
|
+
'name VARCHAR(64))',
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
conn.begin()
|
|
54
|
+
# Test INSERT
|
|
55
|
+
for i in data:
|
|
56
|
+
cursor.execute('INSERT INTO tz_data VALUES (%s, %s, %s)', i)
|
|
57
|
+
self.assertEqual(conn.affected_rows(), 1, 'affected_rows does not match')
|
|
58
|
+
conn.commit()
|
|
59
|
+
|
|
60
|
+
# Test fetchone()
|
|
61
|
+
iter = 0
|
|
62
|
+
cursor.execute('SELECT * FROM tz_data')
|
|
63
|
+
while True:
|
|
64
|
+
row = cursor.fetchone()
|
|
65
|
+
if row is None:
|
|
66
|
+
break
|
|
67
|
+
iter += 1
|
|
68
|
+
|
|
69
|
+
# Test cursor.rowcount
|
|
70
|
+
self.assertEqual(
|
|
71
|
+
cursor.rowcount,
|
|
72
|
+
affected_rows,
|
|
73
|
+
'cursor.rowcount != %s' % (str(affected_rows)),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Test cursor.rownumber
|
|
77
|
+
self.assertEqual(
|
|
78
|
+
cursor.rownumber, iter, 'cursor.rowcount != %s' % (str(iter)),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Test row came out the same as it went in
|
|
82
|
+
self.assertEqual((row in data), True, 'Row not found in source data')
|
|
83
|
+
|
|
84
|
+
# Test fetchall
|
|
85
|
+
cursor.execute('SELECT * FROM tz_data')
|
|
86
|
+
self.assertEqual(
|
|
87
|
+
len(cursor.fetchall()),
|
|
88
|
+
len(data),
|
|
89
|
+
'fetchall failed. Number of rows does not match',
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Test fetchmany
|
|
93
|
+
cursor.execute('SELECT * FROM tz_data')
|
|
94
|
+
self.assertEqual(
|
|
95
|
+
len(cursor.fetchmany(2)),
|
|
96
|
+
2,
|
|
97
|
+
'fetchmany failed. Number of rows does not match',
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# So MySQLdb won't throw "Commands out of sync"
|
|
101
|
+
while True:
|
|
102
|
+
res = cursor.fetchone()
|
|
103
|
+
if res is None:
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
# Test update, affected_rows()
|
|
107
|
+
cursor.execute('UPDATE tz_data SET zone = %s', ['Foo'])
|
|
108
|
+
conn.commit()
|
|
109
|
+
self.assertEqual(
|
|
110
|
+
cursor.rowcount,
|
|
111
|
+
len(data),
|
|
112
|
+
'Update failed. affected_rows != %s' % (str(len(data))),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Test executemany
|
|
116
|
+
cursor.executemany('INSERT INTO tz_data VALUES (%s, %s, %s)', data)
|
|
117
|
+
self.assertEqual(
|
|
118
|
+
cursor.rowcount,
|
|
119
|
+
len(data),
|
|
120
|
+
'executemany failed. cursor.rowcount != %s' % (str(len(data))),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Test multiple datasets
|
|
124
|
+
cursor.execute('SELECT 1; SELECT 2; SELECT 3')
|
|
125
|
+
self.assertListEqual(list(cursor), [(1,)])
|
|
126
|
+
self.assertTrue(cursor.nextset())
|
|
127
|
+
self.assertListEqual(list(cursor), [(2,)])
|
|
128
|
+
self.assertTrue(cursor.nextset())
|
|
129
|
+
self.assertListEqual(list(cursor), [(3,)])
|
|
130
|
+
self.assertFalse(cursor.nextset())
|
|
131
|
+
|
|
132
|
+
cursor.execute('DROP TABLE IF EXISTS tz_data')
|
|
133
|
+
cursor.close()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = ['TestSSCursor']
|
|
137
|
+
|
|
138
|
+
if __name__ == '__main__':
|
|
139
|
+
import unittest
|
|
140
|
+
|
|
141
|
+
unittest.main()
|