Skip to content

Commit e1fd8f2

Browse files
committed
Merge branch 'v1.4-andium'
2 parents c42539c + 0465578 commit e1fd8f2

File tree

15 files changed

+122
-118
lines changed

15 files changed

+122
-118
lines changed

.github/workflows/packaging.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
testsuite: all
6969
duckdb-python-sha: ${{ inputs.duckdb-python-sha != '' && inputs.duckdb-python-sha || github.sha }}
7070
duckdb-sha: ${{ inputs.duckdb-sha }}
71-
set-version: ${{ inputs.stable-version }}
71+
set-version: ${{ inputs.set-version }}
7272

7373
build_wheels:
7474
name: Build and test releases
@@ -78,4 +78,4 @@ jobs:
7878
testsuite: all
7979
duckdb-python-sha: ${{ inputs.duckdb-python-sha != '' && inputs.duckdb-python-sha || github.sha }}
8080
duckdb-sha: ${{ inputs.duckdb-sha }}
81-
set-version: ${{ inputs.stable-version }}
81+
set-version: ${{ inputs.set-version }}

.github/workflows/packaging_wheels.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ jobs:
7373
7474
# Make sure that OVERRIDE_GIT_DESCRIBE is propagated to cibuildwhel's env, also when it's running linux builds
7575
- name: Set OVERRIDE_GIT_DESCRIBE
76+
shell: bash
7677
if: ${{ inputs.set-version != '' }}
7778
run: echo "CIBW_ENVIRONMENT=OVERRIDE_GIT_DESCRIBE=${{ inputs.set-version }}" >> $GITHUB_ENV
7879

duckdb/__init__.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,49 @@ def version():
1818
"functional"
1919
])
2020

