polars-df 0.21.1 → 0.23.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Cargo.lock +120 -90
- data/Cargo.toml +3 -0
- data/README.md +20 -7
- data/ext/polars/Cargo.toml +18 -12
- data/ext/polars/src/batched_csv.rs +4 -4
- data/ext/polars/src/catalog/unity.rs +96 -94
- data/ext/polars/src/conversion/any_value.rs +39 -37
- data/ext/polars/src/conversion/chunked_array.rs +36 -29
- data/ext/polars/src/conversion/datetime.rs +11 -0
- data/ext/polars/src/conversion/mod.rs +244 -51
- data/ext/polars/src/dataframe/construction.rs +5 -17
- data/ext/polars/src/dataframe/export.rs +17 -15
- data/ext/polars/src/dataframe/general.rs +15 -17
- data/ext/polars/src/dataframe/io.rs +1 -2
- data/ext/polars/src/dataframe/mod.rs +25 -1
- data/ext/polars/src/dataframe/serde.rs +23 -8
- data/ext/polars/src/exceptions.rs +8 -5
- data/ext/polars/src/expr/datatype.rs +4 -4
- data/ext/polars/src/expr/datetime.rs +22 -28
- data/ext/polars/src/expr/general.rs +3 -10
- data/ext/polars/src/expr/list.rs +8 -24
- data/ext/polars/src/expr/meta.rs +4 -6
- data/ext/polars/src/expr/mod.rs +2 -0
- data/ext/polars/src/expr/name.rs +11 -14
- data/ext/polars/src/expr/serde.rs +28 -0
- data/ext/polars/src/expr/string.rs +5 -10
- data/ext/polars/src/file.rs +20 -14
- data/ext/polars/src/functions/business.rs +0 -1
- data/ext/polars/src/functions/io.rs +7 -4
- data/ext/polars/src/functions/lazy.rs +7 -6
- data/ext/polars/src/functions/meta.rs +3 -3
- data/ext/polars/src/functions/string_cache.rs +3 -3
- data/ext/polars/src/interop/arrow/to_ruby.rs +3 -3
- data/ext/polars/src/interop/numo/numo_rs.rs +4 -3
- data/ext/polars/src/io/mod.rs +23 -3
- data/ext/polars/src/lazyframe/general.rs +35 -50
- data/ext/polars/src/lazyframe/mod.rs +16 -1
- data/ext/polars/src/lazyframe/optflags.rs +57 -0
- data/ext/polars/src/lazyframe/serde.rs +27 -3
- data/ext/polars/src/lib.rs +144 -19
- data/ext/polars/src/map/dataframe.rs +18 -15
- data/ext/polars/src/map/lazy.rs +6 -5
- data/ext/polars/src/map/series.rs +7 -6
- data/ext/polars/src/on_startup.rs +12 -5
- data/ext/polars/src/rb_modules.rs +2 -2
- data/ext/polars/src/series/aggregation.rs +49 -29
- data/ext/polars/src/series/construction.rs +2 -0
- data/ext/polars/src/series/export.rs +38 -33
- data/ext/polars/src/series/general.rs +69 -31
- data/ext/polars/src/series/mod.rs +29 -4
- data/lib/polars/array_expr.rb +1 -1
- data/lib/polars/data_frame.rb +119 -15
- data/lib/polars/data_types.rb +23 -6
- data/lib/polars/date_time_expr.rb +36 -15
- data/lib/polars/expr.rb +41 -32
- data/lib/polars/functions/business.rb +95 -0
- data/lib/polars/functions/lazy.rb +1 -1
- data/lib/polars/iceberg_dataset.rb +113 -0
- data/lib/polars/io/iceberg.rb +34 -0
- data/lib/polars/io/ipc.rb +28 -49
- data/lib/polars/io/parquet.rb +7 -4
- data/lib/polars/io/scan_options.rb +12 -3
- data/lib/polars/io/utils.rb +17 -0
- data/lib/polars/lazy_frame.rb +97 -10
- data/lib/polars/list_expr.rb +21 -13
- data/lib/polars/list_name_space.rb +33 -21
- data/lib/polars/meta_expr.rb +25 -0
- data/lib/polars/query_opt_flags.rb +50 -0
- data/lib/polars/scan_cast_options.rb +23 -1
- data/lib/polars/schema.rb +1 -1
- data/lib/polars/selectors.rb +8 -8
- data/lib/polars/series.rb +26 -2
- data/lib/polars/string_expr.rb +27 -28
- data/lib/polars/string_name_space.rb +18 -5
- data/lib/polars/utils/convert.rb +2 -2
- data/lib/polars/utils/serde.rb +17 -0
- data/lib/polars/utils/various.rb +4 -0
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +6 -0
- metadata +10 -1
data/ext/polars/Cargo.toml
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "polars"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.23.0"
|
|
4
4
|
license = "MIT"
|
|
5
5
|
authors = ["Andrew Kane <andrew@ankane.org>"]
|
|
6
6
|
edition = "2024"
|
|
7
|
-
rust-version = "1.
|
|
7
|
+
rust-version = "1.89.0"
|
|
8
8
|
publish = false
|
|
9
9
|
|
|
10
10
|
[lib]
|
|
@@ -12,25 +12,27 @@ crate-type = ["cdylib"]
|
|
|
12
12
|
|
|
13
13
|
[dependencies]
|
|
14
14
|
ahash = "0.8"
|
|
15
|
-
arrow = { package = "polars-arrow", version = "=0.
|
|
15
|
+
arrow = { package = "polars-arrow", version = "=0.52.0" }
|
|
16
16
|
bytes = "1"
|
|
17
17
|
chrono = "0.4"
|
|
18
18
|
either = "1.8"
|
|
19
|
-
magnus = {
|
|
19
|
+
magnus = { version = "0.8", features = ["chrono"] }
|
|
20
20
|
num-traits = "0.2"
|
|
21
|
-
polars-
|
|
22
|
-
polars-
|
|
23
|
-
polars-
|
|
24
|
-
polars-
|
|
25
|
-
polars-
|
|
26
|
-
polars-
|
|
27
|
-
polars-
|
|
21
|
+
polars-compute = "=0.52.0"
|
|
22
|
+
polars-core = "=0.52.0"
|
|
23
|
+
polars-dtype = "=0.52.0"
|
|
24
|
+
polars-error = "=0.52.0"
|
|
25
|
+
polars-io = "=0.52.0"
|
|
26
|
+
polars-lazy = { version = "=0.52.0", features = ["catalog"] }
|
|
27
|
+
polars-plan = "=0.52.0"
|
|
28
|
+
polars-parquet = "=0.52.0"
|
|
29
|
+
polars-utils = "=0.52.0"
|
|
28
30
|
rayon = "1.9"
|
|
29
31
|
regex = "1"
|
|
30
32
|
serde_json = "1"
|
|
31
33
|
|
|
32
34
|
[dependencies.polars]
|
|
33
|
-
version = "=0.
|
|
35
|
+
version = "=0.52.0"
|
|
34
36
|
features = [
|
|
35
37
|
"abs",
|
|
36
38
|
"approx_unique",
|
|
@@ -141,3 +143,7 @@ jemallocator = { version = "0.5", features = ["disable_initial_exec_tls"] }
|
|
|
141
143
|
|
|
142
144
|
[target.'cfg(not(any(target_os = "linux", target_os = "windows")))'.dependencies]
|
|
143
145
|
mimalloc = { version = "0.1", default-features = false }
|
|
146
|
+
|
|
147
|
+
[features]
|
|
148
|
+
default = []
|
|
149
|
+
serialize_binary = []
|
|
@@ -2,7 +2,7 @@ use std::cell::RefCell;
|
|
|
2
2
|
use std::path::PathBuf;
|
|
3
3
|
use std::sync::Mutex;
|
|
4
4
|
|
|
5
|
-
use magnus::{RArray, Value, prelude::*};
|
|
5
|
+
use magnus::{RArray, Ruby, Value, prelude::*};
|
|
6
6
|
use polars::io::RowIndex;
|
|
7
7
|
use polars::io::csv::read::OwnedBatchedCsvReader;
|
|
8
8
|
use polars::io::mmap::MmapBytesReader;
|
|
@@ -124,8 +124,8 @@ impl RbBatchedCsv {
|
|
|
124
124
|
})
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
pub fn next_batches(&
|
|
128
|
-
let reader = &
|
|
127
|
+
pub fn next_batches(ruby: &Ruby, rb_self: &Self, n: usize) -> RbResult<Option<RArray>> {
|
|
128
|
+
let reader = &rb_self.reader;
|
|
129
129
|
let batches = reader
|
|
130
130
|
.borrow()
|
|
131
131
|
.lock()
|
|
@@ -133,6 +133,6 @@ impl RbBatchedCsv {
|
|
|
133
133
|
.next_batches(n)
|
|
134
134
|
.map_err(RbPolarsErr::from)?;
|
|
135
135
|
|
|
136
|
-
Ok(batches.map(|batches|
|
|
136
|
+
Ok(batches.map(|batches| ruby.ary_from_iter(batches.into_iter().map(RbDataFrame::from))))
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use std::str::FromStr;
|
|
2
2
|
|
|
3
3
|
use magnus::value::{Lazy, ReprValue};
|
|
4
|
-
use magnus::{IntoValue, Module,
|
|
4
|
+
use magnus::{IntoValue, Module, RClass, RHash, RModule, Ruby, Value};
|
|
5
5
|
use polars::prelude::{PlHashMap, PlSmallStr, Schema};
|
|
6
6
|
use polars_io::catalog::unity::client::{CatalogClient, CatalogClientBuilder};
|
|
7
7
|
use polars_io::catalog::unity::models::{
|
|
@@ -85,15 +85,15 @@ impl RbCatalogClient {
|
|
|
85
85
|
builder.build().map(RbCatalogClient).map_err(to_rb_err)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
pub fn list_catalogs(&
|
|
88
|
+
pub fn list_catalogs(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
|
89
89
|
let v = pl_async::get_runtime()
|
|
90
|
-
.block_in_place_on(
|
|
90
|
+
.block_in_place_on(rb_self.client().list_catalogs())
|
|
91
91
|
.map_err(to_rb_err)?;
|
|
92
92
|
|
|
93
93
|
let mut opt_err = None;
|
|
94
94
|
|
|
95
|
-
let out =
|
|
96
|
-
let v = catalog_info_to_rbobject(x);
|
|
95
|
+
let out = ruby.ary_from_iter(v.into_iter().map(|x| {
|
|
96
|
+
let v = catalog_info_to_rbobject(ruby, x);
|
|
97
97
|
if let Ok(v) = v {
|
|
98
98
|
Some(v)
|
|
99
99
|
} else {
|
|
@@ -104,18 +104,18 @@ impl RbCatalogClient {
|
|
|
104
104
|
|
|
105
105
|
opt_err.transpose()?;
|
|
106
106
|
|
|
107
|
-
Ok(out.
|
|
107
|
+
Ok(out.as_value())
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
pub fn list_namespaces(&
|
|
110
|
+
pub fn list_namespaces(ruby: &Ruby, rb_self: &Self, catalog_name: String) -> RbResult<Value> {
|
|
111
111
|
let v = pl_async::get_runtime()
|
|
112
|
-
.block_in_place_on(
|
|
112
|
+
.block_in_place_on(rb_self.client().list_namespaces(&catalog_name))
|
|
113
113
|
.map_err(to_rb_err)?;
|
|
114
114
|
|
|
115
115
|
let mut opt_err = None;
|
|
116
116
|
|
|
117
|
-
let out =
|
|
118
|
-
let v = namespace_info_to_rbobject(x);
|
|
117
|
+
let out = ruby.ary_from_iter(v.into_iter().map(|x| {
|
|
118
|
+
let v = namespace_info_to_rbobject(ruby, x);
|
|
119
119
|
match v {
|
|
120
120
|
Ok(v) => Some(v),
|
|
121
121
|
Err(_) => {
|
|
@@ -127,27 +127,33 @@ impl RbCatalogClient {
|
|
|
127
127
|
|
|
128
128
|
opt_err.transpose()?;
|
|
129
129
|
|
|
130
|
-
Ok(out.
|
|
130
|
+
Ok(out.as_value())
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
pub fn list_tables(
|
|
133
|
+
pub fn list_tables(
|
|
134
|
+
ruby: &Ruby,
|
|
135
|
+
rb_self: &Self,
|
|
136
|
+
catalog_name: String,
|
|
137
|
+
namespace: String,
|
|
138
|
+
) -> RbResult<Value> {
|
|
134
139
|
let v = pl_async::get_runtime()
|
|
135
|
-
.block_in_place_on(
|
|
140
|
+
.block_in_place_on(rb_self.client().list_tables(&catalog_name, &namespace))
|
|
136
141
|
.map_err(to_rb_err)?;
|
|
137
142
|
|
|
138
143
|
let mut opt_err = None;
|
|
139
144
|
|
|
140
|
-
let out =
|
|
141
|
-
|
|
145
|
+
let out = ruby
|
|
146
|
+
.ary_from_iter(v.into_iter().map(|table_info| {
|
|
147
|
+
let v = table_info_to_rbobject(ruby, table_info);
|
|
142
148
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
if let Ok(v) = v {
|
|
150
|
+
Some(v)
|
|
151
|
+
} else {
|
|
152
|
+
opt_err.replace(v);
|
|
153
|
+
None
|
|
154
|
+
}
|
|
155
|
+
}))
|
|
156
|
+
.as_value();
|
|
151
157
|
|
|
152
158
|
opt_err.transpose()?;
|
|
153
159
|
|
|
@@ -155,36 +161,39 @@ impl RbCatalogClient {
|
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
pub fn get_table_info(
|
|
158
|
-
&
|
|
164
|
+
ruby: &Ruby,
|
|
165
|
+
rb_self: &Self,
|
|
159
166
|
table_name: String,
|
|
160
167
|
catalog_name: String,
|
|
161
168
|
namespace: String,
|
|
162
169
|
) -> RbResult<Value> {
|
|
163
170
|
let table_info = pl_async::get_runtime()
|
|
164
|
-
.block_in_place_on(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
.block_in_place_on(rb_self.client().get_table_info(
|
|
172
|
+
&table_name,
|
|
173
|
+
&catalog_name,
|
|
174
|
+
&namespace,
|
|
175
|
+
))
|
|
168
176
|
.map_err(to_rb_err)?;
|
|
169
177
|
|
|
170
|
-
table_info_to_rbobject(table_info)
|
|
178
|
+
table_info_to_rbobject(ruby, table_info)
|
|
171
179
|
}
|
|
172
180
|
|
|
173
181
|
pub fn create_catalog(
|
|
174
|
-
&
|
|
182
|
+
ruby: &Ruby,
|
|
183
|
+
rb_self: &Self,
|
|
175
184
|
catalog_name: String,
|
|
176
185
|
comment: Option<String>,
|
|
177
186
|
storage_root: Option<String>,
|
|
178
187
|
) -> RbResult<Value> {
|
|
179
188
|
let catalog_info = pl_async::get_runtime()
|
|
180
|
-
.block_in_place_on(
|
|
189
|
+
.block_in_place_on(rb_self.client().create_catalog(
|
|
181
190
|
&catalog_name,
|
|
182
191
|
comment.as_deref(),
|
|
183
192
|
storage_root.as_deref(),
|
|
184
193
|
))
|
|
185
194
|
.map_err(to_rb_err)?;
|
|
186
195
|
|
|
187
|
-
catalog_info_to_rbobject(catalog_info)
|
|
196
|
+
catalog_info_to_rbobject(ruby, catalog_info)
|
|
188
197
|
}
|
|
189
198
|
|
|
190
199
|
pub fn delete_catalog(&self, catalog_name: String, force: bool) -> RbResult<()> {
|
|
@@ -194,14 +203,15 @@ impl RbCatalogClient {
|
|
|
194
203
|
}
|
|
195
204
|
|
|
196
205
|
pub fn create_namespace(
|
|
197
|
-
&
|
|
206
|
+
ruby: &Ruby,
|
|
207
|
+
rb_self: &Self,
|
|
198
208
|
catalog_name: String,
|
|
199
209
|
namespace: String,
|
|
200
210
|
comment: Option<String>,
|
|
201
211
|
storage_root: Option<String>,
|
|
202
212
|
) -> RbResult<Value> {
|
|
203
213
|
let namespace_info = pl_async::get_runtime()
|
|
204
|
-
.block_in_place_on(
|
|
214
|
+
.block_in_place_on(rb_self.client().create_namespace(
|
|
205
215
|
&catalog_name,
|
|
206
216
|
&namespace,
|
|
207
217
|
comment.as_deref(),
|
|
@@ -209,7 +219,7 @@ impl RbCatalogClient {
|
|
|
209
219
|
))
|
|
210
220
|
.map_err(to_rb_err)?;
|
|
211
221
|
|
|
212
|
-
namespace_info_to_rbobject(namespace_info)
|
|
222
|
+
namespace_info_to_rbobject(ruby, namespace_info)
|
|
213
223
|
}
|
|
214
224
|
|
|
215
225
|
pub fn delete_namespace(
|
|
@@ -228,7 +238,8 @@ impl RbCatalogClient {
|
|
|
228
238
|
|
|
229
239
|
#[allow(clippy::too_many_arguments)]
|
|
230
240
|
pub fn create_table(
|
|
231
|
-
&
|
|
241
|
+
ruby: &Ruby,
|
|
242
|
+
rb_self: &Self,
|
|
232
243
|
catalog_name: String,
|
|
233
244
|
namespace: String,
|
|
234
245
|
table_name: String,
|
|
@@ -241,7 +252,7 @@ impl RbCatalogClient {
|
|
|
241
252
|
) -> RbResult<Value> {
|
|
242
253
|
let table_info = pl_async::get_runtime()
|
|
243
254
|
.block_in_place_on(
|
|
244
|
-
|
|
255
|
+
rb_self.client().create_table(
|
|
245
256
|
&catalog_name,
|
|
246
257
|
&namespace,
|
|
247
258
|
&table_name,
|
|
@@ -261,7 +272,7 @@ impl RbCatalogClient {
|
|
|
261
272
|
)
|
|
262
273
|
.map_err(to_rb_err)?;
|
|
263
274
|
|
|
264
|
-
table_info_to_rbobject(table_info)
|
|
275
|
+
table_info_to_rbobject(ruby, table_info)
|
|
265
276
|
}
|
|
266
277
|
|
|
267
278
|
pub fn delete_table(
|
|
@@ -278,8 +289,8 @@ impl RbCatalogClient {
|
|
|
278
289
|
.map_err(to_rb_err)
|
|
279
290
|
}
|
|
280
291
|
|
|
281
|
-
pub fn type_json_to_polars_type(type_json: String) -> RbResult<Value> {
|
|
282
|
-
Ok(Wrap(parse_type_json_str(&type_json).map_err(to_rb_err)?).
|
|
292
|
+
pub fn type_json_to_polars_type(ruby: &Ruby, type_json: String) -> RbResult<Value> {
|
|
293
|
+
Ok(Wrap(parse_type_json_str(&type_json).map_err(to_rb_err)?).into_value_with(ruby))
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
|
|
@@ -290,6 +301,7 @@ impl RbCatalogClient {
|
|
|
290
301
|
}
|
|
291
302
|
|
|
292
303
|
fn catalog_info_to_rbobject(
|
|
304
|
+
ruby: &Ruby,
|
|
293
305
|
CatalogInfo {
|
|
294
306
|
name,
|
|
295
307
|
comment,
|
|
@@ -302,10 +314,10 @@ fn catalog_info_to_rbobject(
|
|
|
302
314
|
updated_by,
|
|
303
315
|
}: CatalogInfo,
|
|
304
316
|
) -> RbResult<Value> {
|
|
305
|
-
let dict =
|
|
317
|
+
let dict = ruby.hash_new();
|
|
306
318
|
|
|
307
|
-
let properties = properties_to_rbobject(properties);
|
|
308
|
-
let options = properties_to_rbobject(options);
|
|
319
|
+
let properties = properties_to_rbobject(ruby, properties);
|
|
320
|
+
let options = properties_to_rbobject(ruby, options);
|
|
309
321
|
|
|
310
322
|
rbdict_insert_keys!(dict, {
|
|
311
323
|
name,
|
|
@@ -319,13 +331,11 @@ fn catalog_info_to_rbobject(
|
|
|
319
331
|
updated_by
|
|
320
332
|
});
|
|
321
333
|
|
|
322
|
-
|
|
323
|
-
.unwrap()
|
|
324
|
-
.get_inner(&CATALOG_INFO_CLS)
|
|
325
|
-
.funcall("new", (dict,))
|
|
334
|
+
ruby.get_inner(&CATALOG_INFO_CLS).funcall("new", (dict,))
|
|
326
335
|
}
|
|
327
336
|
|
|
328
337
|
fn namespace_info_to_rbobject(
|
|
338
|
+
ruby: &Ruby,
|
|
329
339
|
NamespaceInfo {
|
|
330
340
|
name,
|
|
331
341
|
comment,
|
|
@@ -337,9 +347,9 @@ fn namespace_info_to_rbobject(
|
|
|
337
347
|
updated_by,
|
|
338
348
|
}: NamespaceInfo,
|
|
339
349
|
) -> RbResult<Value> {
|
|
340
|
-
let dict =
|
|
350
|
+
let dict = ruby.hash_new();
|
|
341
351
|
|
|
342
|
-
let properties = properties_to_rbobject(properties);
|
|
352
|
+
let properties = properties_to_rbobject(ruby, properties);
|
|
343
353
|
|
|
344
354
|
rbdict_insert_keys!(dict, {
|
|
345
355
|
name,
|
|
@@ -352,13 +362,10 @@ fn namespace_info_to_rbobject(
|
|
|
352
362
|
updated_by
|
|
353
363
|
});
|
|
354
364
|
|
|
355
|
-
|
|
356
|
-
.unwrap()
|
|
357
|
-
.get_inner(&NAMESPACE_INFO_CLS)
|
|
358
|
-
.funcall("new", (dict,))
|
|
365
|
+
ruby.get_inner(&NAMESPACE_INFO_CLS).funcall("new", (dict,))
|
|
359
366
|
}
|
|
360
367
|
|
|
361
|
-
fn table_info_to_rbobject(table_info: TableInfo) -> RbResult<Value> {
|
|
368
|
+
fn table_info_to_rbobject(ruby: &Ruby, table_info: TableInfo) -> RbResult<Value> {
|
|
362
369
|
let TableInfo {
|
|
363
370
|
name,
|
|
364
371
|
table_id,
|
|
@@ -374,49 +381,47 @@ fn table_info_to_rbobject(table_info: TableInfo) -> RbResult<Value> {
|
|
|
374
381
|
updated_by,
|
|
375
382
|
} = table_info;
|
|
376
383
|
|
|
377
|
-
let column_info_cls =
|
|
384
|
+
let column_info_cls = ruby.get_inner(&COLUMN_INFO_CLS);
|
|
378
385
|
|
|
379
386
|
let columns = columns
|
|
380
387
|
.map(|columns| {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
},
|
|
411
|
-
))
|
|
388
|
+
ruby.ary_try_from_iter(columns.into_iter().map(
|
|
389
|
+
|ColumnInfo {
|
|
390
|
+
name,
|
|
391
|
+
type_name,
|
|
392
|
+
type_text,
|
|
393
|
+
type_json,
|
|
394
|
+
position,
|
|
395
|
+
comment,
|
|
396
|
+
partition_index,
|
|
397
|
+
}| {
|
|
398
|
+
let dict = ruby.hash_new();
|
|
399
|
+
|
|
400
|
+
let name = name.as_str();
|
|
401
|
+
let type_name = type_name.as_str();
|
|
402
|
+
let type_text = type_text.as_str();
|
|
403
|
+
|
|
404
|
+
rbdict_insert_keys!(dict, {
|
|
405
|
+
name,
|
|
406
|
+
type_name,
|
|
407
|
+
type_text,
|
|
408
|
+
type_json,
|
|
409
|
+
position,
|
|
410
|
+
comment,
|
|
411
|
+
partition_index,
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
column_info_cls.funcall::<_, _, Value>("new", (dict,))
|
|
415
|
+
},
|
|
416
|
+
))
|
|
412
417
|
})
|
|
413
418
|
.transpose()?;
|
|
414
419
|
|
|
415
|
-
let dict =
|
|
420
|
+
let dict = ruby.hash_new();
|
|
416
421
|
|
|
417
422
|
let data_source_format = data_source_format.map(|x| x.to_string());
|
|
418
423
|
let table_type = table_type.to_string();
|
|
419
|
-
let properties = properties_to_rbobject(properties);
|
|
424
|
+
let properties = properties_to_rbobject(ruby, properties);
|
|
420
425
|
|
|
421
426
|
rbdict_insert_keys!(dict, {
|
|
422
427
|
name,
|
|
@@ -433,14 +438,11 @@ fn table_info_to_rbobject(table_info: TableInfo) -> RbResult<Value> {
|
|
|
433
438
|
updated_by,
|
|
434
439
|
});
|
|
435
440
|
|
|
436
|
-
|
|
437
|
-
.unwrap()
|
|
438
|
-
.get_inner(&TABLE_INFO_CLS)
|
|
439
|
-
.funcall("new", (dict,))
|
|
441
|
+
ruby.get_inner(&TABLE_INFO_CLS).funcall("new", (dict,))
|
|
440
442
|
}
|
|
441
443
|
|
|
442
|
-
fn properties_to_rbobject(properties: PlHashMap<PlSmallStr, String>) -> RHash {
|
|
443
|
-
let dict =
|
|
444
|
+
fn properties_to_rbobject(ruby: &Ruby, properties: PlHashMap<PlSmallStr, String>) -> RHash {
|
|
445
|
+
let dict = ruby.hash_new();
|
|
444
446
|
|
|
445
447
|
for (key, value) in properties.into_iter() {
|
|
446
448
|
dict.aset(key.as_str(), value).unwrap();
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
use magnus::encoding::
|
|
1
|
+
use magnus::encoding::EncodingCapable;
|
|
2
2
|
use magnus::{
|
|
3
|
-
IntoValue, RArray, RHash, RString, Ruby, TryConvert, Value,
|
|
3
|
+
IntoValue, RArray, RHash, RString, Ruby, TryConvert, Value, prelude::*, r_hash::ForEach,
|
|
4
4
|
};
|
|
5
5
|
use polars::prelude::*;
|
|
6
|
+
use polars_compute::decimal::{DEC128_MAX_PREC, DecimalFmtBuffer, dec128_fits};
|
|
6
7
|
use polars_core::utils::any_values_to_supertype_and_n_dtypes;
|
|
7
8
|
|
|
9
|
+
use super::datetime::datetime_to_rb_object;
|
|
8
10
|
use super::{ObjectValue, Wrap, struct_dict};
|
|
9
11
|
|
|
10
12
|
use crate::exceptions::RbOverflowError;
|
|
11
|
-
use crate::rb_modules::
|
|
13
|
+
use crate::rb_modules::pl_utils;
|
|
12
14
|
use crate::{RbErr, RbPolarsErr, RbResult, RbSeries};
|
|
13
15
|
|
|
14
16
|
impl IntoValue for Wrap<AnyValue<'_>> {
|
|
@@ -29,11 +31,12 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
|
|
|
29
31
|
AnyValue::UInt16(v) => ruby.into_value(v),
|
|
30
32
|
AnyValue::UInt32(v) => ruby.into_value(v),
|
|
31
33
|
AnyValue::UInt64(v) => ruby.into_value(v),
|
|
34
|
+
AnyValue::UInt128(v) => ruby.into_value(v),
|
|
32
35
|
AnyValue::Int8(v) => ruby.into_value(v),
|
|
33
36
|
AnyValue::Int16(v) => ruby.into_value(v),
|
|
34
37
|
AnyValue::Int32(v) => ruby.into_value(v),
|
|
35
38
|
AnyValue::Int64(v) => ruby.into_value(v),
|
|
36
|
-
AnyValue::Int128(
|
|
39
|
+
AnyValue::Int128(v) => ruby.into_value(v),
|
|
37
40
|
AnyValue::Float32(v) => ruby.into_value(v),
|
|
38
41
|
AnyValue::Float64(v) => ruby.into_value(v),
|
|
39
42
|
AnyValue::Null => ruby.qnil().as_value(),
|
|
@@ -41,12 +44,12 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
|
|
|
41
44
|
AnyValue::String(v) => ruby.into_value(v),
|
|
42
45
|
AnyValue::StringOwned(v) => ruby.into_value(v.as_str()),
|
|
43
46
|
AnyValue::Categorical(cat, map) | AnyValue::Enum(cat, map) => unsafe {
|
|
44
|
-
map.cat_to_str_unchecked(cat).
|
|
47
|
+
map.cat_to_str_unchecked(cat).into_value_with(ruby)
|
|
45
48
|
},
|
|
46
49
|
AnyValue::CategoricalOwned(cat, map) | AnyValue::EnumOwned(cat, map) => unsafe {
|
|
47
|
-
map.cat_to_str_unchecked(cat).
|
|
50
|
+
map.cat_to_str_unchecked(cat).into_value_with(ruby)
|
|
48
51
|
},
|
|
49
|
-
AnyValue::Date(v) =>
|
|
52
|
+
AnyValue::Date(v) => pl_utils().funcall("_to_ruby_date", (v,)).unwrap(),
|
|
50
53
|
AnyValue::Datetime(v, time_unit, time_zone) => {
|
|
51
54
|
datetime_to_rb_object(v, time_unit, time_zone)
|
|
52
55
|
}
|
|
@@ -55,14 +58,14 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
|
|
|
55
58
|
}
|
|
56
59
|
AnyValue::Duration(v, time_unit) => {
|
|
57
60
|
let time_unit = time_unit.to_ascii();
|
|
58
|
-
|
|
61
|
+
pl_utils()
|
|
59
62
|
.funcall("_to_ruby_duration", (v, time_unit))
|
|
60
63
|
.unwrap()
|
|
61
64
|
}
|
|
62
|
-
AnyValue::Time(v) =>
|
|
63
|
-
AnyValue::Array(v, _) | AnyValue::List(v) => RbSeries::new(v).to_a().
|
|
64
|
-
ref av @ AnyValue::Struct(_, _, flds) => struct_dict(av._iter_struct_av(), flds),
|
|
65
|
-
AnyValue::StructOwned(payload) => struct_dict(payload.0.into_iter(), &payload.1),
|
|
65
|
+
AnyValue::Time(v) => pl_utils().funcall("_to_ruby_time", (v,)).unwrap(),
|
|
66
|
+
AnyValue::Array(v, _) | AnyValue::List(v) => RbSeries::new(v).to_a().as_value(),
|
|
67
|
+
ref av @ AnyValue::Struct(_, _, flds) => struct_dict(ruby, av._iter_struct_av(), flds),
|
|
68
|
+
AnyValue::StructOwned(payload) => struct_dict(ruby, payload.0.into_iter(), &payload.1),
|
|
66
69
|
AnyValue::Object(v) => {
|
|
67
70
|
let object = v.as_any().downcast_ref::<ObjectValue>().unwrap();
|
|
68
71
|
object.to_value()
|
|
@@ -71,21 +74,16 @@ pub(crate) fn any_value_into_rb_object(av: AnyValue, ruby: &Ruby) -> Value {
|
|
|
71
74
|
let object = v.0.as_any().downcast_ref::<ObjectValue>().unwrap();
|
|
72
75
|
object.to_value()
|
|
73
76
|
}
|
|
74
|
-
AnyValue::Binary(v) =>
|
|
75
|
-
AnyValue::BinaryOwned(v) =>
|
|
76
|
-
AnyValue::Decimal(v, scale) =>
|
|
77
|
-
|
|
78
|
-
.
|
|
77
|
+
AnyValue::Binary(v) => ruby.str_from_slice(v).as_value(),
|
|
78
|
+
AnyValue::BinaryOwned(v) => ruby.str_from_slice(&v).as_value(),
|
|
79
|
+
AnyValue::Decimal(v, prec, scale) => {
|
|
80
|
+
let mut buf = DecimalFmtBuffer::new();
|
|
81
|
+
let s = buf.format_dec128(v, scale, false, false);
|
|
82
|
+
pl_utils().funcall("_to_ruby_decimal", (prec, s)).unwrap()
|
|
83
|
+
}
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
fn datetime_to_rb_object(v: i64, tu: TimeUnit, tz: Option<&TimeZone>) -> Value {
|
|
83
|
-
let tu = tu.to_ascii();
|
|
84
|
-
utils()
|
|
85
|
-
.funcall("_to_ruby_datetime", (v, tu, tz.map(|v| v.to_string())))
|
|
86
|
-
.unwrap()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
87
|
pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<AnyValue<'s>> {
|
|
90
88
|
// Conversion functions.
|
|
91
89
|
fn get_null(_ob: Value, _strict: bool) -> RbResult<AnyValue<'static>> {
|
|
@@ -100,8 +98,12 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
|
|
|
100
98
|
fn get_int(ob: Value, strict: bool) -> RbResult<AnyValue<'static>> {
|
|
101
99
|
if let Ok(v) = i64::try_convert(ob) {
|
|
102
100
|
Ok(AnyValue::Int64(v))
|
|
101
|
+
} else if let Ok(v) = i128::try_convert(ob) {
|
|
102
|
+
Ok(AnyValue::Int128(v))
|
|
103
103
|
} else if let Ok(v) = u64::try_convert(ob) {
|
|
104
104
|
Ok(AnyValue::UInt64(v))
|
|
105
|
+
} else if let Ok(v) = u128::try_convert(ob) {
|
|
106
|
+
Ok(AnyValue::UInt128(v))
|
|
105
107
|
} else if !strict {
|
|
106
108
|
let f = f64::try_convert(ob)?;
|
|
107
109
|
Ok(AnyValue::Float64(f))
|
|
@@ -117,8 +119,9 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
|
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
fn get_str(ob: Value, _strict: bool) -> RbResult<AnyValue<'static>> {
|
|
122
|
+
let ruby = Ruby::get_with(ob);
|
|
120
123
|
let v = RString::from_value(ob).unwrap();
|
|
121
|
-
if v.enc_get() ==
|
|
124
|
+
if v.enc_get() == ruby.utf8_encindex() {
|
|
122
125
|
Ok(AnyValue::StringOwned(v.to_string()?.into()))
|
|
123
126
|
} else {
|
|
124
127
|
Ok(AnyValue::BinaryOwned(unsafe { v.as_slice() }.to_vec()))
|
|
@@ -211,14 +214,12 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
|
|
|
211
214
|
match digits.parse::<i128>() {
|
|
212
215
|
Ok(mut v) => {
|
|
213
216
|
let scale = if exp > 0 {
|
|
214
|
-
v = 10_i128
|
|
215
|
-
.checked_pow(exp as u32)
|
|
216
|
-
.and_then(|factor| v.checked_mul(factor))?;
|
|
217
|
+
v = 10_i128.checked_pow(exp as u32)?.checked_mul(v)?;
|
|
217
218
|
0
|
|
218
219
|
} else {
|
|
219
220
|
(-exp) as usize
|
|
220
221
|
};
|
|
221
|
-
|
|
222
|
+
dec128_fits(v, DEC128_MAX_PREC).then_some((v, scale))
|
|
222
223
|
}
|
|
223
224
|
Err(_) => None,
|
|
224
225
|
}
|
|
@@ -234,27 +235,28 @@ pub(crate) fn rb_object_to_any_value<'s>(ob: Value, strict: bool) -> RbResult<An
|
|
|
234
235
|
// TODO better error
|
|
235
236
|
v = v.checked_neg().unwrap();
|
|
236
237
|
}
|
|
237
|
-
Ok(AnyValue::Decimal(v, scale))
|
|
238
|
+
Ok(AnyValue::Decimal(v, DEC128_MAX_PREC, scale))
|
|
238
239
|
}
|
|
239
240
|
|
|
241
|
+
let ruby = Ruby::get_with(ob);
|
|
240
242
|
if ob.is_nil() {
|
|
241
243
|
get_null(ob, strict)
|
|
242
|
-
} else if ob.is_kind_of(
|
|
244
|
+
} else if ob.is_kind_of(ruby.class_true_class()) || ob.is_kind_of(ruby.class_false_class()) {
|
|
243
245
|
get_bool(ob, strict)
|
|
244
|
-
} else if ob.is_kind_of(
|
|
246
|
+
} else if ob.is_kind_of(ruby.class_integer()) {
|
|
245
247
|
get_int(ob, strict)
|
|
246
|
-
} else if ob.is_kind_of(
|
|
248
|
+
} else if ob.is_kind_of(ruby.class_float()) {
|
|
247
249
|
get_float(ob, strict)
|
|
248
|
-
} else if ob.is_kind_of(
|
|
250
|
+
} else if ob.is_kind_of(ruby.class_string()) {
|
|
249
251
|
get_str(ob, strict)
|
|
250
|
-
} else if ob.is_kind_of(
|
|
252
|
+
} else if ob.is_kind_of(ruby.class_array()) {
|
|
251
253
|
get_list(ob, strict)
|
|
252
|
-
} else if ob.is_kind_of(
|
|
254
|
+
} else if ob.is_kind_of(ruby.class_hash()) {
|
|
253
255
|
get_struct(ob, strict)
|
|
254
256
|
} else if ob.respond_to("_s", true)? {
|
|
255
257
|
get_list_from_series(ob, strict)
|
|
256
258
|
// call is_a? for ActiveSupport::TimeWithZone
|
|
257
|
-
} else if ob.funcall::<_, _, bool>("is_a?", (
|
|
259
|
+
} else if ob.funcall::<_, _, bool>("is_a?", (ruby.class_time(),))? {
|
|
258
260
|
get_time(ob, strict)
|
|
259
261
|
} else if ob.is_kind_of(crate::rb_modules::datetime()) {
|
|
260
262
|
get_datetime(ob, strict)
|