duckdb 1.5.0.dev37__cp312-cp312-macosx_10_13_universal2.whl → 1.5.0.dev94__cp312-cp312-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of duckdb might be problematic. Click here for more details.
- _duckdb-stubs/__init__.pyi +1443 -0
- _duckdb-stubs/_func.pyi +46 -0
- _duckdb-stubs/_sqltypes.pyi +75 -0
- _duckdb.cpython-312-darwin.so +0 -0
- adbc_driver_duckdb/__init__.py +49 -0
- adbc_driver_duckdb/dbapi.py +115 -0
- duckdb/__init__.py +341 -435
- duckdb/_dbapi_type_object.py +231 -0
- duckdb/_version.py +22 -0
- duckdb/bytes_io_wrapper.py +12 -9
- duckdb/experimental/__init__.py +2 -1
- duckdb/experimental/spark/__init__.py +3 -4
- duckdb/experimental/spark/_globals.py +8 -8
- duckdb/experimental/spark/_typing.py +7 -9
- duckdb/experimental/spark/conf.py +16 -15
- duckdb/experimental/spark/context.py +60 -44
- duckdb/experimental/spark/errors/__init__.py +33 -35
- duckdb/experimental/spark/errors/error_classes.py +1 -1
- duckdb/experimental/spark/errors/exceptions/__init__.py +1 -1
- duckdb/experimental/spark/errors/exceptions/base.py +39 -88
- duckdb/experimental/spark/errors/utils.py +11 -16
- duckdb/experimental/spark/exception.py +9 -6
- duckdb/experimental/spark/sql/__init__.py +5 -5
- duckdb/experimental/spark/sql/_typing.py +8 -15
- duckdb/experimental/spark/sql/catalog.py +21 -20
- duckdb/experimental/spark/sql/column.py +48 -55
- duckdb/experimental/spark/sql/conf.py +9 -8
- duckdb/experimental/spark/sql/dataframe.py +185 -233
- duckdb/experimental/spark/sql/functions.py +1222 -1248
- duckdb/experimental/spark/sql/group.py +56 -52
- duckdb/experimental/spark/sql/readwriter.py +80 -94
- duckdb/experimental/spark/sql/session.py +64 -59
- duckdb/experimental/spark/sql/streaming.py +9 -10
- duckdb/experimental/spark/sql/type_utils.py +67 -65
- duckdb/experimental/spark/sql/types.py +309 -345
- duckdb/experimental/spark/sql/udf.py +6 -6
- duckdb/filesystem.py +26 -16
- duckdb/func/__init__.py +3 -0
- duckdb/functional/__init__.py +12 -16
- duckdb/polars_io.py +130 -83
- duckdb/query_graph/__main__.py +91 -96
- duckdb/sqltypes/__init__.py +63 -0
- duckdb/typing/__init__.py +18 -8
- duckdb/udf.py +10 -5
- duckdb/value/__init__.py +1 -0
- duckdb/value/constant/__init__.py +62 -60
- {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/METADATA +12 -4
- duckdb-1.5.0.dev94.dist-info/RECORD +52 -0
- duckdb/__init__.pyi +0 -713
- duckdb/functional/__init__.pyi +0 -31
- duckdb/typing/__init__.pyi +0 -36
- duckdb/value/constant/__init__.pyi +0 -115
- duckdb-1.5.0.dev37.dist-info/RECORD +0 -47
- /duckdb/{value/__init__.pyi → py.typed} +0 -0
- {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/WHEEL +0 -0
- {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/licenses/LICENSE +0 -0
duckdb/query_graph/__main__.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import argparse # noqa: D100
|
|
1
2
|
import json
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
3
|
import re
|
|
5
4
|
import webbrowser
|
|
6
5
|
from functools import reduce
|
|
7
|
-
import
|
|
6
|
+
from pathlib import Path
|
|
8
7
|
|
|
9
8
|
qgraph_css = """
|
|
10
9
|
.styled-table {
|
|
@@ -57,7 +56,7 @@ qgraph_css = """
|
|
|
57
56
|
text-align: center;
|
|
58
57
|
padding: 0px;
|
|
59
58
|
border-radius: 1px;
|
|
60
|
-
|
|
59
|
+
|
|
61
60
|
/* Positioning */
|
|
62
61
|
position: absolute;
|
|
63
62
|
z-index: 1;
|
|
@@ -65,7 +64,7 @@ qgraph_css = """
|
|
|
65
64
|
left: 50%;
|
|
66
65
|
transform: translateX(-50%);
|
|
67
66
|
margin-bottom: 8px;
|
|
68
|
-
|
|
67
|
+
|
|
69
68
|
/* Tooltip Arrow */
|
|
70
69
|
width: 400px;
|
|
71
70
|
}
|
|
@@ -76,124 +75,128 @@ qgraph_css = """
|
|
|
76
75
|
"""
|
|
77
76
|
|
|
78
77
|
|
|
79
|
-
class NodeTiming:
|
|
80
|
-
|
|
81
|
-
def __init__(self, phase: str, time: float) -> object:
|
|
78
|
+
class NodeTiming: # noqa: D101
|
|
79
|
+
def __init__(self, phase: str, time: float) -> None: # noqa: D107
|
|
82
80
|
self.phase = phase
|
|
83
81
|
self.time = time
|
|
84
82
|
# percentage is determined later.
|
|
85
83
|
self.percentage = 0
|
|
86
84
|
|
|
87
|
-
def calculate_percentage(self, total_time: float) -> None:
|
|
85
|
+
def calculate_percentage(self, total_time: float) -> None: # noqa: D102
|
|
88
86
|
self.percentage = self.time / total_time
|
|
89
87
|
|
|
90
|
-
def combine_timing(
|
|
91
|
-
# TODO: can only add timings for same-phase nodes
|
|
92
|
-
total_time =
|
|
93
|
-
return NodeTiming(
|
|
88
|
+
def combine_timing(self, r: "NodeTiming") -> "NodeTiming": # noqa: D102
|
|
89
|
+
# TODO: can only add timings for same-phase nodes # noqa: TD002, TD003
|
|
90
|
+
total_time = self.time + r.time
|
|
91
|
+
return NodeTiming(self.phase, total_time)
|
|
94
92
|
|
|
95
93
|
|
|
96
|
-
class AllTimings:
|
|
97
|
-
|
|
98
|
-
def __init__(self):
|
|
94
|
+
class AllTimings: # noqa: D101
|
|
95
|
+
def __init__(self) -> None: # noqa: D107
|
|
99
96
|
self.phase_to_timings = {}
|
|
100
97
|
|
|
101
|
-
def add_node_timing(self, node_timing: NodeTiming):
|
|
98
|
+
def add_node_timing(self, node_timing: NodeTiming) -> None: # noqa: D102
|
|
102
99
|
if node_timing.phase in self.phase_to_timings:
|
|
103
100
|
self.phase_to_timings[node_timing.phase].append(node_timing)
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
else:
|
|
102
|
+
self.phase_to_timings[node_timing.phase] = [node_timing]
|
|
106
103
|
|
|
107
|
-
def get_phase_timings(self, phase: str):
|
|
104
|
+
def get_phase_timings(self, phase: str) -> list[NodeTiming]: # noqa: D102
|
|
108
105
|
return self.phase_to_timings[phase]
|
|
109
106
|
|
|
110
|
-
def get_summary_phase_timings(self, phase: str):
|
|
107
|
+
def get_summary_phase_timings(self, phase: str) -> NodeTiming: # noqa: D102
|
|
111
108
|
return reduce(NodeTiming.combine_timing, self.phase_to_timings[phase])
|
|
112
109
|
|
|
113
|
-
def get_phases(self):
|
|
110
|
+
def get_phases(self) -> list[NodeTiming]: # noqa: D102
|
|
114
111
|
phases = list(self.phase_to_timings.keys())
|
|
115
112
|
phases.sort(key=lambda x: (self.get_summary_phase_timings(x)).time)
|
|
116
113
|
phases.reverse()
|
|
117
114
|
return phases
|
|
118
115
|
|
|
119
|
-
def get_sum_of_all_timings(self):
|
|
116
|
+
def get_sum_of_all_timings(self) -> float: # noqa: D102
|
|
120
117
|
total_timing_sum = 0
|
|
121
|
-
for phase in self.phase_to_timings
|
|
118
|
+
for phase in self.phase_to_timings:
|
|
122
119
|
total_timing_sum += self.get_summary_phase_timings(phase).time
|
|
123
120
|
return total_timing_sum
|
|
124
121
|
|
|
125
122
|
|
|
126
|
-
def open_utf8(fpath: str, flags: str) -> object:
|
|
127
|
-
return open(
|
|
123
|
+
def open_utf8(fpath: str, flags: str) -> object: # noqa: D103
|
|
124
|
+
return Path(fpath).open(mode=flags, encoding="utf8")
|
|
128
125
|
|
|
129
126
|
|
|
130
|
-
def get_child_timings(top_node: object, query_timings: object) -> str:
|
|
131
|
-
node_timing = NodeTiming(top_node[
|
|
127
|
+
def get_child_timings(top_node: object, query_timings: object) -> str: # noqa: D103
|
|
128
|
+
node_timing = NodeTiming(top_node["operator_type"], float(top_node["operator_timing"]))
|
|
132
129
|
query_timings.add_node_timing(node_timing)
|
|
133
|
-
for child in top_node[
|
|
130
|
+
for child in top_node["children"]:
|
|
134
131
|
get_child_timings(child, query_timings)
|
|
135
132
|
|
|
136
133
|
|
|
137
|
-
def get_pink_shade_hex(fraction: float):
|
|
134
|
+
def get_pink_shade_hex(fraction: float) -> str: # noqa: D103
|
|
138
135
|
fraction = max(0, min(1, fraction))
|
|
139
|
-
|
|
136
|
+
|
|
140
137
|
# Define the RGB values for very light pink (almost white) and dark pink
|
|
141
138
|
light_pink = (255, 250, 250) # Very light pink
|
|
142
|
-
dark_pink = (255, 20, 147)
|
|
143
|
-
|
|
139
|
+
dark_pink = (255, 20, 147) # Dark pink
|
|
140
|
+
|
|
144
141
|
# Calculate the RGB values for the given fraction
|
|
145
142
|
r = int(light_pink[0] + (dark_pink[0] - light_pink[0]) * fraction)
|
|
146
143
|
g = int(light_pink[1] + (dark_pink[1] - light_pink[1]) * fraction)
|
|
147
144
|
b = int(light_pink[2] + (dark_pink[2] - light_pink[2]) * fraction)
|
|
148
|
-
|
|
145
|
+
|
|
149
146
|
# Return as hexadecimal color code
|
|
150
147
|
return f"#{r:02x}{g:02x}{b:02x}"
|
|
151
148
|
|
|
152
|
-
def get_node_body(name: str, result: str, cpu_time: float, card: int, est: int, width: int, extra_info: str) -> str:
|
|
153
|
-
node_style = f"background-color: {get_pink_shade_hex(float(result)/cpu_time)};"
|
|
154
149
|
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
def get_node_body(name: str, result: str, cpu_time: float, card: int, est: int, width: int, extra_info: str) -> str: # noqa: D103
|
|
151
|
+
node_style = f"background-color: {get_pink_shade_hex(float(result) / cpu_time)};"
|
|
152
|
+
|
|
153
|
+
body = f'<span class="tf-nc custom-tooltip" style="{node_style}">'
|
|
154
|
+
body += '<div class="node-body">'
|
|
157
155
|
new_name = "BRIDGE" if (name == "INVALID") else name.replace("_", " ")
|
|
158
156
|
formatted_num = f"{float(result):.4f}"
|
|
159
157
|
body += f"<p><b>{new_name}</b> </p><p>time: {formatted_num} seconds</p>"
|
|
160
|
-
body += f
|
|
161
|
-
if
|
|
158
|
+
body += f'<span class="tooltip-text"> {extra_info} </span>'
|
|
159
|
+
if width > 0:
|
|
162
160
|
body += f"<p>cardinality: {card}</p>"
|
|
163
161
|
body += f"<p>estimate: {est}</p>"
|
|
164
162
|
body += f"<p>width: {width} bytes</p>"
|
|
165
|
-
# TODO: Expand on timing. Usually available from a detailed profiling
|
|
163
|
+
# TODO: Expand on timing. Usually available from a detailed profiling # noqa: TD002, TD003
|
|
166
164
|
body += "</div>"
|
|
167
165
|
body += "</span>"
|
|
168
166
|
return body
|
|
169
167
|
|
|
170
168
|
|
|
171
|
-
def generate_tree_recursive(json_graph: object, cpu_time: float) -> str:
|
|
169
|
+
def generate_tree_recursive(json_graph: object, cpu_time: float) -> str: # noqa: D103
|
|
172
170
|
node_prefix_html = "<li>"
|
|
173
171
|
node_suffix_html = "</li>"
|
|
174
172
|
|
|
175
173
|
extra_info = ""
|
|
176
174
|
estimate = 0
|
|
177
|
-
for key in json_graph[
|
|
178
|
-
value = json_graph[
|
|
179
|
-
if
|
|
175
|
+
for key in json_graph["extra_info"]:
|
|
176
|
+
value = json_graph["extra_info"][key]
|
|
177
|
+
if key == "Estimated Cardinality":
|
|
180
178
|
estimate = int(value)
|
|
181
179
|
else:
|
|
182
180
|
extra_info += f"{key}: {value} <br>"
|
|
183
181
|
cardinality = json_graph["operator_cardinality"]
|
|
184
|
-
width = int(json_graph["result_set_size"]/max(1,cardinality))
|
|
182
|
+
width = int(json_graph["result_set_size"] / max(1, cardinality))
|
|
185
183
|
|
|
186
184
|
# get rid of some typically long names
|
|
187
185
|
extra_info = re.sub(r"__internal_\s*", "__", extra_info)
|
|
188
186
|
extra_info = re.sub(r"compress_integral\s*", "compress", extra_info)
|
|
189
187
|
|
|
190
|
-
node_body = get_node_body(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
188
|
+
node_body = get_node_body(
|
|
189
|
+
json_graph["operator_type"],
|
|
190
|
+
json_graph["operator_timing"],
|
|
191
|
+
cpu_time,
|
|
192
|
+
cardinality,
|
|
193
|
+
estimate,
|
|
194
|
+
width,
|
|
195
|
+
re.sub(r",\s*", ", ", extra_info),
|
|
196
|
+
)
|
|
194
197
|
|
|
195
198
|
children_html = ""
|
|
196
|
-
if len(json_graph[
|
|
199
|
+
if len(json_graph["children"]) >= 1:
|
|
197
200
|
children_html += "<ul>"
|
|
198
201
|
for child in json_graph["children"]:
|
|
199
202
|
children_html += generate_tree_recursive(child, cpu_time)
|
|
@@ -202,12 +205,12 @@ def generate_tree_recursive(json_graph: object, cpu_time: float) -> str:
|
|
|
202
205
|
|
|
203
206
|
|
|
204
207
|
# For generating the table in the top left.
|
|
205
|
-
def generate_timing_html(graph_json: object, query_timings: object) -> object:
|
|
208
|
+
def generate_timing_html(graph_json: object, query_timings: object) -> object: # noqa: D103
|
|
206
209
|
json_graph = json.loads(graph_json)
|
|
207
210
|
gather_timing_information(json_graph, query_timings)
|
|
208
|
-
total_time = float(json_graph.get(
|
|
211
|
+
total_time = float(json_graph.get("operator_timing") or json_graph.get("latency"))
|
|
209
212
|
table_head = """
|
|
210
|
-
<table class=\"styled-table\">
|
|
213
|
+
<table class=\"styled-table\">
|
|
211
214
|
<thead>
|
|
212
215
|
<tr>
|
|
213
216
|
<th>Phase</th>
|
|
@@ -224,7 +227,7 @@ def generate_timing_html(graph_json: object, query_timings: object) -> object:
|
|
|
224
227
|
all_phases = query_timings.get_phases()
|
|
225
228
|
query_timings.add_node_timing(NodeTiming("TOTAL TIME", total_time))
|
|
226
229
|
query_timings.add_node_timing(NodeTiming("Execution Time", execution_time))
|
|
227
|
-
all_phases = ["TOTAL TIME", "Execution Time"
|
|
230
|
+
all_phases = ["TOTAL TIME", "Execution Time", *all_phases]
|
|
228
231
|
for phase in all_phases:
|
|
229
232
|
summarized_phase = query_timings.get_summary_phase_timings(phase)
|
|
230
233
|
summarized_phase.calculate_percentage(total_time)
|
|
@@ -240,55 +243,48 @@ def generate_timing_html(graph_json: object, query_timings: object) -> object:
|
|
|
240
243
|
return table_head + table_body
|
|
241
244
|
|
|
242
245
|
|
|
243
|
-
def generate_tree_html(graph_json: object) -> str:
|
|
246
|
+
def generate_tree_html(graph_json: object) -> str: # noqa: D103
|
|
244
247
|
json_graph = json.loads(graph_json)
|
|
245
|
-
cpu_time = float(json_graph[
|
|
246
|
-
tree_prefix =
|
|
248
|
+
cpu_time = float(json_graph["cpu_time"])
|
|
249
|
+
tree_prefix = '<div class="tf-tree tf-gap-sm"> \n <ul>'
|
|
247
250
|
tree_suffix = "</ul> </div>"
|
|
248
251
|
# first level of json is general overview
|
|
249
|
-
#
|
|
250
|
-
tree_body = generate_tree_recursive(json_graph[
|
|
252
|
+
# TODO: make sure json output first level always has only 1 level # noqa: TD002, TD003
|
|
253
|
+
tree_body = generate_tree_recursive(json_graph["children"][0], cpu_time)
|
|
251
254
|
return tree_prefix + tree_body + tree_suffix
|
|
252
255
|
|
|
253
256
|
|
|
254
|
-
def generate_ipython(json_input: str) -> str:
|
|
257
|
+
def generate_ipython(json_input: str) -> str: # noqa: D103
|
|
255
258
|
from IPython.core.display import HTML
|
|
256
259
|
|
|
257
|
-
html_output = generate_html(json_input, False)
|
|
260
|
+
html_output = generate_html(json_input, False) # noqa: F821
|
|
258
261
|
|
|
259
|
-
return HTML(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
html_output['chart_script']).replace(
|
|
266
|
-
'${LIBRARIES}', html_output['libraries']))
|
|
262
|
+
return HTML(
|
|
263
|
+
('\n ${CSS}\n ${LIBRARIES}\n <div class="chart" id="query-profile"></div>\n ${CHART_SCRIPT}\n ')
|
|
264
|
+
.replace("${CSS}", html_output["css"])
|
|
265
|
+
.replace("${CHART_SCRIPT}", html_output["chart_script"])
|
|
266
|
+
.replace("${LIBRARIES}", html_output["libraries"])
|
|
267
|
+
)
|
|
267
268
|
|
|
268
269
|
|
|
269
|
-
def generate_style_html(graph_json: str, include_meta_info: bool) -> None:
|
|
270
|
-
treeflex_css =
|
|
270
|
+
def generate_style_html(graph_json: str, include_meta_info: bool) -> None: # noqa: D103, FBT001
|
|
271
|
+
treeflex_css = '<link rel="stylesheet" href="https://unpkg.com/treeflex/dist/css/treeflex.css">\n'
|
|
271
272
|
css = "<style>\n"
|
|
272
273
|
css += qgraph_css + "\n"
|
|
273
274
|
css += "</style>\n"
|
|
274
|
-
return {
|
|
275
|
-
'treeflex_css': treeflex_css,
|
|
276
|
-
'duckdb_css': css,
|
|
277
|
-
'libraries': '',
|
|
278
|
-
'chart_script': ''
|
|
279
|
-
}
|
|
275
|
+
return {"treeflex_css": treeflex_css, "duckdb_css": css, "libraries": "", "chart_script": ""}
|
|
280
276
|
|
|
281
277
|
|
|
282
|
-
def gather_timing_information(json: str, query_timings: object) -> None:
|
|
278
|
+
def gather_timing_information(json: str, query_timings: object) -> None: # noqa: D103
|
|
283
279
|
# add up all of the times
|
|
284
280
|
# measure each time as a percentage of the total time.
|
|
285
281
|
# then you can return a list of [phase, time, percentage]
|
|
286
|
-
get_child_timings(json[
|
|
282
|
+
get_child_timings(json["children"][0], query_timings)
|
|
287
283
|
|
|
288
284
|
|
|
289
|
-
def translate_json_to_html(input_file: str, output_file: str) -> None:
|
|
285
|
+
def translate_json_to_html(input_file: str, output_file: str) -> None: # noqa: D103
|
|
290
286
|
query_timings = AllTimings()
|
|
291
|
-
with open_utf8(input_file,
|
|
287
|
+
with open_utf8(input_file, "r") as f:
|
|
292
288
|
text = f.read()
|
|
293
289
|
|
|
294
290
|
html_output = generate_style_html(text, True)
|
|
@@ -317,23 +313,22 @@ def translate_json_to_html(input_file: str, output_file: str) -> None:
|
|
|
317
313
|
</body>
|
|
318
314
|
</html>
|
|
319
315
|
"""
|
|
320
|
-
html = html.replace("${TREEFLEX_CSS}", html_output[
|
|
321
|
-
html = html.replace("${DUCKDB_CSS}", html_output[
|
|
316
|
+
html = html.replace("${TREEFLEX_CSS}", html_output["treeflex_css"])
|
|
317
|
+
html = html.replace("${DUCKDB_CSS}", html_output["duckdb_css"])
|
|
322
318
|
html = html.replace("${TIMING_TABLE}", timing_table)
|
|
323
|
-
html = html.replace(
|
|
319
|
+
html = html.replace("${TREE}", tree_output)
|
|
324
320
|
f.write(html)
|
|
325
321
|
|
|
326
322
|
|
|
327
|
-
def main() -> None:
|
|
328
|
-
if sys.version_info[0] < 3:
|
|
329
|
-
print("Please use python3")
|
|
330
|
-
exit(1)
|
|
323
|
+
def main() -> None: # noqa: D103
|
|
331
324
|
parser = argparse.ArgumentParser(
|
|
332
|
-
prog=
|
|
333
|
-
description=
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
parser.add_argument(
|
|
325
|
+
prog="Query Graph Generator",
|
|
326
|
+
description="""Given a json profile output, generate a html file showing the query graph and
|
|
327
|
+
timings of operators""",
|
|
328
|
+
)
|
|
329
|
+
parser.add_argument("profile_input", help="profile input in json")
|
|
330
|
+
parser.add_argument("--out", required=False, default=False)
|
|
331
|
+
parser.add_argument("--open", required=False, action="store_true", default=True)
|
|
337
332
|
args = parser.parse_args()
|
|
338
333
|
|
|
339
334
|
input = args.profile_input
|
|
@@ -356,8 +351,8 @@ def main() -> None:
|
|
|
356
351
|
translate_json_to_html(input, output)
|
|
357
352
|
|
|
358
353
|
if open_output:
|
|
359
|
-
webbrowser.open(
|
|
354
|
+
webbrowser.open(f"file://{Path(output).resolve()}", new=2)
|
|
360
355
|
|
|
361
356
|
|
|
362
|
-
if __name__ ==
|
|
357
|
+
if __name__ == "__main__":
|
|
363
358
|
main()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""DuckDB's SQL types."""
|
|
2
|
+
|
|
3
|
+
from _duckdb._sqltypes import (
|
|
4
|
+
BIGINT,
|
|
5
|
+
BIT,
|
|
6
|
+
BLOB,
|
|
7
|
+
BOOLEAN,
|
|
8
|
+
DATE,
|
|
9
|
+
DOUBLE,
|
|
10
|
+
FLOAT,
|
|
11
|
+
HUGEINT,
|
|
12
|
+
INTEGER,
|
|
13
|
+
INTERVAL,
|
|
14
|
+
SMALLINT,
|
|
15
|
+
SQLNULL,
|
|
16
|
+
TIME,
|
|
17
|
+
TIME_TZ,
|
|
18
|
+
TIMESTAMP,
|
|
19
|
+
TIMESTAMP_MS,
|
|
20
|
+
TIMESTAMP_NS,
|
|
21
|
+
TIMESTAMP_S,
|
|
22
|
+
TIMESTAMP_TZ,
|
|
23
|
+
TINYINT,
|
|
24
|
+
UBIGINT,
|
|
25
|
+
UHUGEINT,
|
|
26
|
+
UINTEGER,
|
|
27
|
+
USMALLINT,
|
|
28
|
+
UTINYINT,
|
|
29
|
+
UUID,
|
|
30
|
+
VARCHAR,
|
|
31
|
+
DuckDBPyType,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"BIGINT",
|
|
36
|
+
"BIT",
|
|
37
|
+
"BLOB",
|
|
38
|
+
"BOOLEAN",
|
|
39
|
+
"DATE",
|
|
40
|
+
"DOUBLE",
|
|
41
|
+
"FLOAT",
|
|
42
|
+
"HUGEINT",
|
|
43
|
+
"INTEGER",
|
|
44
|
+
"INTERVAL",
|
|
45
|
+
"SMALLINT",
|
|
46
|
+
"SQLNULL",
|
|
47
|
+
"TIME",
|
|
48
|
+
"TIMESTAMP",
|
|
49
|
+
"TIMESTAMP_MS",
|
|
50
|
+
"TIMESTAMP_NS",
|
|
51
|
+
"TIMESTAMP_S",
|
|
52
|
+
"TIMESTAMP_TZ",
|
|
53
|
+
"TIME_TZ",
|
|
54
|
+
"TINYINT",
|
|
55
|
+
"UBIGINT",
|
|
56
|
+
"UHUGEINT",
|
|
57
|
+
"UINTEGER",
|
|
58
|
+
"USMALLINT",
|
|
59
|
+
"UTINYINT",
|
|
60
|
+
"UUID",
|
|
61
|
+
"VARCHAR",
|
|
62
|
+
"DuckDBPyType",
|
|
63
|
+
]
|
duckdb/typing/__init__.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"""DuckDB's SQL types. DEPRECATED. Please use `duckdb.sqltypes` instead."""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
from duckdb.sqltypes import (
|
|
3
6
|
BIGINT,
|
|
4
7
|
BIT,
|
|
5
8
|
BLOB,
|
|
@@ -8,29 +11,29 @@ from _duckdb.typing import (
|
|
|
8
11
|
DOUBLE,
|
|
9
12
|
FLOAT,
|
|
10
13
|
HUGEINT,
|
|
11
|
-
UHUGEINT,
|
|
12
14
|
INTEGER,
|
|
13
15
|
INTERVAL,
|
|
14
16
|
SMALLINT,
|
|
15
17
|
SQLNULL,
|
|
16
18
|
TIME,
|
|
19
|
+
TIME_TZ,
|
|
17
20
|
TIMESTAMP,
|
|
18
21
|
TIMESTAMP_MS,
|
|
19
22
|
TIMESTAMP_NS,
|
|
20
23
|
TIMESTAMP_S,
|
|
21
24
|
TIMESTAMP_TZ,
|
|
22
|
-
TIME_TZ,
|
|
23
25
|
TINYINT,
|
|
24
26
|
UBIGINT,
|
|
27
|
+
UHUGEINT,
|
|
25
28
|
UINTEGER,
|
|
26
29
|
USMALLINT,
|
|
27
30
|
UTINYINT,
|
|
28
31
|
UUID,
|
|
29
|
-
VARCHAR
|
|
32
|
+
VARCHAR,
|
|
33
|
+
DuckDBPyType,
|
|
30
34
|
)
|
|
31
35
|
|
|
32
36
|
__all__ = [
|
|
33
|
-
"DuckDBPyType",
|
|
34
37
|
"BIGINT",
|
|
35
38
|
"BIT",
|
|
36
39
|
"BLOB",
|
|
@@ -39,7 +42,6 @@ __all__ = [
|
|
|
39
42
|
"DOUBLE",
|
|
40
43
|
"FLOAT",
|
|
41
44
|
"HUGEINT",
|
|
42
|
-
"UHUGEINT",
|
|
43
45
|
"INTEGER",
|
|
44
46
|
"INTERVAL",
|
|
45
47
|
"SMALLINT",
|
|
@@ -53,9 +55,17 @@ __all__ = [
|
|
|
53
55
|
"TIME_TZ",
|
|
54
56
|
"TINYINT",
|
|
55
57
|
"UBIGINT",
|
|
58
|
+
"UHUGEINT",
|
|
56
59
|
"UINTEGER",
|
|
57
60
|
"USMALLINT",
|
|
58
61
|
"UTINYINT",
|
|
59
62
|
"UUID",
|
|
60
|
-
"VARCHAR"
|
|
63
|
+
"VARCHAR",
|
|
64
|
+
"DuckDBPyType",
|
|
61
65
|
]
|
|
66
|
+
|
|
67
|
+
warnings.warn(
|
|
68
|
+
"`duckdb.typing` is deprecated and will be removed in a future version. Please use `duckdb.sqltypes` instead.",
|
|
69
|
+
DeprecationWarning,
|
|
70
|
+
stacklevel=2,
|
|
71
|
+
)
|
duckdb/udf.py
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# ruff: noqa: D100
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def vectorized(func: typing.Callable[..., typing.Any]) -> typing.Callable[..., typing.Any]:
|
|
6
|
+
"""Decorate a function with annotated function parameters.
|
|
7
|
+
|
|
8
|
+
This allows DuckDB to infer that the function should be provided with pyarrow arrays and should expect
|
|
9
|
+
pyarrow array(s) as output.
|
|
4
10
|
"""
|
|
5
|
-
from inspect import signature
|
|
6
11
|
import types
|
|
12
|
+
from inspect import signature
|
|
7
13
|
|
|
8
14
|
new_func = types.FunctionType(func.__code__, func.__globals__, func.__name__, func.__defaults__, func.__closure__)
|
|
9
15
|
# Construct the annotations:
|
|
@@ -11,7 +17,6 @@ def vectorized(func):
|
|
|
11
17
|
|
|
12
18
|
new_annotations = {}
|
|
13
19
|
sig = signature(func)
|
|
14
|
-
sig.parameters
|
|
15
20
|
for param in sig.parameters:
|
|
16
21
|
new_annotations[param] = pa.lib.ChunkedArray
|
|
17
22
|
|
duckdb/value/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# noqa: D104
|