21+
class DBAPITypeObject:
22+
def __init__(self, types: list[typing.DuckDBPyType]) -> None:
23+
self.types = types
24+
25+
def __eq__(self, other):
26+
if isinstance(other, typing.DuckDBPyType):
27+
return other in self.types
28+
return False
29+
30+
def __repr__(self):
31+
return f"<DBAPITypeObject [{','.join(str(x) for x in self.types)}]>"
32+
33+
# Define the standard DBAPI sentinels
34+
STRING = DBAPITypeObject([typing.VARCHAR])
35+
NUMBER = DBAPITypeObject([
36+
typing.TINYINT,
37+
typing.UTINYINT,
38+
typing.SMALLINT,
39+
typing.USMALLINT,
40+
typing.INTEGER,
41+
typing.UINTEGER,
42+
typing.BIGINT,
43+
typing.UBIGINT,
44+
typing.HUGEINT,
45+
typing.UHUGEINT,
46+
typing.DuckDBPyType("BIGNUM"),
47+
typing.DuckDBPyType("DECIMAL"),
48+
typing.FLOAT,
49+
typing.DOUBLE
50+
])
51+
DATETIME = DBAPITypeObject([
52+
typing.DATE,
53+
typing.TIME,
54+
typing.TIME_TZ,
55+
typing.TIMESTAMP,
56+
typing.TIMESTAMP_TZ,
57+
typing.TIMESTAMP_NS,
58+
typing.TIMESTAMP_MS,
59+
typing.TIMESTAMP_S
60+
])
61+
BINARY = DBAPITypeObject([typing.BLOB])
62+
ROWID = None
63+
2164
# Classes
2265
from _duckdb import (
2366
DuckDBPyRelation,

external/duckdb

Submodule duckdb updated 53 files

src/duckdb_py/pyconnection.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,9 @@ shared_ptr<DuckDBPyConnection> DuckDBPyConnection::ExecuteMany(const py::object
465465

466466
unique_ptr<QueryResult> DuckDBPyConnection::CompletePendingQuery(PendingQueryResult &pending_query) {
467467
PendingExecutionResult execution_result;
468+
if (pending_query.HasError()) {
469+
pending_query.ThrowError();
470+
}
468471
while (!PendingQueryResult::IsResultReady(execution_result = pending_query.ExecuteTask())) {
469472
{
470473
py::gil_scoped_acquire gil;

src/duckdb_py/pyexpression/initialize.cpp

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,17 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
6161
FunctionExpression: self '+' expr
6262
)";
6363

64-
m.def("__add__", &DuckDBPyExpression::Add, py::arg("expr"), docs);
64+
m.def("__add__", &DuckDBPyExpression::Add, py::arg("expr"), docs, py::is_operator());
6565
m.def(
66-
"__radd__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Add(a); }, docs);
66+
"__radd__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Add(a); }, docs, py::is_operator());
6767

6868
docs = R"(
6969
Negate the expression.
7070
7171
Returns:
7272
FunctionExpression: -self
7373
)";
74-
m.def("__neg__", &DuckDBPyExpression::Negate, docs);
74+
m.def("__neg__", &DuckDBPyExpression::Negate, docs, py::is_operator());
7575

7676
docs = R"(
7777
Subtract expr from self
@@ -82,9 +82,9 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
8282
Returns:
8383
FunctionExpression: self '-' expr
8484
)";
85-
m.def("__sub__", &DuckDBPyExpression::Subtract, docs);
85+
m.def("__sub__", &DuckDBPyExpression::Subtract, docs, py::is_operator());
8686
m.def(
87-
"__rsub__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Subtract(a); }, docs);
87+
"__rsub__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Subtract(a); }, docs, py::is_operator());
8888

8989
docs = R"(
9090
Multiply self by expr
@@ -95,9 +95,9 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
9595
Returns:
9696
FunctionExpression: self '*' expr
9797
)";
98-
m.def("__mul__", &DuckDBPyExpression::Multiply, docs);
98+
m.def("__mul__", &DuckDBPyExpression::Multiply, docs, py::is_operator());
9999
m.def(
100-
"__rmul__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Multiply(a); }, docs);
100+
"__rmul__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Multiply(a); }, docs, py::is_operator());
101101

102102
docs = R"(
103103
Divide self by expr
@@ -108,13 +108,13 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
108108
Returns:
109109
FunctionExpression: self '/' expr
110110
)";
111-
m.def("__div__", &DuckDBPyExpression::Division, docs);
111+
m.def("__div__", &DuckDBPyExpression::Division, docs, py::is_operator());
112112
m.def(
113-
"__rdiv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Division(a); }, docs);
113+
"__rdiv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Division(a); }, docs, py::is_operator());
114114

115-
m.def("__truediv__", &DuckDBPyExpression::Division, docs);
115+
m.def("__truediv__", &DuckDBPyExpression::Division, docs, py::is_operator());
116116
m.def(
117-
"__rtruediv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Division(a); }, docs);
117+
"__rtruediv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Division(a); }, docs, py::is_operator());
118118

119119
docs = R"(
120120
(Floor) Divide self by expr
@@ -125,10 +125,9 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
125125
Returns:
126126
FunctionExpression: self '//' expr
127127
)";
128-
m.def("__floordiv__", &DuckDBPyExpression::FloorDivision, docs);
128+
m.def("__floordiv__", &DuckDBPyExpression::FloorDivision, docs, py::is_operator());
129129
m.def(
130-
"__rfloordiv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.FloorDivision(a); },
131-
docs);
130+
"__rfloordiv__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.FloorDivision(a); }, docs, py::is_operator());
132131

133132
docs = R"(
134133
Modulo self by expr
@@ -139,9 +138,9 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
139138
Returns:
140139
FunctionExpression: self '%' expr
141140
)";
142-
m.def("__mod__", &DuckDBPyExpression::Modulo, docs);
141+
m.def("__mod__", &DuckDBPyExpression::Modulo, docs, py::is_operator());
143142
m.def(
144-
"__rmod__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Modulo(a); }, docs);
143+
"__rmod__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Modulo(a); }, docs, py::is_operator());
145144

146145
docs = R"(
147146
Power self by expr
@@ -152,9 +151,9 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
152151
Returns:
153152
FunctionExpression: self '**' expr
154153
)";
155-
m.def("__pow__", &DuckDBPyExpression::Power, docs);
154+
m.def("__pow__", &DuckDBPyExpression::Power, docs, py::is_operator());
156155
m.def(
157-
"__rpow__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Power(a); }, docs);
156+
"__rpow__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Power(a); }, docs, py::is_operator());
158157

159158
docs = R"(
160159
Create an equality expression between two expressions
@@ -165,7 +164,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
165164
Returns:
166165
FunctionExpression: self '=' expr
167166
)";
168-
m.def("__eq__", &DuckDBPyExpression::Equality, docs);
167+
m.def("__eq__", &DuckDBPyExpression::Equality, docs, py::is_operator());
169168

170169
docs = R"(
171170
Create an inequality expression between two expressions
@@ -176,7 +175,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
176175
Returns:
177176
FunctionExpression: self '!=' expr
178177
)";
179-
m.def("__ne__", &DuckDBPyExpression::Inequality, docs);
178+
m.def("__ne__", &DuckDBPyExpression::Inequality, docs, py::is_operator());
180179

181180
docs = R"(
182181
Create a greater than expression between two expressions
@@ -187,7 +186,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
187186
Returns:
188187
FunctionExpression: self '>' expr
189188
)";
190-
m.def("__gt__", &DuckDBPyExpression::GreaterThan, docs);
189+
m.def("__gt__", &DuckDBPyExpression::GreaterThan, docs, py::is_operator());
191190

192191
docs = R"(
193192
Create a greater than or equal expression between two expressions
@@ -198,7 +197,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
198197
Returns:
199198
FunctionExpression: self '>=' expr
200199
)";
201-
m.def("__ge__", &DuckDBPyExpression::GreaterThanOrEqual, docs);
200+
m.def("__ge__", &DuckDBPyExpression::GreaterThanOrEqual, docs, py::is_operator());
202201

