1
+ import contextlib
2
+
1
3
import numpy as np
2
4
import pytest
5
+ from pytest import param
3
6
4
7
import ibis
5
8
import ibis .expr .datatypes as dt
9
+ from ibis .util import guid
6
10
7
11
pytestmark = [
8
12
pytest .mark .never (
9
- ["sqlite" , "mysql" , "mssql" , "postgres" ], reason = "No map support"
13
+ ["sqlite" , "mysql" , "mssql" ], reason = "Unlikely to ever add map support"
10
14
),
11
15
pytest .mark .notyet (
12
- ["bigquery" , "impala" ], reason = "backend doesn't implement map types"
16
+ ["bigquery" , "impala" ], reason = "Backend doesn't yet implement map types"
13
17
),
14
18
pytest .mark .notimpl (
15
- ["duckdb" , "datafusion" , "pyspark" , "polars" ], reason = "Not implemented yet"
19
+ ["duckdb" , "datafusion" , "pyspark" , "polars" ],
20
+ reason = "Not yet implemented in ibis" ,
16
21
),
17
22
]
18
23
19
24
20
25
@pytest .mark .notimpl (["pandas" , "dask" ])
21
26
def test_map_table (con ):
22
27
table = con .table ("map" )
23
- assert not table .execute ().empty
28
+ assert table .kv .type ().is_map ()
29
+ assert not table .limit (1 ).execute ().empty
24
30
25
31
26
32
def test_literal_map_keys (con ):
@@ -42,7 +48,7 @@ def test_literal_map_values(con):
42
48
assert np .array_equal (result , ['a' , 'b' ])
43
49
44
50
45
- @pytest .mark .notimpl (["trino" ])
51
+ @pytest .mark .notimpl (["trino" , "postgres" ])
46
52
@pytest .mark .notyet (["snowflake" ])
47
53
def test_scalar_isin_literal_map_keys (con ):
48
54
mapping = ibis .literal ({'a' : 1 , 'b' : 2 })
@@ -54,6 +60,7 @@ def test_scalar_isin_literal_map_keys(con):
54
60
assert con .execute (false ) == False # noqa: E712
55
61
56
62
63
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
57
64
def test_map_scalar_contains_key_scalar (con ):
58
65
mapping = ibis .literal ({'a' : 1 , 'b' : 2 })
59
66
a = ibis .literal ('a' )
@@ -74,6 +81,7 @@ def test_map_scalar_contains_key_column(backend, alltypes, df):
74
81
75
82
76
83
@pytest .mark .notyet (["snowflake" ])
84
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
77
85
def test_map_column_contains_key_scalar (backend , alltypes , df ):
78
86
expr = ibis .map (ibis .array ([alltypes .string_col ]), ibis .array ([alltypes .int_col ]))
79
87
series = df .apply (lambda row : {row ['string_col' ]: row ['int_col' ]}, axis = 1 )
@@ -85,13 +93,15 @@ def test_map_column_contains_key_scalar(backend, alltypes, df):
85
93
86
94
87
95
@pytest .mark .notyet (["snowflake" ])
88
- def test_map_column_contains_key_column (backend , alltypes , df ):
96
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
97
+ def test_map_column_contains_key_column (alltypes ):
89
98
expr = ibis .map (ibis .array ([alltypes .string_col ]), ibis .array ([alltypes .int_col ]))
90
99
result = expr .contains (alltypes .string_col ).name ('tmp' ).execute ()
91
100
assert result .all ()
92
101
93
102
94
103
@pytest .mark .notyet (["snowflake" ])
104
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
95
105
def test_literal_map_merge (con ):
96
106
a = ibis .literal ({'a' : 0 , 'b' : 2 })
97
107
b = ibis .literal ({'a' : 1 , 'c' : 3 })
@@ -124,15 +134,30 @@ def test_literal_map_get_broadcast(backend, alltypes, df):
124
134
backend .assert_series_equal (result , expected )
125
135
126
136
127
- def test_map_construct_dict (con ):
128
- expr = ibis .map (['a' , 'b' ], [1 , 2 ])
137
+ @pytest .mark .parametrize (
138
+ ("keys" , "values" ),
139
+ [
140
+ param (
141
+ ["a" , "b" ],
142
+ [1 , 2 ],
143
+ id = "string" ,
144
+ marks = pytest .mark .notyet (
145
+ ["postgres" ], reason = "only support maps of string -> string"
146
+ ),
147
+ ),
148
+ param (["a" , "b" ], ["1" , "2" ], id = "int" ),
149
+ ],
150
+ )
151
+ def test_map_construct_dict (con , keys , values ):
152
+ expr = ibis .map (keys , values )
129
153
result = con .execute (expr .name ('tmp' ))
130
- assert result == { 'a' : 1 , 'b' : 2 }
154
+ assert result == dict ( zip ( keys , values ))
131
155
132
156
133
157
@pytest .mark .notimpl (
134
158
["snowflake" ], reason = "unclear how to implement two arrays -> object construction"
135
159
)
160
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
136
161
def test_map_construct_array_column (con , alltypes , df ):
137
162
expr = ibis .map (ibis .array ([alltypes .string_col ]), ibis .array ([alltypes .int_col ]))
138
163
result = con .execute (expr )
@@ -141,25 +166,29 @@ def test_map_construct_array_column(con, alltypes, df):
141
166
assert result .to_list () == expected .to_list ()
142
167
143
168
169
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
144
170
def test_map_get_with_compatible_value_smaller (con ):
145
171
value = ibis .literal ({'A' : 1000 , 'B' : 2000 })
146
172
expr = value .get ('C' , 3 )
147
173
assert con .execute (expr ) == 3
148
174
149
175
176
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
150
177
def test_map_get_with_compatible_value_bigger (con ):
151
178
value = ibis .literal ({'A' : 1 , 'B' : 2 })
152
179
expr = value .get ('C' , 3000 )
153
180
assert con .execute (expr ) == 3000
154
181
155
182
183
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
156
184
def test_map_get_with_incompatible_value_different_kind (con ):
157
185
value = ibis .literal ({'A' : 1000 , 'B' : 2000 })
158
186
expr = value .get ('C' , 3.0 )
159
187
assert con .execute (expr ) == 3.0
160
188
161
189
162
190
@pytest .mark .parametrize ('null_value' , [None , ibis .NA ])
191
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
163
192
def test_map_get_with_null_on_not_nullable (con , null_value ):
164
193
map_type = dt .Map (dt .string , dt .Int16 (nullable = False ))
165
194
value = ibis .literal ({'A' : 1000 , 'B' : 2000 }).cast (map_type )
@@ -174,7 +203,25 @@ def test_map_get_with_null_on_null_type_with_null(con, null_value):
174
203
assert con .execute (expr ) is None
175
204
176
205
206
+ @pytest .mark .notyet (["postgres" ], reason = "only support maps of string -> string" )
177
207
def test_map_get_with_null_on_null_type_with_non_null (con ):
178
208
value = ibis .literal ({'A' : None , 'B' : None })
179
209
expr = value .get ('C' , 1 )
180
210
assert con .execute (expr ) == 1
211
+
212
+
213
+ @pytest .fixture
214
+ def tmptable (con ):
215
+ name = guid ()
216
+ yield name
217
+
218
+ # some backends don't implement drop
219
+ with contextlib .suppress (NotImplementedError ):
220
+ con .drop_table (name )
221
+
222
+
223
+ @pytest .mark .notimpl (["clickhouse" ], reason = ".create_table not yet implemented in ibis" )
224
+ def test_map_create_table (con , tmptable ):
225
+ con .create_table (tmptable , schema = ibis .schema (dict (xyz = "map<string, string>" )))
226
+ t = con .table (tmptable )
227
+ assert t .schema ()["xyz" ].is_map ()
0 commit comments