Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/tests/utils.py
469 views
1
#!/usr/bin/env python
2
# type: ignore
3
"""Utilities for testing."""
4
import os
5
import uuid
6
from typing import Any
7
from typing import Dict
8
from urllib.parse import urlparse
9
10
import singlestoredb as s2
11
from singlestoredb.connection import build_params
12
13
14
def apply_template(content: str, vars: Dict[str, Any]) -> str:
15
for k, v in vars.items():
16
key = '{{%s}}' % k
17
if key in content:
18
content = content.replace(key, v)
19
return content
20
21
22
def load_sql(sql_file: str) -> str:
23
"""
24
Load a file containing SQL code.
25
26
Parameters
27
----------
28
sql_file : str
29
Name of the SQL file to load.
30
31
Returns
32
-------
33
(str, bool)
34
Name of database created for SQL file and a boolean indicating
35
whether the database already existed (meaning that it should not
36
be deleted when tests are finished).
37
38
"""
39
dbname = None
40
41
# Use an existing database name if given.
42
if 'SINGLESTOREDB_URL' in os.environ:
43
dbname = build_params(host=os.environ['SINGLESTOREDB_URL']).get('database')
44
elif 'SINGLESTOREDB_HOST' in os.environ:
45
dbname = build_params(host=os.environ['SINGLESTOREDB_HOST']).get('database')
46
elif 'SINGLESTOREDB_DATABASE' in os.environ:
47
dbname = os.environ['SINGLESTOREDB_DATBASE']
48
49
# If no database name was specified, use initializer URL if given.
50
# HTTP can't change databases, so you can't initialize from HTTP
51
# while also creating a database.
52
args = {'local_infile': True}
53
if not dbname and 'SINGLESTOREDB_INIT_DB_URL' in os.environ:
54
args['host'] = os.environ['SINGLESTOREDB_INIT_DB_URL']
55
56
http_port = 0
57
if 'SINGLESTOREDB_URL' in os.environ:
58
url = os.environ['SINGLESTOREDB_URL']
59
if url.startswith('http:') or url.startswith('https:'):
60
urlp = urlparse(url)
61
if urlp.port:
62
http_port = urlp.port
63
64
if 'SINGLESTOREDB_HTTP_PORT' in os.environ:
65
http_port = int(os.environ['SINGLESTOREDB_HTTP_PORT'])
66
67
dbexisted = bool(dbname)
68
69
template_vars = dict(DATABASE_NAME=dbname, TEST_PATH=os.path.dirname(sql_file))
70
71
# Always use the default driver since not all operations are
72
# permitted in the HTTP API.
73
with open(sql_file, 'r') as infile:
74
with s2.connect(**args) as conn:
75
with conn.cursor() as cur:
76
try:
77
cur.execute('SET GLOBAL default_partitions_per_leaf=2')
78
cur.execute('SET GLOBAL log_file_size_partitions=1048576')
79
cur.execute('SET GLOBAL log_file_size_ref_dbs=1048576')
80
except s2.OperationalError:
81
pass
82
83
if not dbname:
84
dbname = 'TEST_{}'.format(uuid.uuid4()).replace('-', '_')
85
cur.execute(f'CREATE DATABASE {dbname};')
86
cur.execute(f'USE {dbname};')
87
88
template_vars['DATABASE_NAME'] = dbname
89
90
# Execute lines in SQL.
91
for cmd in infile.read().split(';\n'):
92
cmd = apply_template(cmd.strip(), template_vars)
93
if cmd:
94
cmd += ';'
95
cur.execute(cmd)
96
97
elif not conn.driver.startswith('http'):
98
cur.execute(f'USE {dbname};')
99
100
# Start HTTP server as needed.
101
if http_port and not conn.driver.startswith('http'):
102
cur.execute(f'SET GLOBAL HTTP_PROXY_PORT={http_port};')
103
cur.execute('SET GLOBAL HTTP_API=ON;')
104
cur.execute('RESTART PROXY;')
105
106
return dbname, dbexisted
107
108
109
def drop_database(name: str) -> None:
110
"""Drop a database with the given name."""
111
if name:
112
args = {}
113
if 'SINGLESTOREDB_INIT_DB_URL' in os.environ:
114
args['host'] = os.environ['SINGLESTOREDB_INIT_DB_URL']
115
with s2.connect(**args) as conn:
116
with conn.cursor() as cur:
117
cur.execute(f'DROP DATABASE {name};')
118
119
120
def create_user(name: str, password: str, dbname: str) -> None:
121
"""Create a user for the test database."""
122
if name:
123
args = {}
124
if 'SINGLESTOREDB_INIT_DB_URL' in os.environ:
125
args['host'] = os.environ['SINGLESTOREDB_INIT_DB_URL']
126
with s2.connect(**args) as conn:
127
with conn.cursor() as cur:
128
cur.execute(f'DROP USER IF EXISTS {name};')
129
cur.execute(f'CREATE USER "{name}"@"%" IDENTIFIED BY "{password}"')
130
cur.execute(f'GRANT ALL ON {dbname}.* to "{name}"@"%"')
131
132
133
def drop_user(name: str) -> None:
134
"""Drop a database with the given name."""
135
if name:
136
args = {}
137
if 'SINGLESTOREDB_INIT_DB_URL' in os.environ:
138
args['host'] = os.environ['SINGLESTOREDB_INIT_DB_URL']
139
with s2.connect(**args) as conn:
140
with conn.cursor() as cur:
141
cur.execute(f'DROP USER IF EXISTS {name};')
142
143