Skip to content

Commit

Permalink
Little more documentation and preapre 2.0.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
igorcoding committed Jun 30, 2022
1 parent a836c07 commit 4387c90
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 2 deletions.
2 changes: 1 addition & 1 deletion asynctnt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
Db, IProtoError, IProtoErrorStackFrame
)

__version__ = '2.0.0b2'
__version__ = '2.0.0'
29 changes: 29 additions & 0 deletions asynctnt/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,26 +381,55 @@ def execute(self,
timeout=timeout)

def prepare(self, query: str) -> PreparedStatement:
"""
Create a :class:`asynctnt.prepared.PreparedStatement` instance
:param query: query to be prepared
"""
return PreparedStatement(self, query)

def prepare_iproto(self,
query: str,
timeout: float = -1.0) -> MethodRet:
"""
Low-level prepare() call
:param query: query to be prepared
:param timeout: request timeout
"""
return self._db.prepare(query, timeout=timeout)

def unprepare_iproto(self,
stmt_id: int,
timeout: float = -1.0) -> MethodRet:
"""
Low-level unprepare() call
:param stmt_id: query to be unprepared
:param timeout: request timeout
"""
return self._db.prepare(stmt_id, timeout=timeout)

def begin(self,
isolation: Isolation = Isolation.DEFAULT,
tx_timeout: float = 0.0,
timeout: float = -1.0) -> MethodRet:
"""
Begin an interactive transaction within a stream
:param isolation: isolation level
:param tx_timeout: transaction timeout
:param timeout: request timeout
:return:
"""
return self._db.begin(isolation.value, tx_timeout, timeout)

def commit(self, timeout: float = -1.0) -> MethodRet:
"""
Commit a running transaction
:param timeout: request timeout
"""
return self._db.commit(timeout)

def rollback(self, timeout: float = -1.0) -> MethodRet:
"""
Rollback a running transaction
:param timeout: request timeout
"""
return self._db.rollback(timeout)
6 changes: 6 additions & 0 deletions asynctnt/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@ def schema_id(self) -> Optional[int]:

@property
def schema(self) -> Optional[protocol.Schema]:
"""
Current Tarantool schema with all spaces, indexes and fields
"""
if self._protocol is None: # pragma: nocover
return None
return self._protocol.schema
Expand Down Expand Up @@ -613,6 +616,9 @@ def __repr__(self):
)

def stream(self) -> Stream:
"""
Create new stream suitable for interactive transactions
"""
stream = Stream()
db = self._protocol.create_db(True)
stream._set_db(db)
Expand Down
17 changes: 17 additions & 0 deletions asynctnt/iproto/protocol.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,38 @@ from typing import Iterator, Tuple, Optional, List, Any, Union, Dict

class Field:
name: Optional[str]
""" Field name """

type: Optional[str]
""" Field type """

collation: Optional[str]
""" Field collation value """

is_nullable: Optional[bool]
""" If field may be null """

is_autoincrement: Optional[bool]
""" Is Autoincrement """

span: Optional[str]


class Metadata:
fields: List[Field]
""" List of fields """

name_id_map: Dict[str, int]
""" Mapping name -> id """


class SchemaIndex:
iid: int
""" Index id """

sid: int
""" Space id """

name: Optional[str]
index_type: Optional[str]
unique: Optional[bool]
Expand Down
29 changes: 29 additions & 0 deletions asynctnt/prepared.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,32 @@ def __init__(self, api: 'Api', query: str):

@property
def id(self) -> int:
"""
Prepared statement id
"""
return self._stmt_id

@property
def params_count(self) -> int:
"""
Bound params count
"""
return self._params_count

@property
def params(self) -> Optional[protocol.Metadata]:
"""
Bound params metadata
"""
return self._params

async def prepare(self, timeout: float = -1.0) -> int:
"""
Prepare statement
:param timeout: request timeout
:return: prepared statement id
"""
resp = await self._api.prepare_iproto(self._query, timeout=timeout)
self._stmt_id = resp.stmt_id
self._params = resp.params
Expand All @@ -43,6 +58,12 @@ async def execute(self,
*,
parse_metadata: bool = True,
timeout: float = -1.0) -> protocol.Response:
"""
Execute this prepared statement with specified args
:param args: arguments list
:param parse_metadata: whether to parse response metadata or not
:param timeout: request timeout
"""
return await self._api.execute(
query=self._stmt_id,
args=args,
Expand All @@ -51,10 +72,18 @@ async def execute(self,
)

async def unprepare(self, timeout: float = -1.0):
"""
Unprepare current prepared statement
:param timeout: request timeout
"""
await self._api.unprepare_iproto(self._stmt_id, timeout=timeout)
self._stmt_id = None

async def __aenter__(self):
"""
If used as a Context Manager `prepare()` and `unprepare()` methods
are called automatically
"""
if self._stmt_id is None:
await self.prepare()
return self
Expand Down
12 changes: 12 additions & 0 deletions asynctnt/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ def __init__(self):

@property
def stream_id(self) -> int:
"""
Current stream is
"""
return self._db.stream_id

async def __aenter__(self):
"""
If used as Context Manager `begin()` and `commit()`/`rollback()`
are called automatically
:return:
"""
await self.begin()
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
"""
Normally `commit()` is called on context manager exit, but
in the case of exception `rollback()` is called
"""
if exc_type and exc_val:
await self.rollback()
else:
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def find_version():
'myst_parser',
'sphinx_autodoc_typehints',
'sphinx_rtd_theme',
# 'autoapi.extension'
'autoapi.extension'
]

templates_path = ['_templates']
Expand Down
56 changes: 56 additions & 0 deletions docs/sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,59 @@ Stdout:

You can access all the metadata associated with the SQL response, like so:

```python
res = await conn.execute("select * from users")
assert res.metadata.fields[0].name == 'ID'
assert res.metadata.fields[0].type == 'integer'

assert res.metadata.fields[1].name == 'NAME'
assert res.metadata.fields[0].type == 'string'
```

## Prepared statement

You can make use of [prepared statements](https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_sql/prepare/)
in order to execute the same requests more optimally. Simple example:

```python
stmt = conn.prepare('select id, name from users where id = ?')
async with stmt:
user1 = stmt.execute([1])
assert user1.name == 'James Bond'

user2 = stmt.execute([2])
assert user2.name == 'Ethan Hunt'
```

`prepare()` and `unprepare()` calls are called automatically within a prepared statement context manager.
You may want to control prepare/unprepare yourself:

```python
stmt = conn.prepare('select id, name from users where id = ?')

await stmt.prepare()

user1 = stmt.execute([1])
assert user1.name == 'James Bond'

user2 = stmt.execute([2])
assert user2.name == 'Ethan Hunt'

await stmt.unprepare()
```

Named parameters are also supported:

```python
stmt = conn.prepare('select id, name from users where id = :id')
async with stmt:
user1 = stmt.execute([
{':id': 1}
])
assert user1.name == 'James Bond'

user2 = stmt.execute([
{':id': 2}
])
assert user2.name == 'Ethan Hunt'
```

0 comments on commit 4387c90

Please sign in to comment.