203202
docs = R"(
204203
Create a less than expression between two expressions
@@ -209,7 +208,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
209208
Returns:
210209
FunctionExpression: self '<' expr
211210
)";
212-
m.def("__lt__", &DuckDBPyExpression::LessThan, docs);
211+
m.def("__lt__", &DuckDBPyExpression::LessThan, docs, py::is_operator());
213212

214213
docs = R"(
215214
Create a less than or equal expression between two expressions
@@ -220,7 +219,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
220219
Returns:
221220
FunctionExpression: self '<=' expr
222221
)";
223-
m.def("__le__", &DuckDBPyExpression::LessThanOrEqual, docs);
222+
m.def("__le__", &DuckDBPyExpression::LessThanOrEqual, docs, py::is_operator());
224223

225224
// AND, NOT and OR
226225

@@ -233,7 +232,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
233232
Returns:
234233
FunctionExpression: self '&' expr
235234
)";
236-
m.def("__and__", &DuckDBPyExpression::And, docs);
235+
m.def("__and__", &DuckDBPyExpression::And, docs, py::is_operator());
237236

238237
docs = R"(
239238
Binary-or self together with expr
@@ -244,15 +243,15 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
244243
Returns:
245244
FunctionExpression: self '|' expr
246245
)";
247-
m.def("__or__", &DuckDBPyExpression::Or, docs);
246+
m.def("__or__", &DuckDBPyExpression::Or, docs, py::is_operator());
248247

249248
docs = R"(
250249
Create a binary-not expression from self
251250
252251
Returns:
253252
FunctionExpression: ~self
254253
)";
255-
m.def("__invert__", &DuckDBPyExpression::Not, docs);
254+
m.def("__invert__", &DuckDBPyExpression::Not, docs, py::is_operator());
256255

257256
docs = R"(
258257
Binary-and self together with expr
@@ -264,7 +263,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
264263
FunctionExpression: expr '&' self
265264
)";
266265
m.def(
267-
"__rand__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.And(a); }, docs);
266+
"__rand__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.And(a); }, docs, py::is_operator());
268267

269268
docs = R"(
270269
Binary-or self together with expr
@@ -276,7 +275,7 @@ static void InitializeDunderMethods(py::class_<DuckDBPyExpression, shared_ptr<Du
276275
FunctionExpression: expr '|' self
277276
)";
278277
m.def(
279-
"__ror__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Or(a); }, docs);
278+
"__ror__", [](const DuckDBPyExpression &a, const DuckDBPyExpression &b) { return b.Or(a); }, docs, py::is_operator());
280279
}
281280

