Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-sql/tests/statements.rs
6939 views
1
use polars_core::prelude::*;
2
use polars_lazy::prelude::*;
3
use polars_sql::*;
4
5
fn create_ctx() -> SQLContext {
6
let a = Column::new("a".into(), (1..10i64).map(|i| i / 100).collect::<Vec<_>>());
7
let b = Column::new("b".into(), 1..10i64);
8
let df = DataFrame::new(vec![a, b]).unwrap().lazy();
9
let mut ctx = SQLContext::new();
10
ctx.register("df", df);
11
ctx
12
}
13
14
#[test]
15
fn tbl_alias() {
16
let mut ctx = create_ctx();
17
let sql = r#"
18
SELECT
19
tbl.a,
20
tbl.b,
21
FROM df as tbl
22
"#;
23
let actual = ctx.execute(sql);
24
assert!(actual.is_ok());
25
}
26
27
#[test]
28
fn trailing_commas_allowed() {
29
let mut ctx = create_ctx();
30
let sql = r#"
31
SELECT
32
a,
33
b,
34
FROM df
35
"#;
36
let actual = ctx.execute(sql);
37
assert!(actual.is_ok());
38
}
39
40
#[test]
41
fn select_exclude_single() {
42
let mut ctx = create_ctx();
43
let sql = r#"
44
SELECT * EXCLUDE a FROM df
45
"#;
46
let actual = ctx.execute(sql);
47
assert!(actual.is_ok());
48
}
49
50
#[test]
51
fn select_exclude_multi() {
52
let mut ctx = create_ctx();
53
let sql = r#"
54
SELECT * EXCLUDE (a) FROM df
55
"#;
56
let actual = ctx.execute(sql);
57
assert!(actual.is_ok());
58
}
59
60
#[test]
61
fn select_qualified_wildcard() {
62
let df1 = df![
63
"a" => [1,2,3],
64
"b" => ["l", "m", "n"]
65
]
66
.unwrap();
67
let df2 = df![
68
"a" => [4,2,3],
69
"c" => ["x", "y", "z"]
70
]
71
.unwrap();
72
73
let expected = df![
74
"a" => [2,3],
75
"b" => ["m", "n"]
76
]
77
.unwrap();
78
let mut ctx = SQLContext::new();
79
ctx.register("test", df1.lazy());
80
ctx.register("test2", df2.lazy());
81
82
let sql = r#"
83
SELECT test.*
84
FROM test
85
INNER JOIN test2
86
USING(a)
87
"#;
88
let actual = ctx.execute(sql).unwrap().collect().unwrap();
89
assert!(actual.equals(&expected));
90
}
91
92
#[test]
93
fn select_qualified_column() {
94
let df1 = df![
95
"a" => [1,2,3],
96
"b" => ["l", "m", "n"]
97
]
98
.unwrap();
99
let df2 = df![
100
"a" => [4,2,3],
101
"c" => ["x", "y", "z"]
102
]
103
.unwrap();
104
105
let expected = df![
106
"b" => ["m", "n"],
107
"a" => [2,3],
108
"c" => ["y", "z"]
109
]
110
.unwrap();
111
let mut ctx = SQLContext::new();
112
ctx.register("test", df1.lazy());
113
ctx.register("test2", df2.lazy());
114
115
let sql = r#"
116
SELECT test.b, test2.*
117
FROM test
118
INNER JOIN test2
119
USING(a)
120
"#;
121
let actual = ctx.execute(sql).unwrap().collect().unwrap();
122
assert!(actual.equals(&expected));
123
}
124
125
#[test]
126
fn test_union_all() {
127
let df1 = df![
128
"a" => [1,2,3],
129
"b" => ["l", "m", "n"]
130
]
131
.unwrap();
132
let df2 = df![
133
"a" => [4,2,3],
134
"b" => ["x", "y", "z"]
135
]
136
.unwrap();
137
138
let mut ctx = SQLContext::new();
139
ctx.register("test", df1.clone().lazy());
140
ctx.register("test2", df2.clone().lazy());
141
142
let sql = r#"
143
SELECT * FROM test
144
UNION ALL (
145
SELECT * FROM test2
146
)
147
"#;
148
let expected = polars_lazy::dsl::concat(
149
vec![df1.lazy(), df2.lazy()],
150
UnionArgs {
151
rechunk: false,
152
parallel: true,
153
..Default::default()
154
},
155
)
156
.unwrap()
157
.collect()
158
.unwrap();
159
160
let actual = ctx.execute(sql).unwrap().collect().unwrap();
161
assert!(actual.equals(&expected));
162
}
163
164
#[test]
165
fn test_drop_table() {
166
let mut ctx = create_ctx();
167
let sql = r#"
168
DROP TABLE df
169
"#;
170
let actual = ctx.execute(sql);
171
assert!(actual.is_ok());
172
let res = ctx.execute("SELECT * FROM df");
173
assert!(res.is_err());
174
}
175
176
#[test]
177
fn iss_9560_join_as() {
178
let df1 = df! {"id"=> [1, 2, 3, 4], "ano"=> [2, 3, 4, 5]}.unwrap();
179
let df2 = df! {"id"=> [1, 2, 3, 4], "ano"=> [2, 3, 4, 5]}.unwrap();
180
let mut ctx = SQLContext::new();
181
ctx.register("df1", df1.lazy());
182
ctx.register("df2", df2.lazy());
183
let sql = r#"
184
SELECT * FROM df1 AS t1 JOIN df2 AS t2 ON t1.id = t2.id
185
"#;
186
let actual = ctx.execute(sql).unwrap().collect().unwrap();
187
188
let expected = df! {
189
"id" => [1, 2, 3, 4],
190
"ano" => [2, 3, 4, 5],
191
"id:t2" => [1, 2, 3, 4],
192
"ano:t2" => [2, 3, 4, 5],
193
}
194
.unwrap();
195
196
assert!(
197
actual.equals(&expected),
198
"expected = {expected:?}\nactual={actual:?}"
199
);
200
}
201
202
fn prepare_compound_join_context() -> SQLContext {
203
let df1 = df! {
204
"a" => [1, 2, 3, 4, 5],
205
"b" => [1, 3, 4, 4, 5],
206
}
207
.unwrap();
208
let df2 = df! {
209
"a" => [1, 2, 3, 4, 5],
210
"b" => [0, 3, 4, 5, 6]
211
}
212
.unwrap();
213
let df3 = df! {
214
"a" => [1, 2, 3, 4, 5],
215
"b" => [0, 3, 4, 5, 7],
216
"c" => [1, 3, 4, 5, 7]
217
}
218
.unwrap();
219
let mut ctx = SQLContext::new();
220
ctx.register("df1", df1.lazy());
221
ctx.register("df2", df2.lazy());
222
ctx.register("df3", df3.lazy());
223
ctx
224
}
225
226
#[test]
227
fn test_compound_join_basic() {
228
let mut ctx = prepare_compound_join_context();
229
let sql = r#"
230
SELECT * FROM df1
231
INNER JOIN df2 ON df1.a = df2.a AND df1.b = df2.b
232
"#;
233
let actual = ctx.execute(sql).unwrap().collect().unwrap();
234
235
let expected = df! {
236
"a" => [2, 3],
237
"b" => [3, 4],
238
"a:df2" => [2, 3],
239
"b:df2" => [3, 4],
240
}
241
.unwrap();
242
243
assert!(
244
actual.equals(&expected),
245
"expected = {expected:?}\nactual={actual:?}"
246
);
247
}
248
249
#[test]
250
fn test_compound_join_different_column_names() {
251
let df1 = df! {
252
"a" => [1, 2, 3, 4, 5],
253
"b" => [1, 2, 3, 4, 5],
254
}
255
.unwrap();
256
let df2 = df! {
257
"a" => [0, 2, 3, 4, 5],
258
"b" => [1, 2, 3, 5, 6],
259
"c" => [7, 5, 3, 5, 7],
260
}
261
.unwrap();
262
263
let mut ctx = SQLContext::new();
264
ctx.register("lf1", df1.lazy());
265
ctx.register("lf2", df2.lazy());
266
267
let sql = r#"
268
SELECT lf1.a, lf2.b, lf2.c
269
FROM lf1 INNER JOIN lf2
270
-- note: uses "lf1.a" for *both* constraint arms
271
ON lf1.a = lf2.b AND lf1.a = lf2.c
272
ORDER BY a
273
"#;
274
let actual = ctx.execute(sql).unwrap().collect().unwrap();
275
let expected = df! {
276
"a" => [3, 5],
277
"b" => [3, 5],
278
"c" => [3, 5],
279
}
280
.unwrap();
281
282
assert!(
283
actual.equals(&expected),
284
"expected = {expected:?}\nactual={actual:?}"
285
);
286
}
287
288
#[test]
289
fn test_compound_join_three_tables() {
290
let mut ctx = prepare_compound_join_context();
291
let sql = r#"
292
SELECT df3.* FROM df1
293
INNER JOIN df2
294
ON df1.a = df2.a AND df1.b = df2.b
295
INNER JOIN df3
296
ON df3.a = df1.a AND df3.b = df1.b
297
"#;
298
let actual = ctx.execute(sql).unwrap().collect().unwrap();
299
let expected = df! {
300
"a" => [2, 3],
301
"b" => [3, 4],
302
"c" => [3, 4],
303
}
304
.unwrap();
305
306
assert!(
307
actual.equals(&expected),
308
"expected = {expected:?}\nactual={actual:?}"
309
);
310
}
311
312
#[test]
313
fn test_compound_join_nested_and() {
314
let df1 = df! {
315
"a" => [1, 2, 3, 4, 5],
316
"b" => [1, 2, 3, 4, 5],
317
"c" => [0, 3, 4, 5, 6],
318
"d" => [0, 3, 4, 5, 6],
319
}
320
.unwrap();
321
let df2 = df! {
322
"a" => [1, 2, 3, 4, 5],
323
"b" => [1, 3, 3, 5, 6],
324
"c" => [0, 3, 4, 5, 6],
325
"d" => [0, 3, 4, 5, 6]
326
}
327
.unwrap();
328
329
let mut ctx = SQLContext::new();
330
ctx.register("df1", df1.lazy());
331
ctx.register("df2", df2.lazy());
332
333
for cols in [
334
"df1.*",
335
"df2.*",
336
"df1.a, df1.b, df2.c, df2.d",
337
"df2.a, df2.b, df1.c, df1.d",
338
] {
339
let sql = format!(
340
r#"
341
SELECT {cols} FROM df1
342
INNER JOIN df2 ON
343
df1.a = df2.a AND
344
df1.b = df2.b AND
345
df1.c = df2.c AND
346
df1.d = df2.d
347
"#
348
);
349
let actual = ctx.execute(sql.as_str()).unwrap().collect().unwrap();
350
let expected = df! {
351
"a" => [1, 3],
352
"b" => [1, 3],
353
"c" => [0, 4],
354
"d" => [0, 4],
355
}
356
.unwrap();
357
358
assert!(
359
actual.equals(&expected),
360
"expected = {expected:?}\nactual={actual:?}"
361
);
362
}
363
}
364
365
#[test]
366
fn test_resolve_join_column_select_13618() {
367
let df1 = df! {
368
"A" => [1, 2, 3, 4, 5],
369
"B" => [5, 4, 3, 2, 1],
370
"fruits" => ["banana", "banana", "apple", "apple", "banana"],
371
"cars" => ["beetle", "audi", "beetle", "beetle", "beetle"],
372
}
373
.unwrap();
374
let df2 = df1.clone();
375
376
let mut ctx = SQLContext::new();
377
ctx.register("tbl", df1.lazy());
378
ctx.register("other", df2.lazy());
379
380
let join_types = vec!["LEFT", "INNER", "FULL OUTER", ""];
381
for join_type in join_types {
382
let sql = format!(
383
r#"
384
SELECT tbl.A, other.B, tbl.fruits, other.cars
385
FROM tbl
386
{join_type} JOIN other ON tbl.A = other.B
387
ORDER BY tbl.A ASC
388
"#
389
);
390
let actual = ctx.execute(sql.as_str()).unwrap().collect().unwrap();
391
let expected = df! {
392
"A" => [1, 2, 3, 4, 5],
393
"B" => [1, 2, 3, 4, 5],
394
"fruits" => ["banana", "banana", "apple", "apple", "banana"],
395
"cars" => ["beetle", "beetle", "beetle", "audi", "beetle"],
396
}
397
.unwrap();
398
399
assert!(
400
actual.equals(&expected),
401
"({join_type} JOIN) expected = {expected:?}\nactual={actual:?}"
402
);
403
}
404
}
405
406
#[test]
407
fn test_compound_join_and_select_exclude_rename_replace() {
408
let df1 = df! {
409
"a" => [1, 2, 3, 4, 5],
410
"b" => [1, 2, 3, 4, 5],
411
"c" => [0, 3, 4, 5, 6],
412
"d" => [0, 3, 4, 5, 6],
413
"e" => ["a", "b", "c", "d", "?"],
414
}
415
.unwrap();
416
let df2 = df! {
417
"a" => [1, 2, 3, 4, 5],
418
"b" => [1, 3, 3, 5, 6],
419
"c" => [0, 3, 4, 5, 6],
420
"d" => [0, 3, 4, 5, 6],
421
"e" => ["w", "x", "y", "z", "!"],
422
}
423
.unwrap();
424
425
let mut ctx = SQLContext::new();
426
ctx.register("df1", df1.lazy());
427
ctx.register("df2", df2.lazy());
428
429
let sql = r#"
430
SELECT * RENAME ("ee" AS "e")
431
FROM (
432
SELECT df1.* EXCLUDE "e", df2.e AS "ee"
433
FROM df1
434
INNER JOIN df2 ON df1.a = df2.a AND
435
((df1.b = df2.b AND df1.c = df2.c) AND df1.d = df2.d)
436
) tbl
437
"#;
438
let actual = ctx.execute(sql).unwrap().collect().unwrap();
439
let expected = df! {
440
"a" => [1, 3],
441
"b" => [1, 3],
442
"c" => [0, 4],
443
"d" => [0, 4],
444
"e" => ["w", "y"],
445
}
446
.unwrap();
447
448
assert!(
449
actual.equals(&expected),
450
"expected = {expected:?}\nactual={actual:?}"
451
);
452
453
let sql = r#"
454
SELECT * REPLACE ("ee" || "ee" AS "ee")
455
FROM (
456
SELECT * EXCLUDE ("e", "e:df2"), df1.e AS "ee"
457
FROM df1
458
INNER JOIN df2 ON df1.a = df2.a AND
459
((df1.b = df2.b AND df1.c = df2.c) AND df1.d = df2.d)
460
) tbl
461
"#;
462
let actual = ctx.execute(sql).unwrap().collect().unwrap();
463
464
let expected = df! {
465
"a" => [1, 3],
466
"b" => [1, 3],
467
"c" => [0, 4],
468
"d" => [0, 4],
469
"a:df2" => [1, 3],
470
"b:df2" => [1, 3],
471
"c:df2" => [0, 4],
472
"d:df2" => [0, 4],
473
"ee" => ["aa", "cc"],
474
}
475
.unwrap();
476
477
assert!(
478
actual.equals(&expected),
479
"expected = {expected:?}\nactual={actual:?}"
480
);
481
}
482
483
#[test]
484
fn test_join_on_different_keys() {
485
let df1 = df! {"x" => [-1, 0, 1, 2, 3, 4]}.unwrap();
486
let df2 = df! {"y" => [0, 1, -2, 3, 5, 6]}.unwrap();
487
488
let mut ctx = SQLContext::new();
489
ctx.register("df1", df1.lazy());
490
ctx.register("df2", df2.lazy());
491
492
// join on x = y
493
let sql = r#"
494
SELECT df2.*
495
FROM df1
496
INNER JOIN df2 ON df1.x = df2.y
497
ORDER BY y
498
"#;
499
let actual = ctx.execute(sql).unwrap().collect().unwrap();
500
let expected = df! {"y" => [0, 1, 3]}.unwrap();
501
assert!(
502
actual.equals(&expected),
503
"expected = {expected:?}\nactual={actual:?}"
504
);
505
}
506
507
#[test]
508
fn test_join_multi_consecutive() {
509
let df1 = df! { "a" => [1, 2, 3], "b" => [4, 8, 6] }.unwrap();
510
let df2 = df! { "a" => [3, 2, 1], "b" => [6, 5, 4], "c" => ["x", "y", "z"] }.unwrap();
511
let df3 = df! { "c" => ["w", "y", "z"], "d" => [10.5, -50.0, 25.5] }.unwrap();
512
513
let mut ctx = SQLContext::new();
514
ctx.register("tbl_a", df1.lazy());
515
ctx.register("tbl_b", df2.lazy());
516
ctx.register("tbl_c", df3.lazy());
517
518
let sql = r#"
519
SELECT tbl_a.a, tbl_a.b, tbl_b.c, tbl_c.d FROM tbl_a
520
INNER JOIN tbl_b ON tbl_a.a = tbl_b.a AND tbl_a.b = tbl_b.b
521
INNER JOIN tbl_c ON tbl_a.c = tbl_c.c
522
ORDER BY a DESC
523
"#;
524
let actual = ctx.execute(sql).unwrap().collect().unwrap();
525
526
let expected = df! {
527
"a" => [1],
528
"b" => [4],
529
"c" => ["z"],
530
"d" => [25.5],
531
}
532
.unwrap();
533
534
assert!(
535
actual.equals(&expected),
536
"expected = {expected:?}\nactual={actual:?}"
537
);
538
}
539
540
#[test]
541
fn test_join_utf8() {
542
// (色) color and (野菜) vegetable
543
let df1 = df! {
544
"" => ["", "", "黄色"],
545
"野菜" => ["トマト", "ケール", "コーン"],
546
}
547
.unwrap();
548
549
// (色) color and (動物) animal
550
let df2 = df! {
551
"" => ["黄色", "", ""],
552
"動物" => ["ゴシキヒワ", "", "レッサーパンダ"],
553
}
554
.unwrap();
555
556
let mut ctx = SQLContext::new();
557
ctx.register("df1", df1.lazy());
558
ctx.register("df2", df2.lazy());
559
560
let expected = df! {
561
"" => ["", "", "黄色"], // green, red, yellow
562
"野菜" => ["ケール", "トマト", "コーン"], // kale, tomato, corn
563
"動物" => ["", "レッサーパンダ", "ゴシキヒワ"], // frog, red panda, goldfinch
564
}
565
.unwrap();
566
567
let sql = r#"
568
SELECT df1.*, df2.動物
569
FROM df1
570
INNER JOIN df2 ON df1.色 = df2.色
571
ORDER BY 色
572
"#;
573
let actual = ctx.execute(sql).unwrap().collect().unwrap();
574
575
assert!(
576
actual.equals(&expected),
577
"expected = {expected:?}\nactual={actual:?}"
578
);
579
}
580
581
#[test]
582
#[should_panic]
583
fn test_compound_invalid_1() {
584
let mut ctx = prepare_compound_join_context();
585
let sql = "SELECT * FROM df1 OUTER JOIN df2 ON a AND b";
586
let _ = ctx.execute(sql).unwrap();
587
}
588
589
#[test]
590
#[should_panic]
591
fn test_compound_invalid_2() {
592
let mut ctx = prepare_compound_join_context();
593
let sql = "SELECT * FROM df1 LEFT JOIN df2 ON df1.a = df2.a AND b = b";
594
let _ = ctx.execute(sql).unwrap();
595
}
596
597
#[test]
598
#[should_panic]
599
fn test_compound_invalid_3() {
600
let mut ctx = prepare_compound_join_context();
601
let sql = "SELECT * FROM df1 INNER JOIN df2 ON df1.a = df2.a AND b";
602
let _ = ctx.execute(sql).unwrap();
603
}
604
605