|
26 | 26 | import org.apache.iceberg.transforms.Transform;
|
27 | 27 | import org.apache.iceberg.transforms.Transforms;
|
28 | 28 | import org.apache.iceberg.types.Types;
|
| 29 | +import org.apache.iceberg.util.NaNUtil; |
29 | 30 |
|
30 | 31 | /**
|
31 | 32 | * Factory methods for creating {@link Expression expressions}.
|
@@ -123,51 +124,79 @@ public static <T> UnboundPredicate<T> notNull(UnboundTerm<T> expr) {
|
123 | 124 | return new UnboundPredicate<>(Expression.Operation.NOT_NULL, expr);
|
124 | 125 | }
|
125 | 126 |
|
| 127 | + public static <T> UnboundPredicate<T> isNaN(String name) { |
| 128 | + return new UnboundPredicate<>(Expression.Operation.IS_NAN, ref(name)); |
| 129 | + } |
| 130 | + |
| 131 | + public static <T> UnboundPredicate<T> isNaN(UnboundTerm<T> expr) { |
| 132 | + return new UnboundPredicate<>(Expression.Operation.IS_NAN, expr); |
| 133 | + } |
| 134 | + |
| 135 | + public static <T> UnboundPredicate<T> notNaN(String name) { |
| 136 | + return new UnboundPredicate<>(Expression.Operation.NOT_NAN, ref(name)); |
| 137 | + } |
| 138 | + |
| 139 | + public static <T> UnboundPredicate<T> notNaN(UnboundTerm<T> expr) { |
| 140 | + return new UnboundPredicate<>(Expression.Operation.NOT_NAN, expr); |
| 141 | + } |
| 142 | + |
126 | 143 | public static <T> UnboundPredicate<T> lessThan(String name, T value) {
|
| 144 | + validateInput("lessThan", value); |
127 | 145 | return new UnboundPredicate<>(Expression.Operation.LT, ref(name), value);
|
128 | 146 | }
|
129 | 147 |
|
130 | 148 | public static <T> UnboundPredicate<T> lessThan(UnboundTerm<T> expr, T value) {
|
| 149 | + validateInput("lessThan", value); |
131 | 150 | return new UnboundPredicate<>(Expression.Operation.LT, expr, value);
|
132 | 151 | }
|
133 | 152 |
|
134 | 153 | public static <T> UnboundPredicate<T> lessThanOrEqual(String name, T value) {
|
| 154 | + validateInput("lessThanOrEqual", value); |
135 | 155 | return new UnboundPredicate<>(Expression.Operation.LT_EQ, ref(name), value);
|
136 | 156 | }
|
137 | 157 |
|
138 | 158 | public static <T> UnboundPredicate<T> lessThanOrEqual(UnboundTerm<T> expr, T value) {
|
| 159 | + validateInput("lessThanOrEqual", value); |
139 | 160 | return new UnboundPredicate<>(Expression.Operation.LT_EQ, expr, value);
|
140 | 161 | }
|
141 | 162 |
|
142 | 163 | public static <T> UnboundPredicate<T> greaterThan(String name, T value) {
|
| 164 | + validateInput("greaterThan", value); |
143 | 165 | return new UnboundPredicate<>(Expression.Operation.GT, ref(name), value);
|
144 | 166 | }
|
145 | 167 |
|
146 | 168 | public static <T> UnboundPredicate<T> greaterThan(UnboundTerm<T> expr, T value) {
|
| 169 | + validateInput("greaterThan", value); |
147 | 170 | return new UnboundPredicate<>(Expression.Operation.GT, expr, value);
|
148 | 171 | }
|
149 | 172 |
|
150 | 173 | public static <T> UnboundPredicate<T> greaterThanOrEqual(String name, T value) {
|
| 174 | + validateInput("greaterThanOrEqual", value); |
151 | 175 | return new UnboundPredicate<>(Expression.Operation.GT_EQ, ref(name), value);
|
152 | 176 | }
|
153 | 177 |
|
154 | 178 | public static <T> UnboundPredicate<T> greaterThanOrEqual(UnboundTerm<T> expr, T value) {
|
| 179 | + validateInput("greaterThanOrEqual", value); |
155 | 180 | return new UnboundPredicate<>(Expression.Operation.GT_EQ, expr, value);
|
156 | 181 | }
|
157 | 182 |
|
158 | 183 | public static <T> UnboundPredicate<T> equal(String name, T value) {
|
| 184 | + validateInput("equal", value); |
159 | 185 | return new UnboundPredicate<>(Expression.Operation.EQ, ref(name), value);
|
160 | 186 | }
|
161 | 187 |
|
162 | 188 | public static <T> UnboundPredicate<T> equal(UnboundTerm<T> expr, T value) {
|
| 189 | + validateInput("equal", value); |
163 | 190 | return new UnboundPredicate<>(Expression.Operation.EQ, expr, value);
|
164 | 191 | }
|
165 | 192 |
|
166 | 193 | public static <T> UnboundPredicate<T> notEqual(String name, T value) {
|
| 194 | + validateInput("notEqual", value); |
167 | 195 | return new UnboundPredicate<>(Expression.Operation.NOT_EQ, ref(name), value);
|
168 | 196 | }
|
169 | 197 |
|
170 | 198 | public static <T> UnboundPredicate<T> notEqual(UnboundTerm<T> expr, T value) {
|
| 199 | + validateInput("notEqual", value); |
171 | 200 | return new UnboundPredicate<>(Expression.Operation.NOT_EQ, expr, value);
|
172 | 201 | }
|
173 | 202 |
|
@@ -216,29 +245,43 @@ public static <T> UnboundPredicate<T> notIn(UnboundTerm<T> expr, Iterable<T> val
|
216 | 245 | }
|
217 | 246 |
|
218 | 247 | public static <T> UnboundPredicate<T> predicate(Operation op, String name, T value) {
|
| 248 | + validateInput(op.toString(), value); |
219 | 249 | return predicate(op, name, Literals.from(value));
|
220 | 250 | }
|
221 | 251 |
|
222 | 252 | public static <T> UnboundPredicate<T> predicate(Operation op, String name, Literal<T> lit) {
|
223 |
| - Preconditions.checkArgument(op != Operation.IS_NULL && op != Operation.NOT_NULL, |
| 253 | + Preconditions.checkArgument( |
| 254 | + op != Operation.IS_NULL && op != Operation.NOT_NULL && op != Operation.IS_NAN && op != Operation.NOT_NAN, |
224 | 255 | "Cannot create %s predicate inclusive a value", op);
|
225 | 256 | return new UnboundPredicate<T>(op, ref(name), lit);
|
226 | 257 | }
|
227 | 258 |
|
228 | 259 | public static <T> UnboundPredicate<T> predicate(Operation op, String name, Iterable<T> values) {
|
| 260 | + validateInput(op.toString(), values); |
229 | 261 | return predicate(op, ref(name), values);
|
230 | 262 | }
|
231 | 263 |
|
232 | 264 | public static <T> UnboundPredicate<T> predicate(Operation op, String name) {
|
233 |
| - Preconditions.checkArgument(op == Operation.IS_NULL || op == Operation.NOT_NULL, |
| 265 | + Preconditions.checkArgument( |
| 266 | + op == Operation.IS_NULL || op == Operation.NOT_NULL || op == Operation.IS_NAN || op == Operation.NOT_NAN, |
234 | 267 | "Cannot create %s predicate without a value", op);
|
235 | 268 | return new UnboundPredicate<>(op, ref(name));
|
236 | 269 | }
|
237 | 270 |
|
238 | 271 | private static <T> UnboundPredicate<T> predicate(Operation op, UnboundTerm<T> expr, Iterable<T> values) {
|
| 272 | + validateInput(op.toString(), values); |
239 | 273 | return new UnboundPredicate<>(op, expr, values);
|
240 | 274 | }
|
241 | 275 |
|
| 276 | + private static <T> void validateInput(String op, T value) { |
| 277 | + Preconditions.checkArgument(!NaNUtil.isNaN(value), String.format("Cannot create %s predicate with NaN", op)); |
| 278 | + } |
| 279 | + |
| 280 | + private static <T> void validateInput(String op, Iterable<T> values) { |
| 281 | + Preconditions.checkArgument(Lists.newArrayList(values).stream().noneMatch(NaNUtil::isNaN), |
| 282 | + String.format("Cannot create %s predicate with NaN", op)); |
| 283 | + } |
| 284 | + |
242 | 285 | public static True alwaysTrue() {
|
243 | 286 | return True.INSTANCE;
|
244 | 287 | }
|
|
0 commit comments