package org.reldb.rel.v0.storage; import org.reldb.rel.v0.generator.*; import org.reldb.rel.v0.types.*; import org.reldb.rel.v0.types.builtin.TypeBoolean; import org.reldb.rel.v0.types.builtin.TypeCharacter; import org.reldb.rel.v0.types.builtin.TypeInteger; import org.reldb.rel.v0.types.builtin.TypeRational; import org.reldb.rel.v0.values.*; import org.reldb.rel.v0.vm.*; /** Class for defining built-in operators. */ public class BuiltinOperators { private Generator generator; private void is_empty(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("IS_EMPTY", "// True if relation r is empty\n" + "IS_EMPTY(r RELATION{*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueRelation relation = (ValueRelation)arguments[0]; return relation.is_empty(); } } ) ); } private void countRelation(final RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("COUNT", "// Return cardinality of relation r\n" + "COUNT(r RELATION{*}) RETURNS INTEGER", new Type[] {TypeRelation.getEmptyRelationType()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueRelation relation = (ValueRelation)arguments[0]; return ValueInteger.select(generator, relation.getCardinality()); } } ) ); } private void countArray(final RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("COUNT", "// Return cardinality of ARRAY r\n" + "COUNT(r ARRAY OF TUPLE {*}) RETURNS INTEGER", new Type[] {TypeArray.getEmptyArrayType()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return ValueInteger.select(generator, array.getCount()); } } ) ); } private void sum(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_SUM_INTEGER", "// INTEGER sum of r\n" + "AGGREGATE_SUM_INTEGER(r ARRAY OF TUPLE {AGGREGAND INT, AGGREGATION_SERIAL INT}) RETURNS INTEGER", new Type[] {TypeArray.getEmptyArrayType()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.sumInteger(0); } } ) ); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_SUM_RATIONAL", "// RATIONAL sum of r\n" + "AGGREGATE_SUM_RATIONAL(r ARRAY OF TUPLE {AGGREGAND RATIONAL, AGGREGATION_SERIAL INT}) RETURNS RATIONAL", new Type[] {TypeArray.getEmptyArrayType()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.sumRational(0); } } ) ); } private void avg(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_AVG_INTEGER", "// Arithmetic mean of r\n" + "AGGREGATE_AVG_INTEGER(r ARRAY OF TUPLE {AGGREGAND INT, AGGREGATION_SERIAL INT}) RETURNS RATIONAL", new Type[] {TypeArray.getEmptyArrayType()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.avgInteger(0); } } ) ); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_AVG_RATIONAL", "// Arithmetic mean of r\n" + "AGGREGATE_AVG_INTEGER(r ARRAY OF TUPLE {AGGREGAND RATIONAL, AGGREGATION_SERIAL INT}) RETURNS RATIONAL", new Type[] {TypeArray.getEmptyArrayType()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.avgRational(0); } } ) ); } private void max(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_MAX", "// Maximum of r\n" + "AGGREGATE_MAX(r ARRAY OF TUPLE {AGGREGAND ALPHA, AGGREGATION_SERIAL INT}) RETURNS ALPHA", new Type[] {TypeArray.getEmptyArrayType()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.max(0); } } ) ); } private void min(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_MIN", "// Minimum of r\n" + "AGGREGATE_MIN(r ARRAY OF TUPLE {AGGREGAND ALPHA, AGGREGATION_SERIAL INT}) RETURNS ALPHA", new Type[] {TypeArray.getEmptyArrayType()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.min(0); } } ) ); } private void and(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_AND", "// Logical AND of r\n" + "AGGREGATE_AND(r ARRAY OF TUPLE {AGGREGAND BOOLEAN, AGGREGATION_SERIAL INT}) RETURNS BOOLEAN", new Type[] {TypeArray.getEmptyArrayType()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.and(0); } } ) ); } private void or(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_OR", "// Logical OR of r\n" + "AGGREGATE_OR(r ARRAY OF TUPLE {AGGREGAND BOOLEAN, AGGREGATION_SERIAL INT}) RETURNS BOOLEAN", new Type[] {TypeArray.getEmptyArrayType()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.or(0); } } ) ); } private void xor(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_XOR", "// Logical exclusive-OR of r\n" + "AGGREGATE_XOR(r ARRAY OF TUPLE {AGGREGAND BOOLEAN, AGGREGATION_SERIAL INT}) RETURNS BOOLEAN", new Type[] {TypeArray.getEmptyArrayType()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.xor(0); } } ) ); } private void equiv(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_EQUIV", "// Logical EQUIV (aka '=') of r\n" + "AGGREGATE_EQUIV(r ARRAY OF TUPLE {AGGREGAND BOOLEAN, AGGREGATION_SERIAL INT}) RETURNS BOOLEAN", new Type[] {TypeArray.getEmptyArrayType()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.equiv(0); } } ) ); } private void union(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_UNION", "// UNION of r\n" + "AGGREGATE_UNION(r ARRAY OF TUPLE {AGGREGAND RELATION {*}, AGGREGATION_SERIAL INT}) RETURNS RELATION {*}", new Type[] {TypeArray.getEmptyArrayType()}, TypeRelation.getEmptyRelationType(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.union(0); } } ) ); } private void xunion(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_XUNION", "// exclusive-UNION of r\n" + "AGGREGATE_XUNION(r ARRAY OF TUPLE {AGGREGAND RELATION {*}, AGGREGATION_SERIAL INT}) RETURNS RELATION {*}", new Type[] {TypeArray.getEmptyArrayType()}, TypeRelation.getEmptyRelationType(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.xunion(0); } } ) ); } private void d_union(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_D_UNION", "// disjoint-UNION of r\n" + "AGGREGATE_DUNION(r ARRAY OF TUPLE {AGGREGAND RELATION {*}, AGGREGATION_SERIAL INT}) RETURNS RELATION {*}", new Type[] {TypeArray.getEmptyArrayType()}, TypeRelation.getEmptyRelationType(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.d_union(0); } } ) ); } private void intersect(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("AGGREGATE_INTERSECT", "// INTERSECT of r\n" + "AGGREGATE_INTERSECT(r ARRAY OF TUPLE {AGGREGAND RELATION {*}, AGGREGATION_SERIAL INT}) RETURNS RELATION {*}", new Type[] {TypeArray.getEmptyArrayType()}, TypeRelation.getEmptyRelationType(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = (ValueArray)arguments[0]; return array.intersect(0); } } ) ); } // TODO - rewrite to work on ARRAYs private void exactly(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("EXACTLY", "// Return true if COUNT of true equals n\n" + "EXACTLY(r ARRAY OF TUPLE {AGGREGAND BOOLEAN, AGGREGATION_SERIAL INT}, idx INTEGER, n INTEGER) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeInteger.getInstance(), TypeInteger.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueRelation relation = (ValueRelation)arguments[0]; int attributeIndex = (int)arguments[1].longValue(); long nCount = arguments[2].longValue(); return relation.exactly(nCount, attributeIndex); } } ) ); } private static Type[] primitiveTypes = new Type[] { TypeBoolean.getInstance(), TypeInteger.getInstance(), TypeRational.getInstance(), TypeCharacter.getInstance() }; private void cast_as_boolean(RelDatabase database) { for (Type type: primitiveTypes) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("CAST_AS_BOOLEAN", "// Return n as BOOLEAN\n" + "CAST_AS_BOOLEAN(n " + type.getSignature() + ") RETURNS BOOLEAN", new Type[] {type}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].booleanValue()); } } ) ); } } private void cast_as_integer(RelDatabase database) { for (Type type: primitiveTypes) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("CAST_AS_INTEGER", "// Return n as INTEGER\n" + "CAST_AS_INTEGER(n " + type.getSignature() + ") RETURNS INTEGER", new Type[] {type}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueInteger.select(generator, arguments[0].longValue()); } } ) ); } } private void cast_as_rational(RelDatabase database) { for (Type type: primitiveTypes) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("CAST_AS_RATIONAL", "// Return n as RATIONAL\n" + "CAST_AS_RATIONAL(n " + type.getSignature() + ") RETURNS RATIONAL", new Type[] {type}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueRational.select(generator, arguments[0].doubleValue()); } } ) ); } } private void cast_as_char(RelDatabase database) { for (Type type: primitiveTypes) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("CAST_AS_CHAR", "// Return n as CHAR\n" + "CAST_AS_CHAR(n " + type.getSignature() + ") RETURNS CHAR", new Type[] {type}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, arguments[0].stringValue()); } } ) ); } } private void equals(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.EQUALS, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])==0); } } ) ); } private void equals(RelDatabase database) { equals(database, "// Return true if p equals q\n" + "OP_EQUALS(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); equals(database, "// Return true if p equals q\n" + "OP_EQUALS(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); equals(database, "// Return true if p equals q\n" + "OP_EQUALS(p ALPHA, q ALPHA) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void notequals(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.NOTEQUALS, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])!=0); } } ) ); } private void notequals(RelDatabase database) { notequals(database, "// Return true if p is not equal to q\n" + "OP_NOTEQUALS(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); notequals(database, "// Return true if p is not equal to q\n" + "OP_NOTEQUALS(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); notequals(database, "// Return true if p is not equal to q\n" + "OP_NOTEQUALS(p ALPHA, q ALPHA) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void greaterthanequals(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.GREATERTHANOREQUALS, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])>=0); } } ) ); } private void superset(String opName, RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(opName, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, ((ValueRelation)arguments[0]).isSupersetOf((ValueRelation)arguments[1])); } } ) ); } private void greaterthanequals(RelDatabase database) { superset(BuiltinTypeBuilder.GREATERTHANOREQUALS, database, "// Return true if p is greater than or equal to q\n" + "OP_GREATERTHANOREQUALS(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); superset(BuiltinTypeBuilder.SUPERSETOREQUAL, database, "// Return true if p is a superset of or equal to q\n" + "OP_SUPERSETOREQUAL(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); greaterthanequals(database, "// Return true if p is greater than or equal to q\n" + "OP_GREATERTHANOREQUALS(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); greaterthanequals(database, "// Return true if p is greater than or equal to q\n" + "OP_GREATERTHANOREQUALS(p ALPHA, q ALPHA) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void lessthanequals(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.LESSTHANOREQUALS, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])<=0); } } ) ); } private void subset(String opName, RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(opName, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, ((ValueRelation)arguments[0]).isSubsetOf((ValueRelation)arguments[1])); } } ) ); } private void lessthanequals(RelDatabase database) { subset(BuiltinTypeBuilder.LESSTHANOREQUALS, database, "// Return true if p is less than or equal to q\n" + "OP_LESSTHANOREQUALS(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); subset(BuiltinTypeBuilder.SUBSETOREQUAL, database, "// Return true if p is a subset of or equal to q\n" + "OP_SUBSETOREQUAL(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); lessthanequals(database, "// Return true if p is less than or equal to q\n" + "OP_LESSTHANOREQUALS(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); lessthanequals(database, "// Return true if p is less than or equal to q\n" + "OP_LESSTHANOREQUALS(p ALPHA, q ALPHA) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void greaterthan(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.GREATERTHAN, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])>0); } } ) ); } private void propersuperset(String opName, RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(opName, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, ((ValueRelation)arguments[0]).isProperSupersetOf((ValueRelation)arguments[1])); } } ) ); } private void greaterthan(RelDatabase database) { propersuperset(BuiltinTypeBuilder.GREATERTHAN, database, "// Return true if p is greater than q\n" + "OP_GREATERTHAN(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); propersuperset(BuiltinTypeBuilder.SUPERSET, database, "// Return true if p is a proper superset of q\n" + "OP_SUPERSET(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); greaterthan(database, "// Return true if p is greater than q\n" + "OP_GREATERTHAN(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); greaterthan(database, "// Return true if p is greater than q\n" + "OP_GREATERTHAN(p ALPHA, q ALPHA) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void lessthan(RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(BuiltinTypeBuilder.LESSTHAN, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].compareTo(arguments[1])<0); } } ) ); } private void propersubset(String opName, RelDatabase database, String docs, Type[] parameters) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction(opName, docs, parameters, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, ((ValueRelation)arguments[0]).isProperSubsetOf((ValueRelation)arguments[1])); } } ) ); } private void lessthan(RelDatabase database) { propersubset(BuiltinTypeBuilder.LESSTHAN, database, "// Return true if p is less than q\n" + "OP_LESSTHAN(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); propersubset(BuiltinTypeBuilder.SUBSET, database, "// Return true if p is a proper subset of q\n" + "OP_SUBSET(p RELATION {*}, q RELATION {*}) RETURNS BOOLEAN", new Type[] {TypeRelation.getEmptyRelationType(), TypeRelation.getEmptyRelationType()}); lessthan(database, "// Return true if p is less than q\n" + "OP_LESSTHAN(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeTuple.getEmptyTupleType(), TypeTuple.getEmptyTupleType()}); lessthan(database, "// Return true if p is less than q\n" + "OP_LESSTHAN(p TUPLE {*}, q TUPLE {*}) RETURNS BOOLEAN", new Type[] {TypeAlpha.getEmptyAlphaType(), TypeAlpha.getEmptyAlphaType()}); } private void getuniquenumber(final RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("GET_UNIQUE_NUMBER", "// Obtain a unique number\n" + "GET_UNIQUE_NUMBER() RETURNS INTEGER", new Type[] {}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueInteger.select(generator, database.getUniqueID()); } } ) ); } private void setuniquenumber(final RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeProcedure("SET_UNIQUE_NUMBER", "// Set the next unique number. Must be greater than the current next unique number.\n" + "SET_UNIQUE_NUMBER(n INTEGER)", new Type[] {TypeInteger.getInstance()}, new NativeProcedure() { public void execute(Value arguments[]) { database.setUniqueID(((ValueInteger)arguments[0]).longValue()); } } ) ); } private void sequence2(final RelDatabase database, Type[] parameters) { Heading resultHeading = new Heading(); resultHeading.add("N", TypeInteger.getInstance()); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SEQUENCE", "// Return a RELATION {n INTEGER} where n ranges from start to end.\n" + "SEQUENCE(start INTEGER, end INTEGER) RETURNS RELATION {n INTEGER}", parameters, (new TypeRelation(resultHeading)), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueRelation.sequence(generator, (ValueInteger)arguments[0], (ValueInteger)arguments[1]); } } ) ); } private void sequence3(final RelDatabase database, Type[] parameters) { Heading resultHeading = new Heading(); resultHeading.add("N", TypeInteger.getInstance()); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SEQUENCE", "// Return a RELATION {n INTEGER} where n ranges from start to end, stepping by step.\n" + "SEQUENCE(start INTEGER, end INTEGER, step INTEGER) RETURNS RELATION {n INTEGER}", parameters, (new TypeRelation(resultHeading)), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueRelation.sequence(generator, (ValueInteger)arguments[0], (ValueInteger)arguments[1], (ValueInteger)arguments[2]); } } ) ); } private void sequence(RelDatabase database) { sequence2(database, new Type[] {TypeInteger.getInstance(), TypeInteger.getInstance()}); sequence3(database, new Type[] {TypeInteger.getInstance(), TypeInteger.getInstance(), TypeInteger.getInstance()}); } private void quote(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("QUOTE", "// Return s with special characters quoted\n" + "QUOTE(s CHAR) RETURNS CHAR", new Type[] {TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, StringUtils.quote(arguments[0].stringValue())); } } ) ); } private void unquote(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("UNQUOTE", "// Return s with quoted special characters unquoted\n" + "UNQUOTE(s CHAR) RETURNS CHAR", new Type[] {TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, StringUtils.unquote(arguments[0].stringValue())); } } ) ); } /** Assorted CHAR operators, largely based on Java String methods. */ private void is_digits(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("IS_DIGITS", "// Return TRUE if s is all numeric digits\n" + "IS_DIGITS(s CHAR) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { String sbuf = arguments[0].stringValue(); for (int i=0; i<sbuf.length(); i++) if (!Character.isDigit(sbuf.charAt(i))) return ValueBoolean.select(generator, false); return ValueBoolean.select(generator, true); } } ) ); } private void length(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("LENGTH", "// Return the length of s\n" + "LENGTH(s CHAR) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueInteger.select(generator, arguments[0].stringValue().length()); } } ) ); } private void substring2(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SUBSTRING", "// Return the 0-based substring of s, starting from beginIndex\n" + "SUBSTRING(s CHAR, beginIndex INTEGER) RETURNS CHAR", new Type[] {TypeCharacter.getInstance(), TypeInteger.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Substring, 0 based return ValueCharacter.select(generator, arguments[0].stringValue().substring((int)arguments[1].longValue())); } } ) ); } private void substring3(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SUBSTRING", "// Return the 0-based substring of s, starting from beginIndex and extending to endIndex - 1\n" + "SUBSTRING(s CHAR, beginIndex INTEGER, endIndex INTEGER) RETURNS CHAR", new Type[] {TypeCharacter.getInstance(), TypeInteger.getInstance(), TypeInteger.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Substring, 0 based return ValueCharacter.select(generator, arguments[0].stringValue().substring((int)arguments[1].longValue(), (int)arguments[2].longValue())); } } ) ); } private void compare_to(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("COMPARE_TO", "// Perform the lexicographic comparison of p and q, to return the value 0 if p is equal to q;\n" + "// a value less than 0 if p is lexicographically less than q;\n" + "// and a value greater than 0 if p is lexicographically greater than q.\n" + "COMPARE_TO(p CHAR, q CHAR) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Compares two strings lexicographically. return ValueInteger.select(generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())); } } ) ); } private void compare_to_ignore_case(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("COMPARE_TO_IGNORE_CASE", "// Perform the case-insensitive lexicographic comparison of p and q, to return the value 0 if p is equal to q;\n" + "// a value less than 0 if p is lexicographically less than q;\n" + "// and a value greater than 0 if p is lexicographically greater than q.\n" + "COMPARE_TO_IGNORE_CASE(p CHAR, q CHAR) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Compares two strings lexicographically. return ValueInteger.select(generator, arguments[0].stringValue().compareToIgnoreCase(arguments[1].stringValue())); } } ) ); } private void ends_with(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ENDS_WITH", "// Return true if p ends with suffix q\n" + "ENDS_WITH(p CHAR, q CHAR) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueBoolean.select(generator, arguments[0].stringValue().endsWith(arguments[1].stringValue())); } } ) ); } private void equals_ignore_case(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("EQUALS_IGNORE_CASE", "// Return true if p equals q, ignoring case\n" + "EQUALS_IGNORE_CASE(p CHAR, q CHAR) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Compares this String to another String, ignoring case considerations. return ValueBoolean.select(generator, arguments[0].stringValue().equalsIgnoreCase(arguments[1].stringValue())); } } ) ); } private void index_of2(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("INDEX_OF", "// Return the 0-based index of the first occurrence of needle in haystack. Return -1 if not found.\n" + "INDEX_OF(CHAR haystack, CHAR needle) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the index within this string of the first occurrence of the specified substring. return ValueInteger.select(generator, arguments[0].stringValue().indexOf(arguments[1].stringValue())); } } ) ); } private void index_of3(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("INDEX_OF", "// Return the 0-based index of the first occurrence of needle in haystack, starting at index. Return -1 if not found.\n" + "INDEX_OF(CHAR haystack, CHAR needle, INTEGER index) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeInteger.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the index within this string of the first occurrence of the // specified substring, starting at the specified index. return ValueInteger.select(generator, arguments[0].stringValue().indexOf(arguments[1].stringValue(), (int)arguments[2].longValue())); } } ) ); } private void last_index_of2(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("LAST_INDEX_OF", "// Return the 0-based index of the last occurrence of needle in haystack. Return -1 if not found.\n" + "LAST_INDEX_OF(CHAR haystack, CHAR needle) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the index within this string of the last occurrence of the specified substring. return ValueInteger.select(generator, arguments[0].stringValue().lastIndexOf(arguments[1].stringValue())); } } ) ); } private void last_index_of3(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("LAST_INDEX_OF", "// Return the 0-based index of the last occurrence of needle in haystack, starting at index. Return -1 if not found.\n" + "LAST_INDEX_OF(CHAR haystack, CHAR needle, INTEGER index) RETURNS INTEGER", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeInteger.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the index within this string of the last occurrence of the // specified substring, starting at the specified index. return ValueInteger.select(generator, arguments[0].stringValue().lastIndexOf(arguments[1].stringValue(), (int)arguments[2].longValue())); } } ) ); } private void matches(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MATCHES", "// Return TRUE if p matches the regular expression regexp.\n" + "MATCHES(CHAR p, CHAR regexp) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Tells whether or not this string matches the given regular expression. return ValueBoolean.select(generator, arguments[0].stringValue().matches(arguments[1].stringValue())); } } ) ); } private void region_matches(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("REGION_MATCHES", "// Return TRUE if two string regions are equal.\n" + "MATCHES(CHAR p, BOOLEAN ignoreCase, INTEGER offsetP, CHAR q, INTEGER offsetQ, INTEGER length) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeBoolean.getInstance(), TypeInteger.getInstance(), TypeCharacter.getInstance(), TypeInteger.getInstance(), TypeInteger.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Tests if two string regions are equal. return ValueBoolean.select(generator, arguments[0].stringValue().regionMatches(arguments[1].booleanValue(), (int)arguments[2].longValue(), arguments[3].stringValue(), (int)arguments[4].longValue(), (int)arguments[5].longValue())); } } ) ); } private void replace_all(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("REPLACE_ALL", "// Return p with each substring of p that matches regexp replaced with q.\n" + "REPLACE_ALL(CHAR p, CHAR regexp, CHAR q) RETURNS CHAR", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Replaces each substring of this string that matches the given regular expression with the given replacement. return ValueCharacter.select(generator, arguments[0].stringValue().replaceAll(arguments[1].stringValue(), arguments[2].stringValue())); } } ) ); } private void replace_first(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("REPLACE_FIRST", "// Return p with the first substring of p that matches regexp replaced with q.\n" + "REPLACE_FIRST(CHAR p, CHAR regexp, CHAR q) RETURNS CHAR", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Replaces the first substring of this string that matches the given regular expression with the given replacement. return ValueCharacter.select(generator, arguments[0].stringValue().replaceFirst(arguments[1].stringValue(), arguments[2].stringValue())); } } ) ); } private void split2(RelDatabase database) { Heading arrayHeading = new Heading(); arrayHeading.add("str", TypeCharacter.getInstance()); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SPLIT", "// Split p around matches of the regexp.\n" + "SPLIT(CHAR p, CHAR regexp) RETURNS ARRAY OF TUPLE {str CHAR}", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, new TypeArray(arrayHeading), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = new ValueArray(generator); String[] ss = arguments[0].stringValue().split(arguments[1].stringValue()); for (int i=0; i<ss.length; i++) { Value[] tupleValues = new Value[] {ValueCharacter.select(generator, ss[i])}; ValueTuple tuple = new ValueTuple(generator, tupleValues); array.append(tuple); } return array; } } ) ); } private void split3(RelDatabase database) { Heading arrayHeading = new Heading(); arrayHeading.add("str", TypeCharacter.getInstance()); database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SPLIT", "// Split p around matches of the regexp up to n times.\n" + "SPLIT(CHAR p, CHAR regexp, n INTEGER) RETURNS ARRAY OF TUPLE {str CHAR}", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeInteger.getInstance()}, new TypeArray(arrayHeading), new NativeFunction() { public Value evaluate(Value arguments[]) { ValueArray array = new ValueArray(generator); String[] ss = arguments[0].stringValue().split(arguments[1].stringValue(), (int)arguments[2].longValue()); for (int i=0; i<ss.length; i++) { Value[] tupleValues = new Value[] {ValueCharacter.select(generator, ss[i])}; ValueTuple tuple = new ValueTuple(generator, tupleValues); array.append(tuple); } return array; } } ) ); } private void starts_with2(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("STARTS_WITH", "// Return TRUE if p starts with prefix q.\n" + "STARTS_WITH(CHAR p, CHAR q) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Tests if this string starts with the specified prefix. return ValueBoolean.select(generator, arguments[0].stringValue().startsWith(arguments[1].stringValue())); } } ) ); } private void starts_with3(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("STARTS_WITH", "// Return TRUE if p starts with prefix q, starting at index.\n" + "STARTS_WITH(CHAR p, CHAR q, INTEGER index) RETURNS BOOLEAN", new Type[] {TypeCharacter.getInstance(), TypeCharacter.getInstance(), TypeInteger.getInstance()}, TypeBoolean.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Tests if this string starts with the specified prefix beginning at a specified index. return ValueBoolean.select(generator, arguments[0].stringValue().startsWith(arguments[1].stringValue(), (int)arguments[2].longValue())); } } ) ); } private void to_lower_case(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TO_LOWER_CASE", "// Return p converted to lower case.\n" + "TO_LOWER_CASE(CHAR p) RETURNS CHAR", new Type[] {TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, arguments[0].stringValue().toLowerCase()); } } ) ); } private void to_upper_case(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TO_UPPER_CASE", "// Return p converted to upper case.\n" + "TO_UPPER_CASE(CHAR p) RETURNS CHAR", new Type[] {TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, arguments[0].stringValue().toUpperCase()); } } ) ); } private void trim(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TRIM", "// Return p with leading and trailing whitespace removed\n" + "TRIM(p CHAR) RETURNS CHAR", new Type[] {TypeCharacter.getInstance()}, TypeCharacter.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { return ValueCharacter.select(generator, arguments[0].stringValue().trim()); } } ) ); } /** Math operators. These are essentially a wrapper around the Java Math package. */ private void e(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("E", "// Return the RATIONAL value that is closer than any other to e, the base of the natural logarithms.\n" + "E() RETURNS RATIONAL", new Type[] {}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // The RATIONAL value that is closer than any other to e, the base of // the natural logarithms. return ValueRational.select(generator, Math.E); } } ) ); } private void pi(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("PI", "// Return the RATIONAL value that is closer than any other to pi, the ratio of the circumference of a circle to its diameter\n" + "PI() RETURNS RATIONAL", new Type[] {}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // The RATIONAL value that is closer than any other to pi, the ratio of // the circumference of a circle to its diameter. return ValueRational.select(generator, Math.PI); } } ) ); } private void absRational(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ABS", "// Return the absolute value of p\n" + "ABS(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the absolute value of a RATIONAL value. return ValueRational.select(generator, Math.abs(arguments[0].doubleValue())); } } ) ); } private void absInteger(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ABS", "// Return the absolute value of p\n" + "ABS(p INTEGER) RETURNS INTEGER", new Type[] {TypeInteger.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the absolute value of an INTEGER value. return ValueRational.select(generator, Math.abs(arguments[0].longValue())); } } ) ); } private void acos(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ACOS", "// Return the arc cosine of an angle p, in the range of 0.0 through pi\n" + "ACOS(p INTEGER) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the arc cosine of an angle, in the range of 0.0 through pi. return ValueRational.select(generator, Math.acos(arguments[0].doubleValue())); } } ) ); } private void asin(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ASIN", "// Return the arc sine of an angle p, in the range of -pi/2 through pi/2\n" + "ASIN(p INTEGER) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the arc sine of an angle, in the range of -pi/2 through pi/2. return ValueRational.select(generator, Math.asin(arguments[0].doubleValue())); } } ) ); } private void atan(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ATAN", "// Return the arc tangent of an angle p, in the range of -pi/2 through pi/2\n" + "ATAN(p INTEGER) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the arc tangent of an angle, in the range of -pi/2 through pi/2. return ValueRational.select(generator, Math.atan(arguments[0].doubleValue())); } } ) ); } private void atan2(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ATAN2", "// Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta).\n" + "// The phase theta is computed as an arc tangent of y/x in the range of -pi to pi.\n" + "ATAN2(x RATIONAL, y RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance(), TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Converts rectangular coordinates (x, y) to polar (r, theta). return ValueRational.select(generator, Math.atan2(arguments[1].doubleValue(), arguments[0].doubleValue())); } } ) ); } private void ceil(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("CEIL", "// Returns the smallest (closest to negative infinity) RATIONAL value that is not less than the argument\n" + "// and is equal to a mathematical integer.\n" + "CEIL(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the smallest (closest to negative infinity) RATIONAL value // that is not less than the argument and is equal to a mathematical // integer. return ValueRational.select(generator, Math.ceil(arguments[0].doubleValue())); } } ) ); } private void cos(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("COS", "// Returns the trigonometric cosine of an angle\n" + "COS(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the trigonometric cosine of an angle. return ValueRational.select(generator, Math.cos(arguments[0].doubleValue())); } } ) ); } private void exp(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("EXP", "// Returns Euler's number e raised to the power of a RATIONAL value.\n" + "EXP(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns Euler's number e raised to the power of a RATIONAL value. return ValueRational.select(generator, Math.exp(arguments[0].doubleValue())); } } ) ); } private void floor(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("FLOOR", "// Returns the largest (closest to positive infinity) RATIONAL value that is not greater than the argument\n" + "// and is equal to a mathematical integer.\n" + "FLOOR(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the largest (closest to positive infinity) RATIONAL value that // is not greater than the argument and is equal to a mathematical // integer. return ValueRational.select(generator, Math.floor(arguments[0].doubleValue())); } } ) ); } private void remainder(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("REMAINDER", "// Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard.\n" + "REMAINDER(p RATIONAL, q RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance(), TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard. return ValueRational.select(generator, Math.IEEEremainder(arguments[0].doubleValue(), arguments[1].doubleValue())); } } ) ); } private void log(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("LOG", "// Returns the natural logarithm (base e) of a RATIONAL value.\n" + "LOG(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the natural logarithm (base e) of a RATIONAL value. return ValueRational.select(generator, Math.log(arguments[0].doubleValue())); } } ) ); } private void maximumRational(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MAXIMUM", "// Returns the greater of two RATIONAL values.\n" + "MAXIMUM(p RATIONAL, q RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance(), TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the greater of two RATIONAL values. return ValueRational.select(generator, Math.max(arguments[0].doubleValue(), arguments[1].doubleValue())); } } ) ); } private void maximumInteger(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MAXIMUM", "// Returns the greater of two INTEGER values.\n" + "MAXIMUM(p INTEGER, q INTEGER) RETURNS INTEGER", new Type[] {TypeInteger.getInstance(), TypeInteger.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the greater of two INTEGER values. return ValueInteger.select(generator, Math.max(arguments[0].longValue(), arguments[1].longValue())); } } ) ); } private void minimumRational(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MINIMUM", "// Returns the smaller of two RATIONAL values.\n" + "MINIMUM(p RATIONAL, q RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance(), TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the smaller of two RATIONAL values. return ValueRational.select(generator, Math.min(arguments[0].doubleValue(), arguments[1].doubleValue())); } } ) ); } private void minimumInteger(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MINIMUM", "// Returns the smaller of two INTEGER values.\n" + "MINIMUM(p INTEGER, q INTEGER) RETURNS INTEGER", new Type[] {TypeInteger.getInstance(), TypeInteger.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the smaller of two INTEGER values. return ValueInteger.select(generator, Math.min(arguments[0].longValue(), arguments[1].longValue())); } } ) ); } private void pow(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("POW", "// Returns the value of the first argument raised to the power of the second argument.\n" + "POW(p RATIONAL, q RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance(), TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the value of the first argument raised to the power of the second argument. return ValueRational.select(generator, Math.pow(arguments[0].doubleValue(), arguments[1].doubleValue())); } } ) ); } private void random(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("RANDOM", "// Returns a pseudo-random RATIONAL value with a positive sign, greater than or equal to 0.0 and less than 1.0.\n" + "RANDOM() RETURNS RATIONAL", new Type[] {}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns a RATIONAL value with a positive sign, greater than or equal to 0.0 and less than 1.0. return ValueRational.select(generator, Math.random()); } } ) ); } private void rint(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("RINT", "// Returns the RATIONAL value that is closest in value to the argument and is equal to a mathematical integer.\n" + "RINT(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the RATIONAL value that is closest in value to the argument and is equal to a mathematical integer. return ValueRational.select(generator, Math.rint(arguments[0].doubleValue())); } } ) ); } private void round(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("ROUND", "// Returns the closest INTEGER to the argument.\n" + "ROUND(p RATIONAL) RETURNS INTEGER", new Type[] {TypeRational.getInstance()}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the closest INTEGER to the argument. return ValueInteger.select(generator, Math.round(arguments[0].doubleValue())); } } ) ); } private void sin(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SIN", "// Returns the trigonometric sine of an angle\n" + "SIN(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the trigonometric sine of an angle. return ValueRational.select(generator, Math.sin(arguments[0].doubleValue())); } } ) ); } private void sqrt(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("SQRT", "// Returns the correctly rounded positive square root of a RATIONAL value.\n" + "SQRT(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the correctly rounded positive square root of a RATIONAL value. return ValueRational.select(generator, Math.sqrt(arguments[0].doubleValue())); } } ) ); } private void tan(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TAN", "// Returns the trigonometric tangent of an angle\n" + "TAN(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Returns the trigonometric tangent of an angle. return ValueRational.select(generator, Math.tan(arguments[0].doubleValue())); } } ) ); } private void to_degrees(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TO_DEGREES", "// Converts an angle measured in radians to an approximately equivalent angle measured in degrees.\n" + "TO_DEGREES(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Converts an angle measured in radians to an approximately equivalent angle measured in degrees. return ValueRational.select(generator, Math.toDegrees(arguments[0].doubleValue())); } } ) ); } private void to_radians(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("TO_RADIANS", "// Converts an angle measured in degrees to an approximately equivalent angle measured in radians.\n" + "TO_RADIANS(p RATIONAL) RETURNS RATIONAL", new Type[] {TypeRational.getInstance()}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Converts an angle measured in degrees to an approximately equivalent angle measured in radians. return ValueRational.select(generator, Math.toRadians(arguments[0].doubleValue())); } } ) ); } /** Maxima and minima. */ private void max_integer(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MAX_INTEGER", "// Largest positive integer\n" + "MAX_INTEGER() RETURNS INTEGER", new Type[] {}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Largest positive integer return ValueInteger.select(generator, Long.MAX_VALUE); } } ) ); } private void min_integer(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MIN_INTEGER", "// Largest negative integer\n" + "MIN_INTEGER() RETURNS INTEGER", new Type[] {}, TypeInteger.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Largest negative integer return ValueInteger.select(generator, Long.MIN_VALUE); } } ) ); } private void max_rational(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MAX_RATIONAL", "// Largest positive RATIONAL\n" + "MAX_RATIONAL() RETURNS RATIONAL", new Type[] {}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Largest positive rational return ValueRational.select(generator, Double.MAX_VALUE); } } ) ); } private void min_rational(RelDatabase database) { database.defineBuiltinOperator( new OperatorDefinitionNativeFunction("MIN_RATIONAL", "// Largest negative RATIONAL\n" + "MIN_RATIONAL() RETURNS RATIONAL", new Type[] {}, TypeRational.getInstance(), new NativeFunction() { public Value evaluate(Value arguments[]) { // Smallest positive rational return ValueRational.select(generator, Double.MIN_VALUE); } } ) ); } private BuiltinOperators(RelDatabase database) { generator = new Generator(database, System.out); is_empty(database); countRelation(database); countArray(database); sum(database); avg(database); max(database); min(database); and(database); or(database); xor(database); equiv(database); union(database); xunion(database); d_union(database); intersect(database); exactly(database); cast_as_boolean(database); cast_as_integer(database); cast_as_rational(database); cast_as_char(database); equals(database); notequals(database); lessthanequals(database); greaterthanequals(database); lessthan(database); greaterthan(database); getuniquenumber(database); setuniquenumber(database); sequence(database); quote(database); unquote(database); is_digits(database); length(database); substring2(database); substring3(database); compare_to(database); compare_to_ignore_case(database); ends_with(database); equals_ignore_case(database); index_of2(database); index_of3(database); last_index_of2(database); last_index_of3(database); matches(database); region_matches(database); replace_all(database); replace_first(database); split2(database); split3(database); starts_with2(database); starts_with3(database); to_lower_case(database); to_upper_case(database); trim(database); e(database); pi(database); absRational(database); absInteger(database); acos(database); asin(database); atan(database); atan2(database); ceil(database); cos(database); exp(database); floor(database); remainder(database); log(database); maximumRational(database); maximumInteger(database); minimumRational(database); minimumInteger(database); pow(database); random(database); rint(database); round(database); sin(database); sqrt(database); tan(database); to_degrees(database); to_radians(database); max_integer(database); min_integer(database); max_rational(database); min_rational(database); } public static void buildOperators(RelDatabase database) { new BuiltinOperators(database); } }