Skip to content

Commit 8e23a7b

Browse files
authored
GG-32725 IGNITE-14211 Remove existing cache requirement from SQL API (#26)
(cherry picked from commit 672a767)
1 parent 629174d commit 8e23a7b

6 files changed

Lines changed: 102 additions & 36 deletions

File tree

pygridgain/api/sql.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -284,36 +284,31 @@ def sql_fields(
284284
Performs SQL fields query.
285285
286286
:param conn: connection to GridGain server,
287-
:param cache: name or ID of the cache,
287+
:param cache: name or ID of the cache. If zero, then schema is used.
288288
:param query_str: SQL query string,
289289
:param page_size: cursor page size,
290290
:param query_args: (optional) query arguments. List of values or
291291
(value, type hint) tuples,
292-
:param schema: (optional) schema for the query. Defaults to `PUBLIC`,
292+
:param schema: schema for the query.
293293
:param statement_type: (optional) statement type. Can be:
294294
295295
* StatementType.ALL − any type (default),
296296
* StatementType.SELECT − select,
297297
* StatementType.UPDATE − update.
298298
299-
:param distributed_joins: (optional) distributed joins. Defaults to False,
299+
:param distributed_joins: (optional) distributed joins.
300300
:param local: (optional) pass True if this query should be executed
301-
on local node only. Defaults to False,
301+
on local node only.
302302
:param replicated_only: (optional) whether query contains only
303-
replicated tables or not. Defaults to False,
304-
:param enforce_join_order: (optional) enforce join order. Defaults
305-
to False,
303+
replicated tables or not.
304+
:param enforce_join_order: (optional) enforce join order.
306305
:param collocated: (optional) whether your data is co-located or not.
307-
Defaults to False,
308-
:param lazy: (optional) lazy query execution. Defaults to False,
306+
:param lazy: (optional) lazy query execution.
309307
:param include_field_names: (optional) include field names in result.
310-
Defaults to False,
311-
:param max_rows: (optional) query-wide maximum of rows. Defaults to -1
312-
(all rows),
308+
:param max_rows: (optional) query-wide maximum of rows.
313309
:param timeout: (optional) non-negative timeout value in ms. Zero disables
314-
timeout (default),
310+
timeout.
315311
:param binary: (optional) pass True to keep the value in binary form.
316-
False by default,
317312
:param query_id: (optional) a value generated by client and returned as-is
318313
in response.query_id. When the parameter is omitted, a random value
319314
is generated,

pygridgain/client.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
BinaryTypeError, CacheError, ReconnectError, SQLError, connection_errors,
5959
)
6060
from .utils import (
61-
capitalize, entity_id, schema_id, process_delimiter,
61+
cache_id, capitalize, entity_id, schema_id, process_delimiter,
6262
status_to_exception, is_iterable,
6363
)
6464
from .binary import GenericObjectMeta
@@ -514,13 +514,14 @@ def get_cache_names(self) -> list:
514514
return cache_get_names(self.random_node)
515515

516516
def sql(
517-
self, query_str: str, page_size: int = 1024, query_args: Iterable = None,
518-
schema: Union[int, str] = 'PUBLIC',
517+
self, query_str: str, page_size: int = 1024,
518+
query_args: Iterable = None, schema: str = 'PUBLIC',
519519
statement_type: int = 0, distributed_joins: bool = False,
520520
local: bool = False, replicated_only: bool = False,
521521
enforce_join_order: bool = False, collocated: bool = False,
522522
lazy: bool = False, include_field_names: bool = False,
523523
max_rows: int = -1, timeout: int = 0,
524+
cache: Union[int, str, Cache] = None
524525
):
525526
"""
526527
Runs an SQL query and returns its result.
@@ -554,6 +555,8 @@ def sql(
554555
(all rows),
555556
:param timeout: (optional) non-negative timeout value in ms.
556557
Zero disables timeout (default),
558+
:param cache (optional) Name or ID of the cache to use to infer schema.
559+
If set, 'schema' argument is ignored,
557560
:return: generator with result rows as a lists. If
558561
`include_field_names` was set, the first row will hold field names.
559562
"""
@@ -581,10 +584,13 @@ def generate_result(value):
581584

582585
conn = self.random_node
583586

584-
schema = self.get_cache(schema)
587+
c_id = cache.cache_id if isinstance(cache, Cache) else cache_id(cache)
588+
589+
if c_id != 0:
590+
schema = None
591+
585592
result = sql_fields(
586-
conn, schema.cache_id, query_str,
587-
page_size, query_args, schema.name,
593+
conn, c_id, query_str, page_size, query_args, schema,
588594
statement_type, distributed_joins, local, replicated_only,
589595
enforce_join_order, collocated, lazy, include_field_names,
590596
max_rows, timeout,

pygridgain/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ def hashcode(data: Union[str, bytes, bytearray, memoryview]) -> int:
9191
:param data: UTF-8-encoded string identifier of binary buffer or byte array
9292
:return: hash code.
9393
"""
94+
if data is None:
95+
return 0
96+
9497
if isinstance(data, str):
9598
"""
9699
For strings we iterate over code point which are of the int type

tests/test_binary.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@
6464

6565

6666
def test_sql_read_as_binary(client):
67-
68-
client.get_or_create_cache(scheme_name)
6967
client.sql(drop_query)
7068

7169
# create table
@@ -93,9 +91,6 @@ def test_sql_read_as_binary(client):
9391

9492

9593
def test_sql_write_as_binary(client):
96-
97-
client.get_or_create_cache(scheme_name)
98-
9994
# configure cache as an SQL table
10095
type_name = table_cache_name
10196

tests/test_cache_class.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ def test_cache_remove(client):
6262

6363

6464
def test_cache_get(client):
65-
client.get_or_create_cache('my_cache')
66-
67-
my_cache = client.get_cache('my_cache')
65+
my_cache = client.get_or_create_cache('my_cache')
6866
assert my_cache.settings[PROP_NAME] == 'my_cache'
6967
my_cache.destroy()
7068

tests/test_sql.py

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
from datetime import datetime
1717

1818
import pytest
19+
from pygridgain.exceptions import SQLError
1920

2021
from pygridgain.api import (
2122
sql_fields, sql_fields_cursor_get_page,
2223
sql, sql_cursor_get_page,
2324
cache_get_configuration,
2425
)
26+
from pygridgain.datatypes.cache_config import CacheMode
2527
from pygridgain.datatypes.prop_codes import *
2628
from pygridgain.utils import entity_id
2729
from pygridgain.binary import unwrap_binary
@@ -60,9 +62,10 @@ def test_sql(client):
6062

6163
result = sql_fields(
6264
conn,
63-
'PUBLIC',
65+
0,
6466
create_query,
6567
page_size,
68+
schema='PUBLIC',
6669
include_field_names=True
6770
)
6871
assert result.status == 0, result.message
@@ -71,9 +74,10 @@ def test_sql(client):
7174
fname, lname, grade = data_line
7275
result = sql_fields(
7376
conn,
74-
'PUBLIC',
77+
0,
7578
insert_query,
7679
page_size,
80+
schema='PUBLIC',
7781
query_args=[i, fname, lname, grade],
7882
include_field_names=True
7983
)
@@ -109,7 +113,7 @@ def test_sql(client):
109113
assert data.type_id == entity_id(binary_type_name)
110114

111115
# repeat cleanup
112-
result = sql_fields(conn, 'PUBLIC', drop_query, page_size)
116+
result = sql_fields(conn, 0, drop_query, page_size, schema='PUBLIC')
113117
assert result.status == 0
114118

115119

@@ -122,9 +126,10 @@ def test_sql_fields(client):
122126

123127
result = sql_fields(
124128
conn,
125-
'PUBLIC',
129+
0,
126130
create_query,
127131
page_size,
132+
schema='PUBLIC',
128133
include_field_names=True
129134
)
130135
assert result.status == 0, result.message
@@ -133,19 +138,21 @@ def test_sql_fields(client):
133138
fname, lname, grade = data_line
134139
result = sql_fields(
135140
conn,
136-
'PUBLIC',
141+
0,
137142
insert_query,
138143
page_size,
144+
schema='PUBLIC',
139145
query_args=[i, fname, lname, grade],
140146
include_field_names=True
141147
)
142148
assert result.status == 0, result.message
143149

144150
result = sql_fields(
145151
conn,
146-
'PUBLIC',
152+
0,
147153
select_query,
148154
page_size,
155+
schema='PUBLIC',
149156
include_field_names=True
150157
)
151158
assert result.status == 0
@@ -160,7 +167,7 @@ def test_sql_fields(client):
160167
assert result.value['more'] is False
161168

162169
# repeat cleanup
163-
result = sql_fields(conn, 'PUBLIC', drop_query, page_size)
170+
result = sql_fields(conn, 0, drop_query, page_size, schema='PUBLIC')
164171
assert result.status == 0
165172

166173

@@ -177,7 +184,7 @@ def test_long_multipage_query(client):
177184

178185
client.sql('DROP TABLE LongMultipageQuery IF EXISTS')
179186

180-
client.sql("CREATE TABLE LongMultiPageQuery (%s, %s)" % \
187+
client.sql("CREATE TABLE LongMultiPageQuery (%s, %s)" %
181188
(fields[0] + " INT(11) PRIMARY KEY", ",".join(map(lambda f: f + " INT(11)", fields[1:]))))
182189

183190
for id in range(1, 21):
@@ -216,3 +223,65 @@ def test_server_in_different_timezone(start_ignite_server, start_client, timezon
216223
client.close()
217224
finally:
218225
kill_process_tree(server.pid)
226+
227+
228+
def test_sql_not_create_cache_with_schema(client):
229+
with pytest.raises(SQLError, match=r".*Cache does not exist.*"):
230+
client.sql(schema=None, cache='NOT_EXISTING', query_str='select * from NotExisting')
231+
232+
233+
def test_sql_not_create_cache_with_cache(client):
234+
with pytest.raises(SQLError, match=r".*Failed to set schema.*"):
235+
client.sql(schema='NOT_EXISTING', query_str='select * from NotExisting')
236+
237+
238+
def test_query_with_cache(client):
239+
test_key = 42
240+
test_value = 'Lorem ipsum'
241+
242+
cache_name = test_query_with_cache.__name__.upper()
243+
schema_name = f'{cache_name}_schema'.upper()
244+
table_name = f'{cache_name}_table'.upper()
245+
246+
cache = client.create_cache({
247+
PROP_NAME: cache_name,
248+
PROP_SQL_SCHEMA: schema_name,
249+
PROP_CACHE_MODE: CacheMode.PARTITIONED,
250+
PROP_QUERY_ENTITIES: [
251+
{
252+
'table_name': table_name,
253+
'key_field_name': 'KEY',
254+
'value_field_name': 'VALUE',
255+
'key_type_name': 'java.lang.Long',
256+
'value_type_name': 'java.lang.String',
257+
'query_indexes': [],
258+
'field_name_aliases': [],
259+
'query_fields': [
260+
{
261+
'name': 'KEY',
262+
'type_name': 'java.lang.Long',
263+
'is_key_field': True,
264+
'is_notnull_constraint_field': True,
265+
},
266+
{
267+
'name': 'VALUE',
268+
'type_name': 'java.lang.String',
269+
},
270+
],
271+
},
272+
],
273+
})
274+
275+
cache.put(test_key, test_value)
276+
277+
args_to_check = [
278+
('schema', schema_name),
279+
('cache', cache),
280+
('cache', cache.name),
281+
('cache', cache.cache_id)
282+
]
283+
284+
for param, value in args_to_check:
285+
page = client.sql(f'select value from {table_name}', **{param: value})
286+
received = next(page)[0]
287+
assert test_value == received

0 commit comments

Comments
 (0)