singlestoredb 1.12.1__tar.gz → 1.12.3__tar.gz
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.
Potentially problematic release.
This version of singlestoredb might be problematic. Click here for more details.
- {singlestoredb-1.12.1/singlestoredb.egg-info → singlestoredb-1.12.3}/PKG-INFO +1 -1
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/accel.c +0 -7
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/setup.cfg +1 -1
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/__init__.py +1 -1
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/config.py +1 -1
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/asgi.py +20 -3
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/signature.py +8 -1
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/utils.py +27 -19
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/http/connection.py +9 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/files.py +1 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/cursors.py +8 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_basics.py +69 -0
- singlestoredb-1.12.3/singlestoredb/tests/test_fusion.py +1524 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3/singlestoredb.egg-info}/PKG-INFO +1 -1
- singlestoredb-1.12.1/singlestoredb/tests/test_fusion.py +0 -716
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/LICENSE +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/README.md +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/setup.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/ai/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/ai/embeddings.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/alchemy/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_cloud_functions.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_config.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_connection_info.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_dashboards.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_process.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_stdout_supress.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/apps/_uvicorn_util.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/auth.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/connection.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/converters.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/exceptions.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/decorator.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/dtypes.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/arrow.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/json.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/mmap.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/rowdat_1.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/functions/ext/utils.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/graphql.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handler.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/export.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/files.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/job.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/models.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/stage.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/handlers/workspace.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/registry.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/fusion/result.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/http/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/magics/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/magics/run_personal.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/magics/run_shared.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/billing_usage.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/cluster.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/export.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/job.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/manager.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/organization.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/region.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/utils.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/management/workspace.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/_auth.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/charset.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/connection.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/CLIENT.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/COMMAND.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/CR.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/ER.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/EXTENDED_TYPE.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/FIELD_TYPE.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/FLAG.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/SERVER_STATUS.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/VECTOR_TYPE.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/constants/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/converters.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/err.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/optionfile.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/protocol.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/base.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/conftest.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_DictCursor.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_SSCursor.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_basic.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_connection.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_converters.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_cursor.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_err.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_issues.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_load_local.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_nextset.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/test_optionfile.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/mysql/times.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/notebook/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/notebook/_objects.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/notebook/_portal.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/py.typed +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/pytest.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/server/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/server/docker.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/server/free_tier.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/empty.sql +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/ext_funcs/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/local_infile.csv +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test.ipynb +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test.sql +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test2.ipynb +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test2.sql +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_config.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_connection.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_dbapi.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_exceptions.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_ext_func.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_ext_func_data.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_http.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_management.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_plugin.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_results.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_types.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_udf.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/test_xdict.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/tests/utils.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/types.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/config.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/convert_rows.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/debug.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/dtypes.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/events.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/mogrify.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/results.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb/utils/xdict.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb.egg-info/SOURCES.txt +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb.egg-info/dependency_links.txt +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb.egg-info/entry_points.txt +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb.egg-info/requires.txt +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/singlestoredb.egg-info/top_level.txt +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/sqlx/__init__.py +0 -0
- {singlestoredb-1.12.1 → singlestoredb-1.12.3}/sqlx/magic.py +0 -0
|
@@ -2179,9 +2179,6 @@ static PyObject *load_rowdat_1_numpy(PyObject *self, PyObject *args, PyObject *k
|
|
|
2179
2179
|
|
|
2180
2180
|
// Get number of columns
|
|
2181
2181
|
n_cols = PyObject_Length(py_colspec);
|
|
2182
|
-
if (n_cols == 0) {
|
|
2183
|
-
goto error;
|
|
2184
|
-
}
|
|
2185
2182
|
|
|
2186
2183
|
// Determine column types
|
|
2187
2184
|
ctypes = calloc(sizeof(int), n_cols);
|
|
@@ -3979,10 +3976,6 @@ static PyObject *load_rowdat_1(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
3979
3976
|
end = data + (unsigned long long)length;
|
|
3980
3977
|
|
|
3981
3978
|
colspec_l = PyObject_Length(py_colspec);
|
|
3982
|
-
if (colspec_l == 0) {
|
|
3983
|
-
goto error;
|
|
3984
|
-
}
|
|
3985
|
-
|
|
3986
3979
|
ctypes = malloc(sizeof(int) * colspec_l);
|
|
3987
3980
|
|
|
3988
3981
|
for (i = 0; i < colspec_l; i++) {
|
|
@@ -69,6 +69,12 @@ try:
|
|
|
69
69
|
except ImportError:
|
|
70
70
|
has_cloudpickle = False
|
|
71
71
|
|
|
72
|
+
try:
|
|
73
|
+
from pydantic import BaseModel
|
|
74
|
+
has_pydantic = True
|
|
75
|
+
except ImportError:
|
|
76
|
+
has_pydantic = False
|
|
77
|
+
|
|
72
78
|
|
|
73
79
|
logger = utils.get_logger('singlestoredb.functions.ext.asgi')
|
|
74
80
|
|
|
@@ -138,13 +144,24 @@ def get_func_names(funcs: str) -> List[Tuple[str, str]]:
|
|
|
138
144
|
|
|
139
145
|
|
|
140
146
|
def as_tuple(x: Any) -> Any:
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
"""Convert object to tuple."""
|
|
148
|
+
if has_pydantic and isinstance(x, BaseModel):
|
|
149
|
+
return tuple(x.model_dump().values())
|
|
143
150
|
if dataclasses.is_dataclass(x):
|
|
144
151
|
return dataclasses.astuple(x)
|
|
145
152
|
return x
|
|
146
153
|
|
|
147
154
|
|
|
155
|
+
def as_list_of_tuples(x: Any) -> Any:
|
|
156
|
+
"""Convert object to a list of tuples."""
|
|
157
|
+
if isinstance(x, (list, tuple)) and len(x) > 0:
|
|
158
|
+
if has_pydantic and isinstance(x[0], BaseModel):
|
|
159
|
+
return [tuple(y.model_dump().values()) for y in x]
|
|
160
|
+
if dataclasses.is_dataclass(x[0]):
|
|
161
|
+
return [dataclasses.astuple(y) for y in x]
|
|
162
|
+
return x
|
|
163
|
+
|
|
164
|
+
|
|
148
165
|
def make_func(
|
|
149
166
|
name: str,
|
|
150
167
|
func: Callable[..., Any],
|
|
@@ -183,7 +200,7 @@ def make_func(
|
|
|
183
200
|
out_ids: List[int] = []
|
|
184
201
|
out = []
|
|
185
202
|
for i, res in zip(row_ids, func_map(func, rows)):
|
|
186
|
-
out.extend(
|
|
203
|
+
out.extend(as_list_of_tuples(res))
|
|
187
204
|
out_ids.extend([row_ids[i]] * (len(out)-len(out_ids)))
|
|
188
205
|
return out_ids, out
|
|
189
206
|
|
|
@@ -6,6 +6,8 @@ import numbers
|
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
8
|
import string
|
|
9
|
+
import sys
|
|
10
|
+
import types
|
|
9
11
|
import typing
|
|
10
12
|
from typing import Any
|
|
11
13
|
from typing import Callable
|
|
@@ -32,6 +34,11 @@ except ImportError:
|
|
|
32
34
|
from . import dtypes as dt
|
|
33
35
|
from ..mysql.converters import escape_item # type: ignore
|
|
34
36
|
|
|
37
|
+
if sys.version_info >= (3, 10):
|
|
38
|
+
_UNION_TYPES = {typing.Union, types.UnionType}
|
|
39
|
+
else:
|
|
40
|
+
_UNION_TYPES = {typing.Union}
|
|
41
|
+
|
|
35
42
|
|
|
36
43
|
array_types: Tuple[Any, ...]
|
|
37
44
|
|
|
@@ -211,7 +218,7 @@ def simplify_dtype(dtype: Any) -> List[Any]:
|
|
|
211
218
|
args = []
|
|
212
219
|
|
|
213
220
|
# Flatten Unions
|
|
214
|
-
if origin
|
|
221
|
+
if origin in _UNION_TYPES:
|
|
215
222
|
for x in typing.get_args(dtype):
|
|
216
223
|
args.extend(simplify_dtype(x))
|
|
217
224
|
|
|
@@ -199,59 +199,65 @@ def get_deployment(
|
|
|
199
199
|
"""
|
|
200
200
|
manager = get_workspace_manager()
|
|
201
201
|
|
|
202
|
+
#
|
|
203
|
+
# Search for deployment by name
|
|
204
|
+
#
|
|
202
205
|
deployment_name = params.get('deployment_name') or \
|
|
203
206
|
(params.get('in_deployment') or {}).get('deployment_name') or \
|
|
204
207
|
(params.get('group') or {}).get('deployment_name') or \
|
|
205
208
|
((params.get('in') or {}).get('in_group') or {}).get('deployment_name') or \
|
|
206
209
|
((params.get('in') or {}).get('in_deployment') or {}).get('deployment_name')
|
|
210
|
+
|
|
207
211
|
if deployment_name:
|
|
212
|
+
# Standard workspace group
|
|
208
213
|
workspace_groups = [
|
|
209
214
|
x for x in manager.workspace_groups
|
|
210
215
|
if x.name == deployment_name
|
|
211
216
|
]
|
|
212
217
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
filtered_starter_workspaces = [
|
|
216
|
-
x for x in manager.starter_workspaces
|
|
217
|
-
if x.name == deployment_name
|
|
218
|
-
]
|
|
219
|
-
|
|
220
|
-
if not filtered_starter_workspaces:
|
|
221
|
-
raise KeyError(
|
|
222
|
-
f'no deployment found with name: {deployment_name}',
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
starter_workspaces = filtered_starter_workspaces
|
|
218
|
+
if len(workspace_groups) == 1:
|
|
219
|
+
return workspace_groups[0]
|
|
226
220
|
|
|
227
|
-
|
|
221
|
+
elif len(workspace_groups) > 1:
|
|
228
222
|
ids = ', '.join(x.id for x in workspace_groups)
|
|
229
223
|
raise ValueError(
|
|
230
224
|
f'more than one workspace group with given name was found: {ids}',
|
|
231
225
|
)
|
|
232
226
|
|
|
233
|
-
|
|
227
|
+
# Starter workspace
|
|
228
|
+
starter_workspaces = [
|
|
229
|
+
x for x in manager.starter_workspaces
|
|
230
|
+
if x.name == deployment_name
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
if len(starter_workspaces) == 1:
|
|
234
|
+
return starter_workspaces[0]
|
|
235
|
+
|
|
236
|
+
elif len(starter_workspaces) > 1:
|
|
234
237
|
ids = ', '.join(x.id for x in starter_workspaces)
|
|
235
238
|
raise ValueError(
|
|
236
239
|
f'more than one starter workspace with given name was found: {ids}',
|
|
237
240
|
)
|
|
238
241
|
|
|
239
|
-
|
|
240
|
-
return workspace_groups[0]
|
|
241
|
-
else:
|
|
242
|
-
return starter_workspaces[0]
|
|
242
|
+
raise KeyError(f'no deployment found with name: {deployment_name}')
|
|
243
243
|
|
|
244
|
+
#
|
|
245
|
+
# Search for deployment by ID
|
|
246
|
+
#
|
|
244
247
|
deployment_id = params.get('deployment_id') or \
|
|
245
248
|
(params.get('in_deployment') or {}).get('deployment_id') or \
|
|
246
249
|
(params.get('group') or {}).get('deployment_id') or \
|
|
247
250
|
((params.get('in') or {}).get('in_group') or {}).get('deployment_id') or \
|
|
248
251
|
((params.get('in') or {}).get('in_deployment') or {}).get('deployment_id')
|
|
252
|
+
|
|
249
253
|
if deployment_id:
|
|
250
254
|
try:
|
|
255
|
+
# Standard workspace group
|
|
251
256
|
return manager.get_workspace_group(deployment_id)
|
|
252
257
|
except ManagementError as exc:
|
|
253
258
|
if exc.errno == 404:
|
|
254
259
|
try:
|
|
260
|
+
# Starter workspace
|
|
255
261
|
return manager.get_starter_workspace(deployment_id)
|
|
256
262
|
except ManagementError as exc:
|
|
257
263
|
if exc.errno == 404:
|
|
@@ -260,6 +266,7 @@ def get_deployment(
|
|
|
260
266
|
else:
|
|
261
267
|
raise
|
|
262
268
|
|
|
269
|
+
# Use workspace group from environment
|
|
263
270
|
if os.environ.get('SINGLESTOREDB_WORKSPACE_GROUP'):
|
|
264
271
|
try:
|
|
265
272
|
return manager.get_workspace_group(
|
|
@@ -273,6 +280,7 @@ def get_deployment(
|
|
|
273
280
|
)
|
|
274
281
|
raise
|
|
275
282
|
|
|
283
|
+
# Use cluster from environment
|
|
276
284
|
if os.environ.get('SINGLESTOREDB_CLUSTER'):
|
|
277
285
|
try:
|
|
278
286
|
return manager.get_starter_workspace(
|
|
@@ -43,6 +43,12 @@ try:
|
|
|
43
43
|
except ImportError:
|
|
44
44
|
has_shapely = False
|
|
45
45
|
|
|
46
|
+
try:
|
|
47
|
+
import pydantic
|
|
48
|
+
has_pydantic = True
|
|
49
|
+
except ImportError:
|
|
50
|
+
has_pydantic = False
|
|
51
|
+
|
|
46
52
|
from .. import connection
|
|
47
53
|
from .. import fusion
|
|
48
54
|
from .. import types
|
|
@@ -533,6 +539,9 @@ class Cursor(connection.Cursor):
|
|
|
533
539
|
self._expect_results = True
|
|
534
540
|
sql_type = 'query'
|
|
535
541
|
|
|
542
|
+
if has_pydantic and isinstance(params, pydantic.BaseModel):
|
|
543
|
+
params = params.model_dump()
|
|
544
|
+
|
|
536
545
|
self._validate_param_subs(oper, params)
|
|
537
546
|
|
|
538
547
|
handler = fusion.get_handler(oper)
|
|
@@ -8,6 +8,12 @@ from ..utils import results
|
|
|
8
8
|
from ..utils.debug import log_query
|
|
9
9
|
from ..utils.results import get_schema
|
|
10
10
|
|
|
11
|
+
try:
|
|
12
|
+
from pydantic import BaseModel
|
|
13
|
+
has_pydantic = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
has_pydantic = False
|
|
16
|
+
|
|
11
17
|
|
|
12
18
|
#: Regular expression for :meth:`Cursor.executemany`.
|
|
13
19
|
#: executemany only supports simple bulk insert.
|
|
@@ -149,6 +155,8 @@ class Cursor(BaseCursor):
|
|
|
149
155
|
return tuple(literal(arg) for arg in args)
|
|
150
156
|
elif dtype is dict or isinstance(args, dict):
|
|
151
157
|
return {key: literal(val) for (key, val) in args.items()}
|
|
158
|
+
elif has_pydantic and isinstance(args, BaseModel):
|
|
159
|
+
return {key: literal(val) for (key, val) in args.model_dump().items()}
|
|
152
160
|
# If it's not a dictionary let's try escaping it anyways.
|
|
153
161
|
# Worst case it will throw a Value error
|
|
154
162
|
return conn.escape(args)
|
|
@@ -6,6 +6,7 @@ import decimal
|
|
|
6
6
|
import math
|
|
7
7
|
import os
|
|
8
8
|
import unittest
|
|
9
|
+
from typing import Optional
|
|
9
10
|
|
|
10
11
|
from requests.exceptions import InvalidJSONError
|
|
11
12
|
|
|
@@ -28,6 +29,12 @@ try:
|
|
|
28
29
|
except ImportError:
|
|
29
30
|
has_pygeos = False
|
|
30
31
|
|
|
32
|
+
try:
|
|
33
|
+
import pydantic
|
|
34
|
+
has_pydantic = True
|
|
35
|
+
except ImportError:
|
|
36
|
+
has_pydantic = False
|
|
37
|
+
|
|
31
38
|
import singlestoredb as s2
|
|
32
39
|
from . import utils
|
|
33
40
|
# import traceback
|
|
@@ -1255,6 +1262,68 @@ class TestBasics(unittest.TestCase):
|
|
|
1255
1262
|
except Exception:
|
|
1256
1263
|
pass
|
|
1257
1264
|
|
|
1265
|
+
def test_pydantic(self):
|
|
1266
|
+
if not has_pydantic:
|
|
1267
|
+
self.skipTest('Test requires pydantic')
|
|
1268
|
+
|
|
1269
|
+
tblname = 'foo_' + str(id(self))
|
|
1270
|
+
|
|
1271
|
+
class FooData(pydantic.BaseModel):
|
|
1272
|
+
x: Optional[int]
|
|
1273
|
+
y: Optional[float]
|
|
1274
|
+
z: Optional[str] = None
|
|
1275
|
+
|
|
1276
|
+
self.cur.execute(f'''
|
|
1277
|
+
CREATE TABLE {tblname}(
|
|
1278
|
+
x INT,
|
|
1279
|
+
y DOUBLE,
|
|
1280
|
+
z TEXT
|
|
1281
|
+
)
|
|
1282
|
+
''')
|
|
1283
|
+
|
|
1284
|
+
self.cur.execute(
|
|
1285
|
+
f'INSERT INTO {tblname}(x, y) VALUES (%(x)s, %(y)s)',
|
|
1286
|
+
FooData(x=2, y=3.23),
|
|
1287
|
+
)
|
|
1288
|
+
|
|
1289
|
+
self.cur.execute('SELECT * FROM ' + tblname)
|
|
1290
|
+
|
|
1291
|
+
assert list(sorted(self.cur.fetchall())) == \
|
|
1292
|
+
list(sorted([(2, 3.23, None)]))
|
|
1293
|
+
|
|
1294
|
+
self.cur.executemany(
|
|
1295
|
+
f'INSERT INTO {tblname}(x) VALUES (%(x)s)',
|
|
1296
|
+
[FooData(x=3, y=3.12), FooData(x=10, y=100.11)],
|
|
1297
|
+
)
|
|
1298
|
+
|
|
1299
|
+
self.cur.execute('SELECT * FROM ' + tblname)
|
|
1300
|
+
|
|
1301
|
+
assert list(sorted(self.cur.fetchall())) == \
|
|
1302
|
+
list(
|
|
1303
|
+
sorted([
|
|
1304
|
+
(2, 3.23, None),
|
|
1305
|
+
(3, None, None),
|
|
1306
|
+
(10, None, None),
|
|
1307
|
+
]),
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
def test_charset(self):
|
|
1311
|
+
with s2.connect(database=type(self).dbname) as conn:
|
|
1312
|
+
with conn.cursor() as cur:
|
|
1313
|
+
cur.execute('''
|
|
1314
|
+
select json_extract_string('{"foo":"😀"}', "bar");
|
|
1315
|
+
''')
|
|
1316
|
+
|
|
1317
|
+
if 'http' in self.conn.driver:
|
|
1318
|
+
self.skipTest('Charset is not use in HTTP interface')
|
|
1319
|
+
|
|
1320
|
+
with self.assertRaises(s2.OperationalError):
|
|
1321
|
+
with s2.connect(database=type(self).dbname, charset='utf8') as conn:
|
|
1322
|
+
with conn.cursor() as cur:
|
|
1323
|
+
cur.execute('''
|
|
1324
|
+
select json_extract_string('{"foo":"😀"}', "bar");
|
|
1325
|
+
''')
|
|
1326
|
+
|
|
1258
1327
|
|
|
1259
1328
|
if __name__ == '__main__':
|
|
1260
1329
|
import nose2
|