Skip to content

Commit

Permalink
Merge branch 'release/1.3.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
s3rius committed Apr 20, 2024
2 parents bba4648 + 6512734 commit dfad87e
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 110 deletions.
4 changes: 3 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ repos:
always_run: true
args: ["python"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
rev: v1.9.0
hooks:
- id: mypy
name: python mypy
always_run: true
additional_dependencies:
- "types-python-dateutil"
pass_filenames: false
args: ["python"]
- repo: https://github.com/astral-sh/ruff-pre-commit
Expand Down
13 changes: 7 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "scyllapy"
version = "1.3.0"
version = "1.3.1"
edition = "2021"

[lib]
Expand All @@ -14,20 +14,21 @@ eq-float = "0.1.0"
futures = "0.3.28"
log = "0.4.20"
openssl = { version = "0.10.57", features = ["vendored"] }
pyo3 = { version = "0.19.2", features = [
pyo3 = { version = "0.20.0", features = [
"auto-initialize",
"abi3-py38",
"extension-module",
"chrono",
] }
pyo3-asyncio = { version = "0.19.0", features = ["tokio-runtime"] }
pyo3-log = "0.8.3"
pyo3-asyncio = { version = "0.20.0", features = ["tokio-runtime"] }
pyo3-log = "0.9.0"
rustc-hash = "1.1.0"
scylla = { version = "0.10.1", features = ["ssl"] }
scylla-cql = "0.0.9"
scylla = { version = "0.12.0", features = ["ssl", "full-serialization"] }
bigdecimal-04 = { package = "bigdecimal", version = "0.4" }
thiserror = "1.0.48"
tokio = { version = "1.32.0", features = ["bytes"] }
uuid = { version = "1.4.1", features = ["v4"] }
time = { version = "*", features = ["formatting", "macros"] }

[profile.release]
lto = "fat"
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,35 @@ new_query = query.with_consistency(Consistency.ALL)

All `with_` methods create new query, copying all other parameters.

Here's the list of scylla types and corresponding python types that you should use while passing parameters to queries:

| Scylla type | Python type |
| ----------- | ---------------------- |
| int | int |
| tinyint | extra_types.TinyInt |
| bigint | extra_types.BigInt |
| varint | any int type |
| float | float |
| double | extra_types.Double |
| decimal | decimal.Decimal |
| ascii | str |
| text | str |
| varchar | str |
| blob | bytes |
| boolean | bool |
| counter | extra_types.Counter |
| date | datetime.date |
| uuid | uuid.UUID |
| inet | ipaddress |
| time | datetime.time |
| timestamp | datetime.datetime |
| duration | dateutil.relativedelta |

All types from `extra_types` module are used to eliminate any possible ambiguity while passing parameters to queries. You can find more information about them in `Extra types` section.

We use relative delta from `dateutil` for duration, because it's the only way to represent it in python. Since scylla operates with months, days and nanosecond, there's no way we can represent it in python, becuase months are variable length.


## Named parameters

Also, you can provide named parameters to querties, by using name
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ classifiers = [
"Intended Audience :: Developers",
"Topic :: Database :: Front-Ends",
]

dependencies = ["python-dateutil"]

[tool.maturin]
python-source = "python"
Expand Down Expand Up @@ -105,4 +105,4 @@ convention = "pep257"
ignore-decorators = ["typing.overload"]

[tool.ruff.pylint]
allow-magic-value-types = ["int", "str", "float", "tuple"]
allow-magic-value-types = ["int", "str", "float"]
15 changes: 10 additions & 5 deletions python/tests/test_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import ipaddress
import random
import uuid
from decimal import Decimal
from typing import Any, Callable

import pytest
from dateutil.relativedelta import relativedelta
from tests.utils import random_string

from scyllapy import Scylla
Expand All @@ -30,6 +32,10 @@
("UUID", uuid.uuid5(uuid.uuid4(), "name")),
("INET", ipaddress.ip_address("192.168.1.1")),
("INET", ipaddress.ip_address("2001:db8::8a2e:370:7334")),
("DECIMAL", Decimal("1.1")),
("DECIMAL", Decimal("1.112e10")),
("DURATION", relativedelta(months=1, days=2, microseconds=10)),
("VARINT", 1000),
],
)
async def test_bindings(
Expand All @@ -39,15 +45,14 @@ async def test_bindings(
) -> None:
table_name = random_string(4)
await scylla.execute(
f"CREATE TABLE {table_name} (id {type_name}, PRIMARY KEY (id))",
f"CREATE TABLE {table_name} (id INT, value {type_name}, PRIMARY KEY (id))",
)
insert_query = f"INSERT INTO {table_name}(id) VALUES (?)"
await scylla.execute(insert_query, [test_val])
insert_query = f"INSERT INTO {table_name}(id, value) VALUES (?, ?)"
await scylla.execute(insert_query, [1, test_val])

result = await scylla.execute(f"SELECT * FROM {table_name}")
rows = result.all()
assert len(rows) == 1
assert rows[0] == {"id": test_val}
assert rows == [{"id": 1, "value": test_val}]


@pytest.mark.anyio
Expand Down
27 changes: 26 additions & 1 deletion python/tests/test_extra_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import asdict, dataclass
from typing import Any
from typing import Any, Callable

import pytest
from tests.utils import random_string
Expand Down Expand Up @@ -147,3 +147,28 @@ async def test_autocast_positional(scylla: Scylla, typ: str, val: Any) -> None:
await scylla.execute(f"CREATE TABLE {table_name}(id INT PRIMARY KEY, val {typ})")
prepared = await scylla.prepare(f"INSERT INTO {table_name}(id, val) VALUES (?, ?)")
await scylla.execute(prepared, [1, val])


@pytest.mark.parametrize(
["cast_func", "val"],
[
(extra_types.BigInt, 1000000),
(extra_types.SmallInt, 10),
(extra_types.TinyInt, 1),
(int, 1),
],
)
@pytest.mark.anyio
async def test_varint(
scylla: Scylla,
cast_func: Callable[[Any], Any],
val: Any,
) -> None:
table_name = random_string(4)
await scylla.execute(f"CREATE TABLE {table_name}(id INT PRIMARY KEY, val VARINT)")
await scylla.execute(
f"INSERT INTO {table_name}(id, val) VALUES (?, ?)",
(1, cast_func(val)),
)
res = await scylla.execute(f"SELECT * FROM {table_name}")
assert res.all() == [{"id": 1, "val": val}]
14 changes: 8 additions & 6 deletions src/batches.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use pyo3::{pyclass, pymethods, types::PyDict, PyAny};
use scylla::batch::{Batch, BatchStatement, BatchType};
use scylla::{
batch::{Batch, BatchStatement, BatchType},
frame::value::LegacySerializedValues,
};

use crate::{
exceptions::rust_err::ScyllaPyResult, inputs::BatchQueryInput, queries::ScyllaPyRequestParams,
utils::parse_python_query_params,
};
use scylla::frame::value::SerializedValues;

#[pyclass(name = "BatchType")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand All @@ -27,7 +29,7 @@ pub struct ScyllaPyBatch {
pub struct ScyllaPyInlineBatch {
inner: Batch,
request_params: ScyllaPyRequestParams,
values: Vec<SerializedValues>,
values: Vec<LegacySerializedValues>,
}

impl From<ScyllaPyBatch> for Batch {
Expand All @@ -38,7 +40,7 @@ impl From<ScyllaPyBatch> for Batch {
}
}

impl From<ScyllaPyInlineBatch> for (Batch, Vec<SerializedValues>) {
impl From<ScyllaPyInlineBatch> for (Batch, Vec<LegacySerializedValues>) {
fn from(mut value: ScyllaPyInlineBatch) -> Self {
value.request_params.apply_to_batch(&mut value.inner);
(value.inner, value.values)
Expand Down Expand Up @@ -74,7 +76,7 @@ impl ScyllaPyInlineBatch {
pub fn add_query_inner(
&mut self,
query: impl Into<BatchStatement>,
values: impl Into<SerializedValues>,
values: impl Into<LegacySerializedValues>,
) {
self.inner.append_statement(query);
self.values.push(values.into());
Expand Down Expand Up @@ -123,7 +125,7 @@ impl ScyllaPyInlineBatch {
self.values
.push(parse_python_query_params(Some(passed_params), false, None)?);
} else {
self.values.push(SerializedValues::new());
self.values.push(LegacySerializedValues::new());
}
Ok(())
}
Expand Down
6 changes: 3 additions & 3 deletions src/exceptions/rust_err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ pub enum ScyllaPyError {

// Derived exception.
#[error("{0}")]
QueryError(#[from] scylla_cql::errors::QueryError),
QueryError(#[from] scylla::transport::errors::QueryError),
#[error("{0}")]
DBError(#[from] scylla_cql::errors::DbError),
DBError(#[from] scylla::transport::errors::DbError),
#[error("Python exception: {0}.")]
PyError(#[from] pyo3::PyErr),
#[error("OpenSSL error: {0}.")]
SSLError(#[from] openssl::error::ErrorStack),
#[error("Cannot construct new session: {0}.")]
ScyllaSessionError(#[from] scylla_cql::errors::NewSessionError),
ScyllaSessionError(#[from] scylla::transport::errors::NewSessionError),

// Binding errors
#[error("Binding error. Cannot build values for query: {0},")]
Expand Down
14 changes: 7 additions & 7 deletions src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,31 +66,31 @@ impl ScyllaPyRequestParams {
};
Ok(Self {
consistency: params
.get_item("consistency")
.get_item("consistency")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
serial_consistency: params
.get_item("serial_consistency")
.get_item("serial_consistency")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
request_timeout: params
.get_item("request_timeout")
.get_item("request_timeout")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
timestamp: params
.get_item("timestamp")
.get_item("timestamp")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
is_idempotent: params
.get_item("is_idempotent")
.get_item("is_idempotent")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
tracing: params
.get_item("tracing")
.get_item("tracing")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
profile: params
.get_item("profile")
.get_item("profile")?
.map(pyo3::FromPyObject::extract)
.transpose()?,
})
Expand Down
9 changes: 4 additions & 5 deletions src/query_builder/delete.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use pyo3::{pyclass, pymethods, types::PyDict, PyAny, PyRefMut, Python};
use scylla::query::Query;
use scylla::{frame::value::LegacySerializedValues, query::Query};

use super::utils::{pretty_build, IfCluase, Timeout};
use crate::{
Expand All @@ -9,7 +9,6 @@ use crate::{
scylla_cls::Scylla,
utils::{py_to_value, ScyllaPyCQLDTO},
};
use scylla::frame::value::SerializedValues;

#[pyclass]
#[derive(Clone, Debug, Default)]
Expand All @@ -35,7 +34,7 @@ impl Delete {
.columns
.as_ref()
.map_or(String::new(), |cols| cols.join(", "));
let params = vec![
let params = [
self.timestamp_
.map(|timestamp| format!("TIMESTAMP {timestamp}")),
self.timeout_.as_ref().map(|timeout| match timeout {
Expand Down Expand Up @@ -208,7 +207,7 @@ impl Delete {
///
/// Adds current query to batch.
///
/// # Error
/// # Errors
///
/// May result into error if query cannot be build.
/// Or values cannot be passed to batch.
Expand All @@ -221,7 +220,7 @@ impl Delete {
} else {
self.values_.clone()
};
let mut serialized = SerializedValues::new();
let mut serialized = LegacySerializedValues::new();
for val in values {
serialized.add_value(&val)?;
}
Expand Down
9 changes: 4 additions & 5 deletions src/query_builder/insert.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use pyo3::{pyclass, pymethods, types::PyDict, PyAny, PyRefMut, Python};
use scylla::query::Query;
use scylla::{frame::value::LegacySerializedValues, query::Query};

use crate::{
batches::ScyllaPyInlineBatch,
Expand All @@ -8,7 +8,6 @@ use crate::{
scylla_cls::Scylla,
utils::{py_to_value, ScyllaPyCQLDTO},
};
use scylla::frame::value::SerializedValues;

use super::utils::{pretty_build, Timeout};

Expand Down Expand Up @@ -51,7 +50,7 @@ impl Insert {
} else {
""
};
let params = vec![
let params = [
self.timestamp_
.map(|timestamp| format!("TIMESTAMP {timestamp}")),
self.ttl_.map(|ttl| format!("TTL {ttl}")),
Expand Down Expand Up @@ -172,15 +171,15 @@ impl Insert {
///
/// Adds current query to batch.
///
/// # Error
/// # Errors
///
/// May result into error if query cannot be build.
/// Or values cannot be passed to batch.
pub fn add_to_batch(&self, batch: &mut ScyllaPyInlineBatch) -> ScyllaPyResult<()> {
let mut query = Query::new(self.build_query()?);
self.request_params_.apply_to_query(&mut query);

let mut serialized = SerializedValues::new();
let mut serialized = LegacySerializedValues::new();
for val in self.values_.clone() {
serialized.add_value(&val)?;
}
Expand Down
6 changes: 3 additions & 3 deletions src/query_builder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
};

use super::utils::{pretty_build, Timeout};
use scylla::frame::value::SerializedValues;
use scylla::frame::value::LegacySerializedValues;

#[pyclass]
#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -255,14 +255,14 @@ impl Select {
///
/// Adds current query to batch.
///
/// # Error
/// # Errors
///
/// Returns error if values cannot be passed to batch.
pub fn add_to_batch(&self, batch: &mut ScyllaPyInlineBatch) -> ScyllaPyResult<()> {
let mut query = Query::new(self.build_query());
self.request_params_.apply_to_query(&mut query);

let mut serialized = SerializedValues::new();
let mut serialized = LegacySerializedValues::new();
for val in self.values_.clone() {
serialized.add_value(&val)?;
}
Expand Down
Loading

0 comments on commit dfad87e

Please sign in to comment.