Skip to content

Commit e7c39b6

Browse files
authored
[API-305] Add SQL documentation (#409)
* Add SQL documentation Added similar documentation to the IMDG Reference Manual for the SQL feature. Modified examples and some parts of the documentation to make it suit the Python client. * use ffffff instead of mmmmmm and remove impossible microsecond offset from timezone string format
1 parent 8e44f09 commit e7c39b6

File tree

2 files changed

+299
-0
lines changed

2 files changed

+299
-0
lines changed

docs/features.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ features:
2424
- Transactional Queue
2525
- Transactional List
2626
- Transactional Set
27+
- SQL
2728
- Query (Predicates)
2829
- Entry Processor
2930
- Built-in Predicates

docs/using_python_client_with_hazelcast_imdg.rst

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,304 @@ the entry processor in the ``Map`` methods. See the following example.
13461346
13471347
print(distributed_map.get("key")) # Outputs 'processed'
13481348
1349+
SQL
1350+
---
1351+
1352+
The SQL service provided by Hazelcast Python client allows you to query
1353+
data stored in ``Map`` declaratively.
1354+
1355+
.. warning::
1356+
1357+
The SQL feature is currently in beta. The compatibility between versions
1358+
is not guaranteed. API might change between versions without notice.
1359+
While in beta, the SQL feature is tested against the same major versions
1360+
of the client and the server.
1361+
1362+
**Example: How to Query a Map using SQL**
1363+
1364+
Consider that we have a map called ``emp`` that contains values of type
1365+
``Employee``:
1366+
1367+
.. code:: python
1368+
1369+
class Employee(Portable):
1370+
def __init__(self, name=None, age=None):
1371+
self.name = name
1372+
self.age = age
1373+
1374+
def write_portable(self, writer):
1375+
writer.write_string("name", self.name)
1376+
writer.write_int("age", self.age)
1377+
1378+
def read_portable(self, reader):
1379+
self.name = reader.read_string("name")
1380+
self.age = reader.read_int("age")
1381+
1382+
def get_factory_id(self):
1383+
return 1
1384+
1385+
def get_class_id(self):
1386+
return 1
1387+
1388+
The following code prints names of the employees whose age is less than 30:
1389+
1390+
.. code:: python
1391+
1392+
result = client.sql.execute("SELECT name FROM emp WHERE age < ?", 30)
1393+
1394+
for row in result:
1395+
name = row.get_object("name")
1396+
print(name)
1397+
1398+
1399+
Querying Map
1400+
~~~~~~~~~~~~
1401+
1402+
The following subsections describe how you can access Hazelcast ``Map`` objects
1403+
and perform queries on them.
1404+
1405+
**Names**
1406+
1407+
The SQL service exposes ``Map`` objects as tables in the predefined
1408+
``partitioned`` schema using exact names. This schema is in the SQL service
1409+
search path so that you can access the ``Map`` objects with or without the
1410+
schema name.
1411+
1412+
Schema and table names are case-sensitive; you can access the ``employee`` map,
1413+
for example, as ``employee`` or ``partitioned.employee``, but not as
1414+
``Employee``:
1415+
1416+
.. code:: sql
1417+
1418+
SELECT * FROM employee
1419+
SELECT * FROM partitioned.employee
1420+
1421+
**Fields**
1422+
1423+
The SQL service resolves fields accessible from the SQL automatically. The
1424+
service reads the first local entry pair of the ``Map`` to construct the list
1425+
of fields. If the ``Map`` does not have local entries on the member where the
1426+
query is started, then the list of fields cannot be resolved, and an exception
1427+
is thrown.
1428+
1429+
Field names are case-sensitive.
1430+
1431+
**Key and Value Objects**
1432+
1433+
A ``Map`` entry consists of a key and a value. These are accessible through
1434+
the ``__key`` and ``this`` aliases. The following query returns the keys and
1435+
values of all entries in a map:
1436+
1437+
.. code:: sql
1438+
1439+
SELECT __key, this FROM employee
1440+
1441+
**Key and Value Fields**
1442+
1443+
You may also access the nested fields of a key or a value. The list of exposed
1444+
fields depends on the serialization format, as described below:
1445+
1446+
- For :ref:`Portable<serialization:Portable Serialization>` objects, the fields
1447+
that are written in the
1448+
:func:`write_portable<hazelcast.serialization.api.Portable.write_portable>`
1449+
method are exposed using their exact names.
1450+
- For
1451+
:ref:`IdentifiedDataSerializable<serialization:IdentifiedDataSerializable Serialization>`
1452+
objects, the object is deserialized if needed and then analyzed using the
1453+
reflection mechanism (on the server-side). Only public fields and getters
1454+
are taken into account. See the `IMDG Reference Manual
1455+
<https://docs.hazelcast.com/imdg/latest/sql/querying-imap.html#key-and-value-fields>`__
1456+
for details.
1457+
1458+
.. note::
1459+
1460+
You cannot query JSON fields in SQL. If you want to query JSON, see
1461+
:ref:`using_python_client_with_hazelcast_imdg:Querying with JSON Strings`
1462+
section.
1463+
1464+
1465+
Consider the ``Employee`` class from the example above; the SQL service can
1466+
access the following fields:
1467+
1468+
==== =======
1469+
Name Type
1470+
==== =======
1471+
name VARCHAR
1472+
age INTEGER
1473+
==== =======
1474+
1475+
Together with the key and value objects, you may query the following fields
1476+
from the map:
1477+
1478+
.. code:: sql
1479+
1480+
SELECT __key, this, name, age FROM employee
1481+
1482+
If both the key and value have fields with the same name, then the field of
1483+
the value is exposed.
1484+
1485+
**"SELECT *" Queries**
1486+
1487+
You may use the ``SELECT * FROM <table>`` syntax to get all the table fields.
1488+
1489+
The ``__key`` and ``this`` fields are returned by the ``SELECT *`` queries if
1490+
they do not have nested fields. For the ``employee`` map, the following query
1491+
does not return the ``this`` field, because the value has nested fields
1492+
``name`` and ``age``:
1493+
1494+
.. code:: sql
1495+
1496+
-- Returns __key, name, age
1497+
SELECT * FROM employee
1498+
1499+
**Indexes**
1500+
1501+
The SQL service can use ``Map`` indexes to speed up the execution of certain
1502+
queries. ``SORTED`` and ``HASH`` indexes are supported.
1503+
1504+
Data Types
1505+
~~~~~~~~~~
1506+
1507+
The SQL service supports a set of SQL data types. Every data type is mapped to
1508+
a Python type that represents the type’s value.
1509+
1510+
======================== ===============
1511+
Type Name Python Type
1512+
======================== ===============
1513+
BOOLEAN bool
1514+
VARCHAR str
1515+
TINYINT int
1516+
SMALLINT int
1517+
INTEGER int
1518+
BIGINT int
1519+
DECIMAL str
1520+
REAL float
1521+
DOUBLE float
1522+
DATE str
1523+
TIME str
1524+
TIMESTAMP str
1525+
TIMESTAMP_WITH_TIME_ZONE str
1526+
OBJECT Any Python type
1527+
======================== ===============
1528+
1529+
Note that, the following types are returned as strings, with the following
1530+
formats.
1531+
1532+
- ``DATE`` with the ``YYYY-MM-DD`` format.
1533+
- ``TIME`` with the ``HH:MM:SS[.ffffff]`` format.
1534+
- ``TIMESTAMP`` with the ``YYYY-MM-DDTHH:MM:SS[.ffffff]`` format.
1535+
- ``TIMESTAMP_WITH_TIME_ZONE`` with the ``YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS]``
1536+
- ``DECIMAL`` with the floating point number format.
1537+
1538+
If you want to use these types in queries, you have to send them as strings
1539+
and add explicit ``CAST`` to queries.
1540+
1541+
``CAST`` operator has the following syntax:
1542+
1543+
.. code:: sql
1544+
1545+
CAST(? AS TYPE)
1546+
1547+
An example usage is shown below:
1548+
1549+
.. code:: python
1550+
1551+
client.sql.execute("SELECT * FROM map WHERE date < CAST(? AS DATE)", "2021-06-02")
1552+
1553+
SELECT
1554+
~~~~~~
1555+
1556+
**Synopsis**
1557+
1558+
.. code:: sql
1559+
1560+
SELECT [ * | expression [ [ AS ] expression_alias ] [, ...] ]
1561+
FROM table_name [ [ AS ] table_alias ]
1562+
[WHERE condition]
1563+
1564+
1565+
**Description**
1566+
1567+
The ``SELECT`` command retrieves rows from a table. A row is a sequence of
1568+
expressions defined after the ``SELECT`` keyword. Expressions may have
1569+
optional aliases.
1570+
1571+
``table_name`` refers to a single ``Map`` data structure. A table may have an
1572+
optional alias.
1573+
1574+
An optional ``WHERE`` clause defines a condition, that is any expression that
1575+
evaluates to a result of type boolean. Any row that doesn’t satisfy the
1576+
condition is eliminated from the result.
1577+
1578+
**Sorting**
1579+
1580+
You can use the standard SQL clauses ``ORDER BY``, ``LIMIT``, and ``OFFSET``
1581+
to sort and limit the result set.
1582+
1583+
1584+
.. warning::
1585+
1586+
Note that, you must add sorted indexes to the map object’s fields to be
1587+
sorted by. For example, for the ``SELECT * FROM persons ORDER BY name ASC``
1588+
query, there has to be a sorted index on the ``name`` field as shown below:
1589+
1590+
.. code:: python
1591+
1592+
persons = client.get_map("persons")
1593+
persons.add_index(attributes=["name"], index_type=IndexType.SORTED)
1594+
1595+
See the below examples for sorting.
1596+
1597+
The following statement gets the top five employees ordered by the
1598+
``first_name`` field and skipping the first three ones:
1599+
1600+
.. code:: sql
1601+
1602+
SELECT
1603+
employee_id, first_name, last_name
1604+
FROM
1605+
employees
1606+
ORDER BY first_name
1607+
LIMIT 5 OFFSET 3;
1608+
1609+
1610+
The following statement gets the top five employees with the highest salaries.
1611+
1612+
.. code:: sql
1613+
1614+
SELECT
1615+
employee_id, first_name, last_name, salary
1616+
FROM
1617+
employees
1618+
ORDER BY salary DESC
1619+
LIMIT 5;
1620+
1621+
**Unsupported Features**
1622+
1623+
The following features are **not supported** and are planned for future releases:
1624+
1625+
- ``GROUP BY`` / ``HAVING``
1626+
- ``JOIN``
1627+
- set operators (``UNION``, ``INTERSECT``, ``MINUS``)
1628+
- subqueries (``SELECT ... FROM table WHERE x = (SELECT …)``)
1629+
1630+
Expressions
1631+
~~~~~~~~~~~
1632+
1633+
Hazelcast SQL supports logical predicates, `IS` predicates, comparison
1634+
operators, mathematical functions and operators, string functions, and special
1635+
functions.
1636+
1637+
See `IMDG Reference Manual
1638+
<https://docs.hazelcast.com/imdg/latest/sql/querying-imap.html#key-and-value-fields>`__
1639+
for details.
1640+
1641+
Lite Members
1642+
~~~~~~~~~~~~
1643+
1644+
You cannot start SQL queries on lite members. This limitation will be removed
1645+
in future releases.
1646+
13491647
Distributed Query
13501648
-----------------
13511649

0 commit comments

Comments
 (0)