/** * Returns a schema that matches all the number types that results by promoting the number types * in the specified input schemata to a common type. If any input can be null, adds nullability. * Returns null if inputs neither match null or any number. */ public static Schema promote(Schema s1, Schema s2) { // check for nulls boolean isNullable = s1.is(NULL).maybe() || s2.is(NULL).maybe(); s1 = SchemaTransformation.removeNullability(s1); s2 = SchemaTransformation.removeNullability(s2); if (s1 == null || s2 == null) { return SchemaFactory.nullSchema(); } // check for numeric types boolean s1l = s1.is(JsonType.LONG).maybe(); boolean s1d = s1.is(JsonType.DOUBLE).maybe(); boolean s1m = s1.is(JsonType.DECFLOAT).maybe(); boolean s2l = s2.is(JsonType.LONG).maybe(); boolean s2d = s2.is(JsonType.DOUBLE).maybe(); boolean s2m = s2.is(JsonType.DECFLOAT).maybe(); if (!(s1l || s1d || s1m) || !(s2l || s2d || s2m)) return null; // non-number inputs List<Schema> result = new ArrayList<Schema>(4); if (s1l && s2l) { result.add(SchemaFactory.longSchema()); } if (((s1l || s1d) && s2d) || (s1d && (s2l || s2d))) { result.add(SchemaFactory.doubleSchema()); } if (s1m || s2m) { result.add(SchemaFactory.decfloatSchema()); } assert result.size() > 0; if (isNullable) { result.add(SchemaFactory.nullSchema()); } return OrSchema.make(result); }
@Override public PathStepSchema getSchema(Schema inputSchema) { Schema result = null; if (indexExpr() instanceof ConstExpr) { ConstExpr c = (ConstExpr) indexExpr(); JsonLong i = new JsonLong(((JsonNumber) c.value).longValueExact()); result = inputSchema.element(i); if (result != null && inputSchema.hasElement(i).maybeNot()) { result = SchemaTransformation.addNullability(result); } } if (result == null) { result = SchemaFactory.anySchema(); } return nextStep().getSchema(result); }
@Override public Schema getSchema() { Schema s1 = exprs[0].getSchema(); Schema s2 = exprs[1].getSchema(); Schema result = promote(s1, s2); if (s1.is(JsonType.STRING).maybe() && s2.is(JsonType.STRING).maybe()) { if (result == null) { return SchemaFactory.stringSchema(); } else { return OrSchema.make(SchemaFactory.stringSchema(), result); } } if (result == null) { throw new RuntimeException("Operation " + OP_STR[op] + " not defined for input types."); } return result; }