282281
static void InitializeImplicitConversion(py::class_<DuckDBPyExpression, shared_ptr<DuckDBPyExpression>> &m) {

src/duckdb_py/pyresult.cpp

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -514,72 +514,12 @@ py::object DuckDBPyResult::FetchArrowCapsule(idx_t rows_per_batch) {
514514
return py::capsule(stream, "arrow_array_stream", ArrowArrayStreamPyCapsuleDestructor);
515515
}
516516

517-
py::str GetTypeToPython(const LogicalType &type) {
518-
switch (type.id()) {
519-
case LogicalTypeId::BOOLEAN:
520-
return py::str("bool");
521-
case LogicalTypeId::TINYINT:
522-
case LogicalTypeId::SMALLINT:
523-
case LogicalTypeId::INTEGER:
524-
case LogicalTypeId::BIGINT:
525-
case LogicalTypeId::UTINYINT:
526-
case LogicalTypeId::USMALLINT:
527-
case LogicalTypeId::UINTEGER:
528-
case LogicalTypeId::UBIGINT:
529-
case LogicalTypeId::HUGEINT:
530-
case LogicalTypeId::UHUGEINT:
531-
case LogicalTypeId::FLOAT:
532-
case LogicalTypeId::DOUBLE:
533-
case LogicalTypeId::DECIMAL: {
534-
return py::str("NUMBER");
535-
}
536-
case LogicalTypeId::VARCHAR: {
537-
if (type.HasAlias() && type.GetAlias() == "JSON") {
538-
return py::str("JSON");
539-
} else {
540-
return py::str("STRING");
541-
}
542-
}
543-
case LogicalTypeId::BLOB:
544-
case LogicalTypeId::BIT:
545-
return py::str("BINARY");
546-
case LogicalTypeId::TIMESTAMP:
547-
case LogicalTypeId::TIMESTAMP_TZ:
548-
case LogicalTypeId::TIMESTAMP_MS:
549-
case LogicalTypeId::TIMESTAMP_NS:
550-
case LogicalTypeId::TIMESTAMP_SEC: {
551-
return py::str("DATETIME");
552-
}
553-
case LogicalTypeId::TIME:
554-
case LogicalTypeId::TIME_TZ: {
555-
return py::str("Time");
556-
}
557-
case LogicalTypeId::DATE: {
558-
return py::str("Date");
559-
}
560-
case LogicalTypeId::STRUCT:
561-
case LogicalTypeId::MAP:
562-
return py::str("dict");
563-
case LogicalTypeId::LIST: {
564-
return py::str("list");
565-
}
566-
case LogicalTypeId::INTERVAL: {
567-
return py::str("TIMEDELTA");
568-
}
569-
case LogicalTypeId::UUID: {
570-
return py::str("UUID");
571-
}
572-
default:
573-
return py::str(type.ToString());
574-
}
575-
}
576-
577517
py::list DuckDBPyResult::GetDescription(const vector<string> &names, const vector<LogicalType> &types) {
578518
py::list desc;
579519

580520
for (idx_t col_idx = 0; col_idx < names.size(); col_idx++) {
581521
auto py_name = py::str(names[col_idx]);
582-
auto py_type = GetTypeToPython(types[col_idx]);
522+
auto py_type = DuckDBPyType(types[col_idx]);
583523
desc.append(py::make_tuple(py_name, py_type, py::none(), py::none(), py::none(), py::none(), py::none()));
584524
}
585525
return desc;

src/duckdb_py/typing/pytype.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ void DuckDBPyType::Initialize(py::handle &m) {
326326
auto type_module = py::class_<DuckDBPyType, shared_ptr<DuckDBPyType>>(m, "DuckDBPyType", py::module_local());
327327

328328
type_module.def("__repr__", &DuckDBPyType::ToString, "Stringified representation of the type object");
329-
type_module.def("__eq__", &DuckDBPyType::Equals, "Compare two types for equality", py::arg("other"));
330-
type_module.def("__eq__", &DuckDBPyType::EqualsString, "Compare two types for equality", py::arg("other"));
329+
type_module.def("__eq__", &DuckDBPyType::Equals, "Compare two types for equality", py::arg("other"), py::is_operator());
330+
type_module.def("__eq__", &DuckDBPyType::EqualsString, "Compare two types for equality", py::arg("other"), py::is_operator());
331331
type_module.def_property_readonly("id", &DuckDBPyType::GetId);
332332
type_module.def_property_readonly("children", &DuckDBPyType::Children);
333333
type_module.def(py::init<>([](const string &type_str, shared_ptr<DuckDBPyConnection> connection = nullptr) {
@@ -347,7 +347,7 @@ void DuckDBPyType::Initialize(py::handle &m) {
347347
return make_shared_ptr<DuckDBPyType>(ltype);
348348
}));
349349
type_module.def("__getattr__", &DuckDBPyType::GetAttribute, "Get the child type by 'name'", py::arg("name"));
350-
type_module.def("__getitem__", &DuckDBPyType::GetAttribute, "Get the child type by 'name'", py::arg("name"));
350+
type_module.def("__getitem__", &DuckDBPyType::GetAttribute, "Get the child type by 'name'", py::arg("name"), py::is_operator());
351351

352352
py::implicitly_convertible<py::object, DuckDBPyType>();
353353
py::implicitly_convertible<py::str, DuckDBPyType>();

tests/fast/api/test_3728.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ def test_3728_describe_enum(self, duckdb_cursor):
1414

1515
# This fails with "RuntimeError: Not implemented Error: unsupported type: mood"
1616
assert cursor.table("person").execute().description == [
17-
('name', 'STRING', None, None, None, None, None),
17+
('name', 'VARCHAR', None, None, None, None, None),
1818
('current_mood', "ENUM('sad', 'ok', 'happy')", None, None, None, None, None),
1919
]

0 commit comments

Comments
 (0)