mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-29 03:18:26 +00:00
Add FunctionPipe tests to all functions. Cleanup functions code. (cherry picked from commit 0f83d5799841fe99d8aeaf46e50dd11aa6bf8a57)
This commit is contained in:
parent
551b8bcd73
commit
69f73d948b
x-pack/plugin
eql/src
main/java/org/elasticsearch/xpack/eql
expression/function/scalar
math
string
Between.javaBetweenFunctionPipe.javaBetweenFunctionProcessor.javaCIDRMatch.javaCIDRMatchFunctionPipe.javaConcatFunctionPipe.javaEndsWith.javaEndsWithFunctionPipe.javaEndsWithFunctionProcessor.javaIndexOf.javaIndexOfFunctionPipe.javaIndexOfFunctionProcessor.javaLength.javaLengthFunctionPipe.javaLengthFunctionProcessor.javaStartsWith.javaStringContainsFunctionPipe.javaSubstring.javaSubstringFunctionPipe.javaSubstringFunctionProcessor.javaToStringFunctionPipe.javaToStringFunctionProcessor.java
planner
test/java/org/elasticsearch/xpack/eql/expression/function/scalar
math
string
BetweenFunctionPipeTests.javaCIDRMatchFunctionPipeTests.javaCIDRMatchFunctionProcessorTests.javaConcatFunctionPipeTests.javaEndsWithFunctionPipeTests.javaEndsWithFunctionProcessorTests.javaIndexOfFunctionPipeTests.javaIndexOfFunctionProcessorTests.javaLengthFunctionPipeTests.javaLengthFunctionProcessorTests.javaStartsWithFunctionProcessorTests.javaStringContainsFunctionPipeTests.javaSubstringFunctionPipeTests.javaSubstringFunctionProcessorTests.javaToStringFunctionPipeTests.javaToStringFunctionProcessorTests.java
ql/src
main/java/org/elasticsearch/xpack/ql
expression/function/scalar/string
planner
test/java/org/elasticsearch/xpack/ql
expression/function/scalar
tree
sql/src
main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string
Insert.javaInsertFunctionPipe.javaInsertFunctionProcessor.javaLocate.javaLocateFunctionPipe.javaLocateFunctionProcessor.javaReplace.javaReplaceFunctionPipe.javaReplaceFunctionProcessor.javaSubstring.javaSubstringFunctionPipe.javaSubstringFunctionProcessor.java
test/java/org/elasticsearch/xpack/sql/expression/function/scalar/string
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.math;
|
||||
|
||||
import org.elasticsearch.xpack.ql.execution.search.QlSourceBuilder;
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.NodeInfo;
|
||||
@ -12,6 +13,7 @@ import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ToNumberFunctionPipe extends Pipe {
|
||||
|
||||
@ -21,7 +23,6 @@ public class ToNumberFunctionPipe extends Pipe {
|
||||
super(source, expression, Arrays.asList(value, base));
|
||||
this.value = value;
|
||||
this.base = base;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -29,7 +30,37 @@ public class ToNumberFunctionPipe extends Pipe {
|
||||
if (newChildren.size() != 2) {
|
||||
throw new IllegalArgumentException("expected [2] children but received [" + newChildren.size() + "]");
|
||||
}
|
||||
return new ToNumberFunctionPipe(source(), expression(), newChildren.get(0), newChildren.get(1));
|
||||
return replaceChildren(newChildren.get(0), newChildren.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newValue = value.resolveAttributes(resolver);
|
||||
Pipe newBase = base.resolveAttributes(resolver);
|
||||
if (newValue == value && newBase == base) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newValue, newBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return value.supportedByAggsOnlyQuery() && base.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return value.resolved() && base.resolved();
|
||||
}
|
||||
|
||||
protected ToNumberFunctionPipe replaceChildren(Pipe newValue, Pipe newBase) {
|
||||
return new ToNumberFunctionPipe(source(), expression(), newValue, newBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
value.collectFields(sourceBuilder);
|
||||
base.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,4 +72,32 @@ public class ToNumberFunctionPipe extends Pipe {
|
||||
public ToNumberFunctionProcessor asProcessor() {
|
||||
return new ToNumberFunctionProcessor(value.asProcessor(), base.asProcessor());
|
||||
}
|
||||
|
||||
|
||||
public Pipe value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Pipe base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(value(), base());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ToNumberFunctionPipe other = (ToNumberFunctionPipe) obj;
|
||||
return Objects.equals(value(), other.value()) && Objects.equals(base(), other.base());
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,11 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class Between extends ScalarFunction implements OptionalArgument {
|
||||
|
||||
private final Expression source, left, right, greedy, caseSensitive;
|
||||
private final Expression input, left, right, greedy, caseSensitive;
|
||||
|
||||
public Between(Source source, Expression src, Expression left, Expression right, Expression greedy, Expression caseSensitive) {
|
||||
super(source, Arrays.asList(src, left, right, toDefault(greedy), toDefault(caseSensitive)));
|
||||
this.source = src;
|
||||
public Between(Source source, Expression input, Expression left, Expression right, Expression greedy, Expression caseSensitive) {
|
||||
super(source, Arrays.asList(input, left, right, toDefault(greedy), toDefault(caseSensitive)));
|
||||
this.input = input;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.greedy = arguments().get(3);
|
||||
@ -58,7 +58,7 @@ public class Between extends ScalarFunction implements OptionalArgument {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution resolution = isStringAndExact(source, sourceText(), Expressions.ParamOrdinal.FIRST);
|
||||
TypeResolution resolution = isStringAndExact(input, sourceText(), Expressions.ParamOrdinal.FIRST);
|
||||
if (resolution.unresolved()) {
|
||||
return resolution;
|
||||
}
|
||||
@ -83,48 +83,48 @@ public class Between extends ScalarFunction implements OptionalArgument {
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new BetweenFunctionPipe(source(), this, Expressions.pipe(source),
|
||||
return new BetweenFunctionPipe(source(), this, Expressions.pipe(input),
|
||||
Expressions.pipe(left), Expressions.pipe(right),
|
||||
Expressions.pipe(greedy), Expressions.pipe(caseSensitive));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable() && left.foldable() && right.foldable() && greedy.foldable() && caseSensitive.foldable();
|
||||
return input.foldable() && left.foldable() && right.foldable() && greedy.foldable() && caseSensitive.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), left.fold(), right.fold(), greedy.fold(), caseSensitive.fold());
|
||||
return doProcess(input.fold(), left.fold(), right.fold(), greedy.fold(), caseSensitive.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Between::new, source, left, right, greedy, caseSensitive);
|
||||
return NodeInfo.create(this, Between::new, input, left, right, greedy, caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate leftScript = asScript(left);
|
||||
ScriptTemplate rightScript = asScript(right);
|
||||
ScriptTemplate greedyScript = asScript(greedy);
|
||||
ScriptTemplate caseSensitiveScript = asScript(caseSensitive);
|
||||
|
||||
return asScriptFrom(sourceScript, leftScript, rightScript, greedyScript, caseSensitiveScript);
|
||||
return asScriptFrom(inputScript, leftScript, rightScript, greedyScript, caseSensitiveScript);
|
||||
}
|
||||
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate leftScript,
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate leftScript,
|
||||
ScriptTemplate rightScript, ScriptTemplate greedyScript, ScriptTemplate caseSensitiveScript) {
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{eql}.%s(%s,%s,%s,%s,%s)"),
|
||||
"between",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
leftScript.template(),
|
||||
rightScript.template(),
|
||||
greedyScript.template(),
|
||||
caseSensitiveScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params())
|
||||
.script(inputScript.params())
|
||||
.script(leftScript.params())
|
||||
.script(rightScript.params())
|
||||
.script(greedyScript.params())
|
||||
|
@ -17,11 +17,11 @@ import java.util.Objects;
|
||||
|
||||
public class BetweenFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, left, right, greedy, caseSensitive;
|
||||
private final Pipe input, left, right, greedy, caseSensitive;
|
||||
|
||||
public BetweenFunctionPipe(Source source, Expression expression, Pipe src, Pipe left, Pipe right, Pipe greedy, Pipe caseSensitive) {
|
||||
super(source, expression, Arrays.asList(src, left, right, greedy, caseSensitive));
|
||||
this.source = src;
|
||||
public BetweenFunctionPipe(Source source, Expression expression, Pipe input, Pipe left, Pipe right, Pipe greedy, Pipe caseSensitive) {
|
||||
super(source, expression, Arrays.asList(input, left, right, greedy, caseSensitive));
|
||||
this.input = input;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.greedy = greedy;
|
||||
@ -38,35 +38,35 @@ public class BetweenFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newLeft = left.resolveAttributes(resolver);
|
||||
Pipe newRight = right.resolveAttributes(resolver);
|
||||
Pipe newGreedy = greedy.resolveAttributes(resolver);
|
||||
Pipe newCaseSensitive = caseSensitive.resolveAttributes(resolver);
|
||||
if (newSource == source && newLeft == left && newRight == right && newGreedy == greedy && newCaseSensitive == caseSensitive) {
|
||||
if (newInput == input && newLeft == left && newRight == right && newGreedy == greedy && newCaseSensitive == caseSensitive) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newLeft, newRight, newGreedy, newCaseSensitive);
|
||||
return replaceChildren(newInput, newLeft, newRight, newGreedy, newCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && left.supportedByAggsOnlyQuery() && right.supportedByAggsOnlyQuery()
|
||||
return input.supportedByAggsOnlyQuery() && left.supportedByAggsOnlyQuery() && right.supportedByAggsOnlyQuery()
|
||||
&& greedy.supportedByAggsOnlyQuery() && caseSensitive.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && left.resolved() && right.resolved() && greedy.resolved() && caseSensitive.resolved();
|
||||
return input.resolved() && left.resolved() && right.resolved() && greedy.resolved() && caseSensitive.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newLeft, Pipe newRight, Pipe newGreedy, Pipe newCaseSensitive) {
|
||||
return new BetweenFunctionPipe(source(), expression(), newSource, newLeft, newRight, newGreedy, newCaseSensitive);
|
||||
protected Pipe replaceChildren(Pipe newInput, Pipe newLeft, Pipe newRight, Pipe newGreedy, Pipe newCaseSensitive) {
|
||||
return new BetweenFunctionPipe(source(), expression(), newInput, newLeft, newRight, newGreedy, newCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
left.collectFields(sourceBuilder);
|
||||
right.collectFields(sourceBuilder);
|
||||
greedy.collectFields(sourceBuilder);
|
||||
@ -75,17 +75,17 @@ public class BetweenFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
protected NodeInfo<BetweenFunctionPipe> info() {
|
||||
return NodeInfo.create(this, BetweenFunctionPipe::new, expression(), source, left, right, greedy, caseSensitive);
|
||||
return NodeInfo.create(this, BetweenFunctionPipe::new, expression(), input, left, right, greedy, caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetweenFunctionProcessor asProcessor() {
|
||||
return new BetweenFunctionProcessor(source.asProcessor(), left.asProcessor(), right.asProcessor(),
|
||||
return new BetweenFunctionProcessor(input.asProcessor(), left.asProcessor(), right.asProcessor(),
|
||||
greedy.asProcessor(), caseSensitive.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe left() {
|
||||
@ -106,7 +106,7 @@ public class BetweenFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), left(), right(), greedy(), caseSensitive());
|
||||
return Objects.hash(input(), left(), right(), greedy(), caseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,7 +120,7 @@ public class BetweenFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
BetweenFunctionPipe other = (BetweenFunctionPipe) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(left(), other.left())
|
||||
&& Objects.equals(right(), other.right())
|
||||
&& Objects.equals(greedy(), other.greedy())
|
||||
|
@ -17,10 +17,10 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "sbtw";
|
||||
|
||||
private final Processor source, left, right, greedy, caseSensitive;
|
||||
private final Processor input, left, right, greedy, caseSensitive;
|
||||
|
||||
public BetweenFunctionProcessor(Processor source, Processor left, Processor right, Processor greedy, Processor caseSensitive) {
|
||||
this.source = source;
|
||||
public BetweenFunctionProcessor(Processor input, Processor left, Processor right, Processor greedy, Processor caseSensitive) {
|
||||
this.input = input;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.greedy = greedy;
|
||||
@ -28,7 +28,7 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
public BetweenFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
left = in.readNamedWriteable(Processor.class);
|
||||
right = in.readNamedWriteable(Processor.class);
|
||||
greedy = in.readNamedWriteable(Processor.class);
|
||||
@ -37,7 +37,7 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(left);
|
||||
out.writeNamedWriteable(right);
|
||||
out.writeNamedWriteable(greedy);
|
||||
@ -50,24 +50,23 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input), left.process(input), right.process(input),
|
||||
greedy.process(input), caseSensitive.process(input));
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o), left.process(o), right.process(o), greedy.process(o), caseSensitive.process(o));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object left, Object right, Object greedy, Object caseSensitive) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object left, Object right, Object greedy, Object caseSensitive) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Check.isString(source);
|
||||
Check.isString(input);
|
||||
Check.isString(left);
|
||||
Check.isString(right);
|
||||
|
||||
Check.isBoolean(greedy);
|
||||
Check.isBoolean(caseSensitive);
|
||||
|
||||
String str = source.toString();
|
||||
String str = input.toString();
|
||||
String strRight = right.toString();
|
||||
String strLeft = left.toString();
|
||||
boolean bGreedy = ((Boolean) greedy).booleanValue();
|
||||
@ -75,8 +74,8 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
return StringUtils.between(str, strLeft, strRight, bGreedy, bCaseSensitive);
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Processor left() {
|
||||
@ -97,7 +96,7 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), left(), right(), greedy(), caseSensitive());
|
||||
return Objects.hash(input(), left(), right(), greedy(), caseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -111,7 +110,7 @@ public class BetweenFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
BetweenFunctionProcessor other = (BetweenFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(left(), other.left())
|
||||
&& Objects.equals(right(), other.right())
|
||||
&& Objects.equals(greedy(), other.greedy())
|
||||
|
@ -40,17 +40,17 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class CIDRMatch extends ScalarFunction {
|
||||
|
||||
private final Expression field;
|
||||
private final Expression input;
|
||||
private final List<Expression> addresses;
|
||||
|
||||
public CIDRMatch(Source source, Expression field, List<Expression> addresses) {
|
||||
super(source, CollectionUtils.combine(singletonList(field), addresses == null ? emptyList() : addresses));
|
||||
this.field = field;
|
||||
public CIDRMatch(Source source, Expression input, List<Expression> addresses) {
|
||||
super(source, CollectionUtils.combine(singletonList(input), addresses == null ? emptyList() : addresses));
|
||||
this.input = input;
|
||||
this.addresses = addresses == null ? emptyList() : addresses;
|
||||
}
|
||||
|
||||
public Expression field() {
|
||||
return field;
|
||||
public Expression input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public List<Expression> addresses() {
|
||||
@ -63,15 +63,13 @@ public class CIDRMatch extends ScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution resolution = isIPAndExact(field, sourceText(), Expressions.ParamOrdinal.FIRST);
|
||||
TypeResolution resolution = isIPAndExact(input, sourceText(), Expressions.ParamOrdinal.FIRST);
|
||||
if (resolution.unresolved()) {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
for (Expression addr : addresses) {
|
||||
|
||||
resolution = isFoldable(addr, sourceText(), ParamOrdinal.fromIndex(index));
|
||||
if (resolution.unresolved()) {
|
||||
break;
|
||||
@ -90,31 +88,27 @@ public class CIDRMatch extends ScalarFunction {
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
ArrayList<Pipe> arr = new ArrayList<>(addresses.size());
|
||||
for (Expression address : addresses) {
|
||||
arr.add(Expressions.pipe(address));
|
||||
}
|
||||
return new CIDRMatchFunctionPipe(source(), this, Expressions.pipe(field), arr);
|
||||
return new CIDRMatchFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(addresses));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return field.foldable() && Expressions.foldable(addresses);
|
||||
return input.foldable() && Expressions.foldable(addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(field.fold(), Expressions.fold(addresses));
|
||||
return doProcess(input.fold(), Expressions.fold(addresses));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, CIDRMatch::new, field, addresses);
|
||||
return NodeInfo.create(this, CIDRMatch::new, input, addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate leftScript = asScript(field);
|
||||
ScriptTemplate leftScript = asScript(input);
|
||||
|
||||
List<Object> values = new ArrayList<>(new LinkedHashSet<>(Expressions.fold(addresses)));
|
||||
return new ScriptTemplate(
|
||||
|
@ -20,12 +20,12 @@ import java.util.Objects;
|
||||
|
||||
public class CIDRMatchFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source;
|
||||
private final Pipe input;
|
||||
private final List<Pipe> addresses;
|
||||
|
||||
public CIDRMatchFunctionPipe(Source source, Expression expression, Pipe src, List<Pipe> addresses) {
|
||||
super(source, expression, CollectionUtils.combine(Collections.singletonList(src), addresses));
|
||||
this.source = src;
|
||||
public CIDRMatchFunctionPipe(Source source, Expression expression, Pipe input, List<Pipe> addresses) {
|
||||
super(source, expression, CollectionUtils.combine(Collections.singletonList(input), addresses));
|
||||
this.input = input;
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
@ -39,8 +39,8 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
boolean same = (newSource == source);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
boolean same = (newInput == input);
|
||||
|
||||
ArrayList<Pipe> newAddresses = new ArrayList<Pipe>(addresses.size());
|
||||
for (Pipe address : addresses) {
|
||||
@ -48,15 +48,12 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
newAddresses.add(newAddress);
|
||||
same = same && (address == newAddress);
|
||||
}
|
||||
if (same) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newAddresses);
|
||||
return same ? this : replaceChildren(newInput, newAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
if (source.supportedByAggsOnlyQuery() == false) {
|
||||
if (input.supportedByAggsOnlyQuery() == false) {
|
||||
return false;
|
||||
}
|
||||
for (Pipe address : addresses) {
|
||||
@ -69,7 +66,7 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
if (source.resolved() == false) {
|
||||
if (input.resolved() == false) {
|
||||
return false;
|
||||
}
|
||||
for (Pipe address : addresses) {
|
||||
@ -80,13 +77,13 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, List<Pipe> newAddresses) {
|
||||
return new CIDRMatchFunctionPipe(source(), expression(), newSource, newAddresses);
|
||||
protected CIDRMatchFunctionPipe replaceChildren(Pipe newInput, List<Pipe> newAddresses) {
|
||||
return new CIDRMatchFunctionPipe(source(), expression(), newInput, newAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
for (Pipe address : addresses) {
|
||||
address.collectFields(sourceBuilder);
|
||||
}
|
||||
@ -94,7 +91,7 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
protected NodeInfo<CIDRMatchFunctionPipe> info() {
|
||||
return NodeInfo.create(this, CIDRMatchFunctionPipe::new, expression(), source, addresses);
|
||||
return NodeInfo.create(this, CIDRMatchFunctionPipe::new, expression(), input, addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,11 +100,11 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
for (Pipe address: addresses) {
|
||||
processors.add(address.asProcessor());
|
||||
}
|
||||
return new CIDRMatchFunctionProcessor(source.asProcessor(), processors);
|
||||
return new CIDRMatchFunctionProcessor(input.asProcessor(), processors);
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public List<Pipe> addresses() {
|
||||
@ -116,7 +113,7 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), addresses());
|
||||
return Objects.hash(input(), addresses());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -130,7 +127,6 @@ public class CIDRMatchFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
CIDRMatchFunctionPipe other = (CIDRMatchFunctionPipe) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
&& Objects.equals(addresses(), other.addresses());
|
||||
return Objects.equals(input(), other.input()) && Objects.equals(addresses(), other.addresses());
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class ConcatFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Pipe replaceChildren(List<Pipe> newChildren) {
|
||||
public final ConcatFunctionPipe replaceChildren(List<Pipe> newChildren) {
|
||||
return new ConcatFunctionPipe(source(), expression(), newChildren);
|
||||
}
|
||||
|
||||
@ -85,6 +85,10 @@ public class ConcatFunctionPipe extends Pipe {
|
||||
return new ConcatFunctionProcessor(processors);
|
||||
}
|
||||
|
||||
List<Pipe> values() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(values);
|
||||
@ -100,6 +104,6 @@ public class ConcatFunctionPipe extends Pipe {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(values, ((ConcatFunctionPipe) obj).values);
|
||||
return Objects.equals(values(), ((ConcatFunctionPipe) obj).values());
|
||||
}
|
||||
}
|
||||
|
@ -36,12 +36,12 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class EndsWith extends CaseSensitiveScalarFunction {
|
||||
|
||||
private final Expression source;
|
||||
private final Expression input;
|
||||
private final Expression pattern;
|
||||
|
||||
public EndsWith(Source source, Expression src, Expression pattern, Configuration configuration) {
|
||||
super(source, Arrays.asList(src, pattern), configuration);
|
||||
this.source = src;
|
||||
public EndsWith(Source source, Expression input, Expression pattern, Configuration configuration) {
|
||||
super(source, Arrays.asList(input, pattern), configuration);
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ public class EndsWith extends CaseSensitiveScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -66,43 +66,43 @@ public class EndsWith extends CaseSensitiveScalarFunction {
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new EndsWithFunctionPipe(source(), this, Expressions.pipe(source), Expressions.pipe(pattern), isCaseSensitive());
|
||||
return new EndsWithFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(pattern), isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable() && pattern.foldable();
|
||||
return input.foldable() && pattern.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), pattern.fold(), isCaseSensitive());
|
||||
return doProcess(input.fold(), pattern.fold(), isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, EndsWith::new, source, pattern, configuration());
|
||||
return NodeInfo.create(this, EndsWith::new, input, pattern, configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate patternScript = asScript(pattern);
|
||||
|
||||
return asScriptFrom(sourceScript, patternScript);
|
||||
return asScriptFrom(inputScript, patternScript);
|
||||
}
|
||||
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate patternScript) {
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate patternScript) {
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{eql}.%s(%s,%s,%s)"),
|
||||
"endsWith",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
patternScript.template(),
|
||||
"{}"),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params())
|
||||
.script(patternScript.params())
|
||||
.variable(isCaseSensitive())
|
||||
.build(), dataType());
|
||||
.script(inputScript.params())
|
||||
.script(patternScript.params())
|
||||
.variable(isCaseSensitive())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,13 +17,12 @@ import java.util.Objects;
|
||||
|
||||
public class EndsWithFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source;
|
||||
private final Pipe pattern;
|
||||
private final Pipe input, pattern;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public EndsWithFunctionPipe(Source source, Expression expression, Pipe src, Pipe pattern, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(src, pattern));
|
||||
this.source = src;
|
||||
public EndsWithFunctionPipe(Source source, Expression expression, Pipe input, Pipe pattern, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(input, pattern));
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
@ -38,55 +37,59 @@ public class EndsWithFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newPattern = pattern.resolveAttributes(resolver);
|
||||
if (newSource == source && newPattern == pattern) {
|
||||
if (newInput == input && newPattern == pattern) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newPattern);
|
||||
return replaceChildren(newInput, newPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && pattern.resolved();
|
||||
return input.resolved() && pattern.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newPattern) {
|
||||
return new EndsWithFunctionPipe(source(), expression(), newSource, newPattern, isCaseSensitive);
|
||||
protected EndsWithFunctionPipe replaceChildren(Pipe newInput, Pipe newPattern) {
|
||||
return new EndsWithFunctionPipe(source(), expression(), newInput, newPattern, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
pattern.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<EndsWithFunctionPipe> info() {
|
||||
return NodeInfo.create(this, EndsWithFunctionPipe::new, expression(), source, pattern, isCaseSensitive);
|
||||
return NodeInfo.create(this, EndsWithFunctionPipe::new, expression(), input, pattern, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EndsWithFunctionProcessor asProcessor() {
|
||||
return new EndsWithFunctionProcessor(source.asProcessor(), pattern.asProcessor(), isCaseSensitive);
|
||||
return new EndsWithFunctionProcessor(input.asProcessor(), pattern.asProcessor(), isCaseSensitive);
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe pattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
protected boolean isCaseSensitive() {
|
||||
return isCaseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, pattern, isCaseSensitive);
|
||||
return Objects.hash(input, pattern, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,8 +103,8 @@ public class EndsWithFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
EndsWithFunctionPipe other = (EndsWithFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source)
|
||||
&& Objects.equals(pattern, other.pattern)
|
||||
&& Objects.equals(isCaseSensitive, other.isCaseSensitive);
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(pattern(), other.pattern())
|
||||
&& Objects.equals(isCaseSensitive(), other.isCaseSensitive());
|
||||
}
|
||||
}
|
||||
|
@ -18,40 +18,40 @@ public class EndsWithFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "senw";
|
||||
|
||||
private final Processor source;
|
||||
private final Processor input;
|
||||
private final Processor pattern;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public EndsWithFunctionProcessor(Processor source, Processor pattern, boolean isCaseSensitive) {
|
||||
this.source = source;
|
||||
public EndsWithFunctionProcessor(Processor input, Processor pattern, boolean isCaseSensitive) {
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
|
||||
public EndsWithFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
pattern = in.readNamedWriteable(Processor.class);
|
||||
isCaseSensitive = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(pattern);
|
||||
out.writeBoolean(isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input), pattern.process(input), isCaseSensitive());
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o), pattern.process(o), isCaseSensitive());
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object pattern, boolean isCaseSensitive) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object pattern, boolean isCaseSensitive) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (source instanceof String == false && source instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (input instanceof String == false && input instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (pattern == null) {
|
||||
return null;
|
||||
@ -61,14 +61,14 @@ public class EndsWithFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
if (isCaseSensitive) {
|
||||
return source.toString().endsWith(pattern.toString());
|
||||
return input.toString().endsWith(pattern.toString());
|
||||
} else {
|
||||
return source.toString().toLowerCase(Locale.ROOT).endsWith(pattern.toString().toLowerCase(Locale.ROOT));
|
||||
return input.toString().toLowerCase(Locale.ROOT).endsWith(pattern.toString().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
protected Processor pattern() {
|
||||
@ -90,14 +90,14 @@ public class EndsWithFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
EndsWithFunctionProcessor other = (EndsWithFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(pattern(), other.pattern())
|
||||
&& Objects.equals(isCaseSensitive(), other.isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), pattern(), isCaseSensitive());
|
||||
return Objects.hash(input(), pattern(), isCaseSensitive());
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,11 +39,11 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class IndexOf extends CaseSensitiveScalarFunction implements OptionalArgument {
|
||||
|
||||
private final Expression source, substring, start;
|
||||
private final Expression input, substring, start;
|
||||
|
||||
public IndexOf(Source source, Expression src, Expression substring, Expression start, Configuration configuration) {
|
||||
super(source, Arrays.asList(src, substring, start != null ? start : new Literal(source, null, DataTypes.NULL)), configuration);
|
||||
this.source = src;
|
||||
public IndexOf(Source source, Expression input, Expression substring, Expression start, Configuration configuration) {
|
||||
super(source, Arrays.asList(input, substring, start != null ? start : new Literal(source, null, DataTypes.NULL)), configuration);
|
||||
this.input = input;
|
||||
this.substring = substring;
|
||||
this.start = arguments().get(2);
|
||||
}
|
||||
@ -59,7 +59,7 @@ public class IndexOf extends CaseSensitiveScalarFunction implements OptionalArgu
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution resolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution resolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (resolution.unresolved()) {
|
||||
return resolution;
|
||||
}
|
||||
@ -74,47 +74,47 @@ public class IndexOf extends CaseSensitiveScalarFunction implements OptionalArgu
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new IndexOfFunctionPipe(source(), this, Expressions.pipe(source), Expressions.pipe(substring),
|
||||
Expressions.pipe(start), isCaseSensitive());
|
||||
return new IndexOfFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(substring), Expressions.pipe(start),
|
||||
isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable() && substring.foldable() && start.foldable();
|
||||
return input.foldable() && substring.foldable() && start.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), substring.fold(), start.fold(), isCaseSensitive());
|
||||
return doProcess(input.fold(), substring.fold(), start.fold(), isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, IndexOf::new, source, substring, start, configuration());
|
||||
return NodeInfo.create(this, IndexOf::new, input, substring, start, configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate substringScript = asScript(substring);
|
||||
ScriptTemplate startScript = asScript(start);
|
||||
|
||||
return asScriptFrom(sourceScript, substringScript, startScript);
|
||||
return asScriptFrom(inputScript, substringScript, startScript);
|
||||
}
|
||||
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate substringScript, ScriptTemplate startScript) {
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate substringScript, ScriptTemplate startScript) {
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{eql}.%s(%s,%s,%s,%s)"),
|
||||
"indexOf",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
substringScript.template(),
|
||||
startScript.template(),
|
||||
"{}"),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params())
|
||||
.script(substringScript.params())
|
||||
.script(startScript.params())
|
||||
.variable(isCaseSensitive())
|
||||
.build(), dataType());
|
||||
.script(inputScript.params())
|
||||
.script(substringScript.params())
|
||||
.script(startScript.params())
|
||||
.variable(isCaseSensitive())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,12 +17,12 @@ import java.util.Objects;
|
||||
|
||||
public class IndexOfFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, substring, start;
|
||||
private final Pipe input, substring, start;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public IndexOfFunctionPipe(Source source, Expression expression, Pipe src, Pipe substring, Pipe start, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(src, substring, start));
|
||||
this.source = src;
|
||||
public IndexOfFunctionPipe(Source source, Expression expression, Pipe input, Pipe substring, Pipe start, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(input, substring, start));
|
||||
this.input = input;
|
||||
this.substring = substring;
|
||||
this.start = start;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
@ -38,48 +38,48 @@ public class IndexOfFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newSubstring = substring.resolveAttributes(resolver);
|
||||
Pipe newStart = start.resolveAttributes(resolver);
|
||||
if (newSource == source && newSubstring == substring && newStart == start) {
|
||||
if (newInput == input && newSubstring == substring && newStart == start) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newSubstring, newStart);
|
||||
return replaceChildren(newInput, newSubstring, newStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && substring.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && substring.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && substring.resolved() && start.resolved();
|
||||
return input.resolved() && substring.resolved() && start.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newSubstring, Pipe newStart) {
|
||||
return new IndexOfFunctionPipe(source(), expression(), newSource, newSubstring, newStart, isCaseSensitive);
|
||||
protected IndexOfFunctionPipe replaceChildren(Pipe newInput, Pipe newSubstring, Pipe newStart) {
|
||||
return new IndexOfFunctionPipe(source(), expression(), newInput, newSubstring, newStart, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
substring.collectFields(sourceBuilder);
|
||||
start.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<IndexOfFunctionPipe> info() {
|
||||
return NodeInfo.create(this, IndexOfFunctionPipe::new, expression(), source, substring, start, isCaseSensitive);
|
||||
return NodeInfo.create(this, IndexOfFunctionPipe::new, expression(), input, substring, start, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexOfFunctionProcessor asProcessor() {
|
||||
return new IndexOfFunctionProcessor(source.asProcessor(), substring.asProcessor(), start.asProcessor(), isCaseSensitive);
|
||||
return new IndexOfFunctionProcessor(input.asProcessor(), substring.asProcessor(), start.asProcessor(), isCaseSensitive);
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe substring() {
|
||||
@ -90,9 +90,13 @@ public class IndexOfFunctionPipe extends Pipe {
|
||||
return start;
|
||||
}
|
||||
|
||||
protected boolean isCaseSensitive() {
|
||||
return isCaseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, substring, start, isCaseSensitive);
|
||||
return Objects.hash(input, substring, start, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,9 +110,9 @@ public class IndexOfFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
IndexOfFunctionPipe other = (IndexOfFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source)
|
||||
&& Objects.equals(substring, other.substring)
|
||||
&& Objects.equals(start, other.start)
|
||||
&& Objects.equals(isCaseSensitive, other.isCaseSensitive);
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(substring(), other.substring())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(isCaseSensitive(), other.isCaseSensitive());
|
||||
}
|
||||
}
|
||||
|
@ -18,20 +18,20 @@ public class IndexOfFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "siof";
|
||||
|
||||
private final Processor source;
|
||||
private final Processor input;
|
||||
private final Processor substring;
|
||||
private final Processor start;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public IndexOfFunctionProcessor(Processor source, Processor substring, Processor start, boolean isCaseSensitive) {
|
||||
this.source = source;
|
||||
public IndexOfFunctionProcessor(Processor input, Processor substring, Processor start, boolean isCaseSensitive) {
|
||||
this.input = input;
|
||||
this.substring = substring;
|
||||
this.start = start;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
|
||||
public IndexOfFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
substring = in.readNamedWriteable(Processor.class);
|
||||
start = in.readNamedWriteable(Processor.class);
|
||||
isCaseSensitive = in.readBoolean();
|
||||
@ -39,23 +39,23 @@ public class IndexOfFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(substring);
|
||||
out.writeNamedWriteable(start);
|
||||
out.writeBoolean(isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input), substring.process(input), start.process(input), isCaseSensitive());
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o), substring.process(o), start.process(o), isCaseSensitive());
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object substring, Object start, boolean isCaseSensitive) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object substring, Object start, boolean isCaseSensitive) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (source instanceof String == false && source instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (input instanceof String == false && input instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (substring == null) {
|
||||
return null;
|
||||
@ -72,16 +72,16 @@ public class IndexOfFunctionProcessor implements Processor {
|
||||
int result;
|
||||
|
||||
if (isCaseSensitive) {
|
||||
result = source.toString().indexOf(substring.toString(), startIndex);
|
||||
result = input.toString().indexOf(substring.toString(), startIndex);
|
||||
} else {
|
||||
result = source.toString().toLowerCase(Locale.ROOT).indexOf(substring.toString().toLowerCase(Locale.ROOT), startIndex);
|
||||
result = input.toString().toLowerCase(Locale.ROOT).indexOf(substring.toString().toLowerCase(Locale.ROOT), startIndex);
|
||||
}
|
||||
|
||||
return result < 0 ? null : result;
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
protected Processor substring() {
|
||||
@ -107,7 +107,7 @@ public class IndexOfFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
IndexOfFunctionProcessor other = (IndexOfFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(substring(), other.substring())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(isCaseSensitive(), other.isCaseSensitive());
|
||||
@ -115,7 +115,7 @@ public class IndexOfFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), substring(), start(), isCaseSensitive());
|
||||
return Objects.hash(input(), substring(), start(), isCaseSensitive());
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,11 +34,11 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class Length extends ScalarFunction {
|
||||
|
||||
private final Expression source;
|
||||
private final Expression input;
|
||||
|
||||
public Length(Source source, Expression src) {
|
||||
super(source, Arrays.asList(src));
|
||||
this.source = src;
|
||||
public Length(Source source, Expression input) {
|
||||
super(source, Arrays.asList(input));
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -47,38 +47,38 @@ public class Length extends ScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
return isStringAndExact(source, sourceText(), ParamOrdinal.DEFAULT);
|
||||
return isStringAndExact(input, sourceText(), ParamOrdinal.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new LengthFunctionPipe(source(), this, Expressions.pipe(source));
|
||||
return new LengthFunctionPipe(source(), this, Expressions.pipe(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable();
|
||||
return input.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold());
|
||||
return doProcess(input.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Length::new, source);
|
||||
return NodeInfo.create(this, Length::new, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{eql}.%s(%s)"),
|
||||
"length",
|
||||
sourceScript.template()),
|
||||
inputScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params())
|
||||
.script(inputScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ import java.util.Objects;
|
||||
|
||||
public class LengthFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source;
|
||||
private final Pipe input;
|
||||
|
||||
public LengthFunctionPipe(Source source, Expression expression, Pipe src) {
|
||||
super(source, expression, Arrays.asList(src));
|
||||
this.source = src;
|
||||
public LengthFunctionPipe(Source source, Expression expression, Pipe input) {
|
||||
super(source, expression, Arrays.asList(input));
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -34,49 +34,46 @@ public class LengthFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
if (newSource == source) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
return newInput == input ? this : replaceChildren(newInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved();
|
||||
return input.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource) {
|
||||
return new LengthFunctionPipe(source(), expression(), newSource);
|
||||
protected LengthFunctionPipe replaceChildren(Pipe newInput) {
|
||||
return new LengthFunctionPipe(source(), expression(), newInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<LengthFunctionPipe> info() {
|
||||
return NodeInfo.create(this, LengthFunctionPipe::new, expression(), source);
|
||||
return NodeInfo.create(this, LengthFunctionPipe::new, expression(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LengthFunctionProcessor asProcessor() {
|
||||
return new LengthFunctionProcessor(source.asProcessor());
|
||||
return new LengthFunctionProcessor(input.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source);
|
||||
return Objects.hash(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,6 +86,6 @@ public class LengthFunctionPipe extends Pipe {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(source, ((LengthFunctionPipe) obj).source);
|
||||
return Objects.equals(input(), ((LengthFunctionPipe) obj).input());
|
||||
}
|
||||
}
|
||||
|
@ -17,39 +17,39 @@ public class LengthFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "slen";
|
||||
|
||||
private final Processor source;
|
||||
private final Processor input;
|
||||
|
||||
public LengthFunctionProcessor(Processor source) {
|
||||
this.source = source;
|
||||
public LengthFunctionProcessor(Processor input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public LengthFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input));
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (source instanceof String == false && source instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (input instanceof String == false && input instanceof Character == false) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
|
||||
return source.toString().length();
|
||||
return input.toString().length();
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -62,12 +62,12 @@ public class LengthFunctionProcessor implements Processor {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(source(), ((LengthFunctionProcessor) obj).source());
|
||||
return Objects.equals(input(), ((LengthFunctionProcessor) obj).input());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source());
|
||||
return Objects.hash(input());
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,8 +13,8 @@ import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
public class StartsWith extends org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWith {
|
||||
|
||||
public StartsWith(Source source, Expression field, Expression pattern, Configuration configuration) {
|
||||
super(source, field, pattern, configuration);
|
||||
public StartsWith(Source source, Expression input, Expression pattern, Configuration configuration) {
|
||||
super(source, input, pattern, configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,7 +54,7 @@ public class StringContainsFunctionPipe extends Pipe {
|
||||
return string.resolved() && substring.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe string, Pipe substring) {
|
||||
protected StringContainsFunctionPipe replaceChildren(Pipe string, Pipe substring) {
|
||||
return new StringContainsFunctionPipe(source(), expression(), string, substring);
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ public class StringContainsFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), string(), substring());
|
||||
return Objects.hash(string(), substring());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,8 +99,7 @@ public class StringContainsFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
StringContainsFunctionPipe other = (StringContainsFunctionPipe) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
&& Objects.equals(string(), other.string())
|
||||
return Objects.equals(string(), other.string())
|
||||
&& Objects.equals(substring(), other.substring());
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,11 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class Substring extends ScalarFunction implements OptionalArgument {
|
||||
|
||||
private final Expression source, start, end;
|
||||
private final Expression input, start, end;
|
||||
|
||||
public Substring(Source source, Expression src, Expression start, Expression end) {
|
||||
super(source, Arrays.asList(src, start, end != null ? end : new Literal(source, null, DataTypes.NULL)));
|
||||
this.source = src;
|
||||
public Substring(Source source, Expression input, Expression start, Expression end) {
|
||||
super(source, Arrays.asList(input, start, end != null ? end : new Literal(source, null, DataTypes.NULL)));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.end = arguments().get(2);
|
||||
}
|
||||
@ -52,7 +52,7 @@ public class Substring extends ScalarFunction implements OptionalArgument {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -67,41 +67,41 @@ public class Substring extends ScalarFunction implements OptionalArgument {
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new SubstringFunctionPipe(source(), this, Expressions.pipe(source), Expressions.pipe(start), Expressions.pipe(end));
|
||||
return new SubstringFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(start), Expressions.pipe(end));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable() && start.foldable() && end.foldable();
|
||||
return input.foldable() && start.foldable() && end.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), start.fold(), end.fold());
|
||||
return doProcess(input.fold(), start.fold(), end.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Substring::new, source, start, end);
|
||||
return NodeInfo.create(this, Substring::new, input, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate startScript = asScript(start);
|
||||
ScriptTemplate endScript = asScript(end);
|
||||
|
||||
return asScriptFrom(sourceScript, startScript, endScript);
|
||||
return asScriptFrom(inputScript, startScript, endScript);
|
||||
}
|
||||
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate startScript, ScriptTemplate endScript) {
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate startScript, ScriptTemplate endScript) {
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{eql}.%s(%s,%s,%s)"),
|
||||
"substring",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
startScript.template(),
|
||||
endScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params())
|
||||
.script(inputScript.params())
|
||||
.script(startScript.params())
|
||||
.script(endScript.params())
|
||||
.build(), dataType());
|
||||
|
@ -17,11 +17,11 @@ import java.util.Objects;
|
||||
|
||||
public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, start, end;
|
||||
private final Pipe input, start, end;
|
||||
|
||||
public SubstringFunctionPipe(Source source, Expression expression, Pipe src, Pipe start, Pipe end) {
|
||||
super(source, expression, Arrays.asList(src, start, end));
|
||||
this.source = src;
|
||||
public SubstringFunctionPipe(Source source, Expression expression, Pipe input, Pipe start, Pipe end) {
|
||||
super(source, expression, Arrays.asList(input, start, end));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
@ -36,48 +36,48 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newStart = start.resolveAttributes(resolver);
|
||||
Pipe newEnd = end.resolveAttributes(resolver);
|
||||
if (newSource == source && newStart == start && newEnd == end) {
|
||||
if (newInput == input && newStart == start && newEnd == end) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newStart, newEnd);
|
||||
return replaceChildren(newInput, newStart, newEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery() && end.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery() && end.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && start.resolved() && end.resolved();
|
||||
return input.resolved() && start.resolved() && end.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newStart, Pipe newEnd) {
|
||||
return new SubstringFunctionPipe(source(), expression(), newSource, newStart, newEnd);
|
||||
protected SubstringFunctionPipe replaceChildren(Pipe newInput, Pipe newStart, Pipe newEnd) {
|
||||
return new SubstringFunctionPipe(source(), expression(), newInput, newStart, newEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
start.collectFields(sourceBuilder);
|
||||
end.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<SubstringFunctionPipe> info() {
|
||||
return NodeInfo.create(this, SubstringFunctionPipe::new, expression(), source, start, end);
|
||||
return NodeInfo.create(this, SubstringFunctionPipe::new, expression(), input, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubstringFunctionProcessor asProcessor() {
|
||||
return new SubstringFunctionProcessor(source.asProcessor(), start.asProcessor(), end.asProcessor());
|
||||
return new SubstringFunctionProcessor(input.asProcessor(), start.asProcessor(), end.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe start() {
|
||||
@ -90,7 +90,7 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, start, end);
|
||||
return Objects.hash(input(), start(), end());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,8 +104,8 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
SubstringFunctionPipe other = (SubstringFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source)
|
||||
&& Objects.equals(start, other.start)
|
||||
&& Objects.equals(end, other.end);
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(end(), other.end());
|
||||
}
|
||||
}
|
||||
|
@ -17,41 +17,41 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "ssub";
|
||||
|
||||
private final Processor source, start, end;
|
||||
private final Processor input, start, end;
|
||||
|
||||
public SubstringFunctionProcessor(Processor source, Processor start, Processor end) {
|
||||
this.source = source;
|
||||
this.input = source;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public SubstringFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
start = in.readNamedWriteable(Processor.class);
|
||||
end = in.readNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(start);
|
||||
out.writeNamedWriteable(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input), start.process(input), end.process(input));
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o), start.process(o), end.process(o));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object start, Object end) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object start, Object end) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(source instanceof String || source instanceof Character)) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (!(input instanceof String || input instanceof Character)) {
|
||||
throw new EqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (start == null) {
|
||||
return source;
|
||||
return input;
|
||||
}
|
||||
if ((start instanceof Number) == false) {
|
||||
throw new EqlIllegalArgumentException("A number is required; received [{}]", start);
|
||||
@ -60,15 +60,15 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
throw new EqlIllegalArgumentException("A number is required; received [{}]", end);
|
||||
}
|
||||
|
||||
String str = source.toString();
|
||||
String str = input.toString();
|
||||
int startIndex = ((Number) start).intValue();
|
||||
int endIndex = end == null ? str.length() : ((Number) end).intValue();
|
||||
|
||||
return StringUtils.substringSlice(str, startIndex, endIndex);
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
protected Processor start() {
|
||||
@ -90,14 +90,14 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
SubstringFunctionProcessor other = (SubstringFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(end(), other.end());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), start(), end());
|
||||
return Objects.hash(input(), start(), end());
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,15 +17,15 @@ import java.util.Objects;
|
||||
|
||||
public class ToStringFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source;
|
||||
private final Pipe input;
|
||||
|
||||
public ToStringFunctionPipe(Source source, Expression expression, Pipe src) {
|
||||
super(source, expression, Collections.singletonList(src));
|
||||
this.source = src;
|
||||
public ToStringFunctionPipe(Source source, Expression expression, Pipe input) {
|
||||
super(source, expression, Collections.singletonList(input));
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Pipe replaceChildren(List<Pipe> newChildren) {
|
||||
public final ToStringFunctionPipe replaceChildren(List<Pipe> newChildren) {
|
||||
if (newChildren.size() != 1) {
|
||||
throw new IllegalArgumentException("expected [1] children but received [" + newChildren.size() + "]");
|
||||
}
|
||||
@ -34,45 +34,46 @@ public class ToStringFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
if (newSource == source) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(Collections.singletonList(newSource));
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
return newInput == input ? this : replaceChildren(newInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved();
|
||||
return input.resolved();
|
||||
}
|
||||
|
||||
protected ToStringFunctionPipe replaceChildren(Pipe newInput) {
|
||||
return new ToStringFunctionPipe(source(), expression(), newInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<ToStringFunctionPipe> info() {
|
||||
return NodeInfo.create(this, ToStringFunctionPipe::new, expression(), source);
|
||||
return NodeInfo.create(this, ToStringFunctionPipe::new, expression(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToStringFunctionProcessor asProcessor() {
|
||||
return new ToStringFunctionProcessor(source.asProcessor());
|
||||
return new ToStringFunctionProcessor(input.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source);
|
||||
return Objects.hash(input());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,6 +86,6 @@ public class ToStringFunctionPipe extends Pipe {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(source, ((ToStringFunctionPipe) obj).source);
|
||||
return Objects.equals(input(), ((ToStringFunctionPipe) obj).input());
|
||||
}
|
||||
}
|
||||
|
@ -16,32 +16,32 @@ public class ToStringFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "sstr";
|
||||
|
||||
private final Processor source;
|
||||
private final Processor input;
|
||||
|
||||
public ToStringFunctionProcessor(Processor source) {
|
||||
this.source = source;
|
||||
public ToStringFunctionProcessor(Processor input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public ToStringFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input));
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source) {
|
||||
return source == null ? null : source.toString();
|
||||
public static Object doProcess(Object input) {
|
||||
return input == null ? null : input.toString();
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,12 +55,12 @@ public class ToStringFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
ToStringFunctionProcessor other = (ToStringFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source());
|
||||
return Objects.equals(input(), other.input());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source());
|
||||
return Objects.hash(input());
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,8 +97,8 @@ final class QueryTranslator {
|
||||
}
|
||||
if (f instanceof CIDRMatch) {
|
||||
CIDRMatch cm = (CIDRMatch) f;
|
||||
if (cm.field() instanceof FieldAttribute && Expressions.foldable(cm.addresses())) {
|
||||
String targetFieldName = handler.nameOf(((FieldAttribute) cm.field()).exactAttribute());
|
||||
if (cm.input() instanceof FieldAttribute && Expressions.foldable(cm.addresses())) {
|
||||
String targetFieldName = handler.nameOf(((FieldAttribute) cm.input()).exactAttribute());
|
||||
|
||||
Set<Object> set = new LinkedHashSet<>(CollectionUtils.mapSize(cm.addresses().size()));
|
||||
|
||||
|
119
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/math/ToNumberFunctionPipeTests.java
Normal file
119
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/math/ToNumberFunctionPipeTests.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.math;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomIntLiteral;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class ToNumberFunctionPipeTests extends AbstractNodeTestCase<ToNumberFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected ToNumberFunctionPipe randomInstance() {
|
||||
return randomToNumberFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomToNumberFunctionExpression() {
|
||||
return randomToNumberFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static ToNumberFunctionPipe randomToNumberFunctionPipe() {
|
||||
return (ToNumberFunctionPipe) (new ToNumber(
|
||||
randomSource(),
|
||||
randomStringLiteral(),
|
||||
randomFrom(true, false) ? randomIntLiteral() : null)
|
||||
.makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (string and base) which are tested separately
|
||||
ToNumberFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomToNumberFunctionExpression());
|
||||
ToNumberFunctionPipe newB = new ToNumberFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.value(),
|
||||
b1.base());
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
ToNumberFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new ToNumberFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.value(),
|
||||
b2.base());
|
||||
assertEquals(newB,
|
||||
b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
ToNumberFunctionPipe b = randomInstance();
|
||||
Pipe newValue = randomValueOtherThan(b.value(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newBase = b.base() == null ? null : randomValueOtherThan(b.base(), () -> pipe(randomIntLiteral()));
|
||||
ToNumberFunctionPipe newB = new ToNumberFunctionPipe(b.source(), b.expression(), b.value(), b.base());
|
||||
|
||||
ToNumberFunctionPipe transformed = newB.replaceChildren(newValue, b.base());
|
||||
assertEquals(transformed.value(), newValue);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.base(), b.base());
|
||||
|
||||
transformed = newB.replaceChildren(b.value(), newBase);
|
||||
assertEquals(transformed.value(), b.value());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.base(), newBase);
|
||||
|
||||
transformed = newB.replaceChildren(newValue, newBase);
|
||||
assertEquals(transformed.value(), newValue);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.base(), newBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToNumberFunctionPipe mutate(ToNumberFunctionPipe instance) {
|
||||
List<Function<ToNumberFunctionPipe, ToNumberFunctionPipe>> randoms = new ArrayList<>();
|
||||
randoms.add(f -> new ToNumberFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.value(), () -> randomStringLiteral()))),
|
||||
f.base()));
|
||||
randoms.add(f -> new ToNumberFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
f.value(),
|
||||
f.base() == null ? null : randomValueOtherThan(f.base(), () -> pipe(randomIntLiteral()))));
|
||||
randoms.add(f -> new ToNumberFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.value(), () -> randomStringLiteral()))),
|
||||
f.base() == null ? null : randomValueOtherThan(f.base(), () -> pipe(randomIntLiteral()))));
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToNumberFunctionPipe copy(ToNumberFunctionPipe instance) {
|
||||
return new ToNumberFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.value(),
|
||||
instance.base());
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTest
|
||||
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
|
||||
|
||||
public class ToNumberProcessorTests extends ESTestCase {
|
||||
public class ToNumberFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
private static Object process(Object value, Object base) {
|
||||
return new ToNumber(EMPTY, l(value), l(base)).makePipe().asProcessor().process(null);
|
155
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/BetweenFunctionPipeTests.java
Normal file
155
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/BetweenFunctionPipeTests.java
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.Combinations;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomBooleanLiteral;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class BetweenFunctionPipeTests extends AbstractNodeTestCase<BetweenFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected BetweenFunctionPipe randomInstance() {
|
||||
return randomBetweenFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomBetweenFunctionExpression() {
|
||||
return randomBetweenFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static BetweenFunctionPipe randomBetweenFunctionPipe() {
|
||||
return (BetweenFunctionPipe) (new Between(randomSource(),
|
||||
randomStringLiteral(),
|
||||
randomStringLiteral(),
|
||||
randomStringLiteral(),
|
||||
randomFrom(true, false) ? randomBooleanLiteral() : null,
|
||||
randomBooleanLiteral())
|
||||
.makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (input, left, right, greedy, caseSensitive) which are tested separately
|
||||
BetweenFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomBetweenFunctionExpression());
|
||||
BetweenFunctionPipe newB = new BetweenFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.left(),
|
||||
b1.right(),
|
||||
b1.greedy(),
|
||||
b1.caseSensitive());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
BetweenFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new BetweenFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input(),
|
||||
b2.left(),
|
||||
b2.right(),
|
||||
b2.greedy(),
|
||||
b2.caseSensitive());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
BetweenFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newLeft = randomValueOtherThan(b.left(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newRight = randomValueOtherThan(b.right(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newGreedy = b.greedy() == null ? null : randomValueOtherThan(b.greedy(), () -> pipe(randomBooleanLiteral()));
|
||||
Pipe newCaseSensitive = randomValueOtherThan(b.caseSensitive(), () -> pipe(randomBooleanLiteral()));
|
||||
|
||||
BetweenFunctionPipe newB = new BetweenFunctionPipe(b.source(), b.expression(), b.input(), b.left(), b.right(), b.greedy(),
|
||||
b.caseSensitive());
|
||||
BetweenFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 6; i++) {
|
||||
for(BitSet comb : new Combinations(5, i)) {
|
||||
Pipe tempNewGreedy = b.greedy() == null ? b.greedy() : (comb.get(3) ? newGreedy : b.greedy());
|
||||
transformed = (BetweenFunctionPipe) newB.replaceChildren(
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newLeft : b.left(),
|
||||
comb.get(2) ? newRight : b.right(),
|
||||
tempNewGreedy,
|
||||
comb.get(4) ? newCaseSensitive : b.caseSensitive());
|
||||
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.left(), comb.get(1) ? newLeft : b.left());
|
||||
assertEquals(transformed.right(), comb.get(2) ? newRight : b.right());
|
||||
assertEquals(transformed.greedy(), tempNewGreedy);
|
||||
assertEquals(transformed.caseSensitive(), comb.get(4) ? newCaseSensitive : b.caseSensitive());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BetweenFunctionPipe mutate(BetweenFunctionPipe instance) {
|
||||
List<Function<BetweenFunctionPipe, BetweenFunctionPipe>> randoms = new ArrayList<>();
|
||||
if (instance.greedy() == null) {
|
||||
for(int i = 1; i < 5; i++) {
|
||||
for(BitSet comb : new Combinations(4, i)) {
|
||||
randoms.add(f -> new BetweenFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.left(), () -> pipe(randomStringLiteral())) : f.left(),
|
||||
comb.get(2) ? randomValueOtherThan(f.right(), () -> pipe(randomStringLiteral())) : f.right(),
|
||||
null,
|
||||
comb.get(4) ? randomValueOtherThan(f.caseSensitive(), () -> pipe(randomBooleanLiteral())) : f.caseSensitive()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 1; i < 6; i++) {
|
||||
for(BitSet comb : new Combinations(5, i)) {
|
||||
randoms.add(f -> new BetweenFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.left(), () -> pipe(randomStringLiteral())) : f.left(),
|
||||
comb.get(2) ? randomValueOtherThan(f.right(), () -> pipe(randomStringLiteral())) : f.right(),
|
||||
comb.get(3) ? randomValueOtherThan(f.greedy(), () -> pipe(randomBooleanLiteral())) : f.greedy(),
|
||||
comb.get(4) ? randomValueOtherThan(f.caseSensitive(), () -> pipe(randomBooleanLiteral())) : f.caseSensitive()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BetweenFunctionPipe copy(BetweenFunctionPipe instance) {
|
||||
return new BetweenFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.input(),
|
||||
instance.left(),
|
||||
instance.right(),
|
||||
instance.greedy(),
|
||||
instance.caseSensitive());
|
||||
}
|
||||
}
|
130
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/CIDRMatchFunctionPipeTests.java
Normal file
130
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/CIDRMatchFunctionPipeTests.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class CIDRMatchFunctionPipeTests extends AbstractNodeTestCase<CIDRMatchFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected CIDRMatchFunctionPipe randomInstance() {
|
||||
return randomCIDRMatchFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomCIDRMatchFunctionExpression() {
|
||||
return randomCIDRMatchFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static CIDRMatchFunctionPipe randomCIDRMatchFunctionPipe() {
|
||||
int size = randomIntBetween(2, 10);
|
||||
List<Expression> addresses = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
addresses.add(randomStringLiteral());
|
||||
}
|
||||
return (CIDRMatchFunctionPipe) (new CIDRMatch(randomSource(), randomStringLiteral(), addresses).makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (input, addresses) which are tested separately
|
||||
CIDRMatchFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomCIDRMatchFunctionExpression());
|
||||
CIDRMatchFunctionPipe newB = new CIDRMatchFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.addresses());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
CIDRMatchFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new CIDRMatchFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input(),
|
||||
b2.addresses());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
CIDRMatchFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
List<Pipe> newAddresses = mutateOneAddress(b.addresses());
|
||||
|
||||
CIDRMatchFunctionPipe newB = new CIDRMatchFunctionPipe(b.source(), b.expression(), b.input(), b.addresses());
|
||||
CIDRMatchFunctionPipe transformed = newB.replaceChildren(newInput, b.addresses());
|
||||
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.addresses(), b.addresses());
|
||||
|
||||
transformed = newB.replaceChildren(b.input(), newAddresses);
|
||||
assertEquals(transformed.input(), b.input());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.addresses(), newAddresses);
|
||||
|
||||
transformed = newB.replaceChildren(newInput, newAddresses);
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.addresses(), newAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CIDRMatchFunctionPipe mutate(CIDRMatchFunctionPipe instance) {
|
||||
List<Function<CIDRMatchFunctionPipe, CIDRMatchFunctionPipe>> randoms = new ArrayList<>();
|
||||
randoms.add(f -> new CIDRMatchFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())),
|
||||
f.addresses()));
|
||||
randoms.add(f -> new CIDRMatchFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
f.input(),
|
||||
mutateOneAddress(f.addresses())));
|
||||
randoms.add(f -> new CIDRMatchFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())),
|
||||
mutateOneAddress(f.addresses())));
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CIDRMatchFunctionPipe copy(CIDRMatchFunctionPipe instance) {
|
||||
return new CIDRMatchFunctionPipe(instance.source(), instance.expression(), instance.input(), instance.addresses());
|
||||
}
|
||||
|
||||
private List<Pipe> mutateOneAddress(List<Pipe> oldAddresses) {
|
||||
int size = oldAddresses.size();
|
||||
ArrayList<Pipe> newAddresses = new ArrayList<>(size);
|
||||
|
||||
int index = randomIntBetween(0, size - 1);
|
||||
for (int i = 0; i < size; i++) {
|
||||
Pipe p = oldAddresses.get(i);
|
||||
newAddresses.add(i != index ? p : randomValueOtherThan(p, () -> pipe(randomStringLiteral())));
|
||||
}
|
||||
return newAddresses;
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import java.util.ArrayList;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l;
|
||||
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
|
||||
public class CIDRMatchProcessorTests extends ESTestCase {
|
||||
public class CIDRMatchFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
public void testCIDRMatchFunctionValidInput() {
|
||||
// Expects null if source was null
|
101
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ConcatFunctionPipeTests.java
Normal file
101
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ConcatFunctionPipeTests.java
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class ConcatFunctionPipeTests extends AbstractNodeTestCase<ConcatFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected ConcatFunctionPipe randomInstance() {
|
||||
return randomConcatFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomConcatFunctionExpression() {
|
||||
return randomConcatFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static ConcatFunctionPipe randomConcatFunctionPipe() {
|
||||
int size = randomIntBetween(2, 10);
|
||||
List<Expression> addresses = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
addresses.add(randomStringLiteral());
|
||||
}
|
||||
return (ConcatFunctionPipe) (new Concat(randomSource(), addresses).makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (the values) which are tested separately
|
||||
ConcatFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomConcatFunctionExpression());
|
||||
ConcatFunctionPipe newB = new ConcatFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.values());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
ConcatFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new ConcatFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.values());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
ConcatFunctionPipe b = randomInstance();
|
||||
List<Pipe> newValues = mutateOneValue(b.values());
|
||||
|
||||
ConcatFunctionPipe newB = new ConcatFunctionPipe(b.source(), b.expression(), b.values());
|
||||
ConcatFunctionPipe transformed = newB.replaceChildren(newValues);
|
||||
|
||||
assertEquals(transformed.values(), newValues);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConcatFunctionPipe mutate(ConcatFunctionPipe instance) {
|
||||
return new ConcatFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
mutateOneValue(instance.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConcatFunctionPipe copy(ConcatFunctionPipe instance) {
|
||||
return new ConcatFunctionPipe(instance.source(), instance.expression(), instance.values());
|
||||
}
|
||||
|
||||
private List<Pipe> mutateOneValue(List<Pipe> oldValues) {
|
||||
int size = oldValues.size();
|
||||
ArrayList<Pipe> newValues = new ArrayList<>(size);
|
||||
|
||||
int index = randomIntBetween(0, size - 1);
|
||||
for (int i = 0; i < size; i++) {
|
||||
Pipe p = oldValues.get(i);
|
||||
newValues.add(i != index ? p : randomValueOtherThan(p, () -> pipe(randomStringLiteral())));
|
||||
}
|
||||
return newValues;
|
||||
}
|
||||
}
|
127
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/EndsWithFunctionPipeTests.java
Normal file
127
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/EndsWithFunctionPipeTests.java
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.eql.EqlTestUtils;
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class EndsWithFunctionPipeTests extends AbstractNodeTestCase<EndsWithFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected EndsWithFunctionPipe randomInstance() {
|
||||
return randomEndsWithFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomEndsWithFunctionExpression() {
|
||||
return randomEndsWithFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static EndsWithFunctionPipe randomEndsWithFunctionPipe() {
|
||||
return (EndsWithFunctionPipe) (new EndsWith(randomSource(),
|
||||
randomStringLiteral(),
|
||||
randomStringLiteral(),
|
||||
EqlTestUtils.randomConfiguration())
|
||||
.makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (input and pattern) which are tested separately
|
||||
EndsWithFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomEndsWithFunctionExpression());
|
||||
EndsWithFunctionPipe newB = new EndsWithFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.pattern(),
|
||||
b1.isCaseSensitive());
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
EndsWithFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new EndsWithFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input(),
|
||||
b2.pattern(),
|
||||
b2.isCaseSensitive());
|
||||
assertEquals(newB,
|
||||
b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
EndsWithFunctionPipe b = randomInstance();
|
||||
Pipe newInput = pipe(((Expression) randomValueOtherThan(b.input(), () -> randomStringLiteral())));
|
||||
Pipe newPattern = pipe(((Expression) randomValueOtherThan(b.pattern(), () -> randomStringLiteral())));
|
||||
boolean newCaseSensitive = randomValueOtherThan(b.isCaseSensitive(), () -> randomBoolean());
|
||||
EndsWithFunctionPipe newB =
|
||||
new EndsWithFunctionPipe(b.source(), b.expression(), b.input(), b.pattern(), newCaseSensitive);
|
||||
|
||||
EndsWithFunctionPipe transformed = newB.replaceChildren(newInput, b.pattern());
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), b.pattern());
|
||||
|
||||
transformed = newB.replaceChildren(b.input(), newPattern);
|
||||
assertEquals(transformed.input(), b.input());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), newPattern);
|
||||
|
||||
transformed = newB.replaceChildren(newInput, newPattern);
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), newPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EndsWithFunctionPipe mutate(EndsWithFunctionPipe instance) {
|
||||
List<Function<EndsWithFunctionPipe, EndsWithFunctionPipe>> randoms = new ArrayList<>();
|
||||
randoms.add(f -> new EndsWithFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.input(), () -> randomStringLiteral()))),
|
||||
f.pattern(),
|
||||
randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean())));
|
||||
randoms.add(f -> new EndsWithFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
f.input(),
|
||||
pipe(((Expression) randomValueOtherThan(f.pattern(), () -> randomStringLiteral()))),
|
||||
randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean())));
|
||||
randoms.add(f -> new EndsWithFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.input(), () -> randomStringLiteral()))),
|
||||
pipe(((Expression) randomValueOtherThan(f.pattern(), () -> randomStringLiteral()))),
|
||||
randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean())));
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EndsWithFunctionPipe copy(EndsWithFunctionPipe instance) {
|
||||
return new EndsWithFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.input(),
|
||||
instance.pattern(),
|
||||
instance.isCaseSensitive());
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class EndsWithProcessorTests extends ESTestCase {
|
||||
public class EndsWithFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
final Configuration caseInsensitive = randomConfigurationWithCaseSensitive(false);
|
||||
|
||||
@ -42,7 +42,6 @@ public class EndsWithProcessorTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testEndsWithFunctionWithValidInputCaseInsensitive() {
|
||||
final Configuration config = randomConfigurationWithCaseSensitive(false);
|
||||
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("r"), caseInsensitive).makePipe().asProcessor().process(null));
|
||||
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("R"), caseInsensitive).makePipe().asProcessor().process(null));
|
||||
assertEquals(false, new EndsWith(EMPTY, l("foobar"), l("foo"), caseInsensitive).makePipe().asProcessor().process(null));
|
145
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/IndexOfFunctionPipeTests.java
Normal file
145
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/IndexOfFunctionPipeTests.java
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.eql.EqlTestUtils;
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.Combinations;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomIntLiteral;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class IndexOfFunctionPipeTests extends AbstractNodeTestCase<IndexOfFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected IndexOfFunctionPipe randomInstance() {
|
||||
return randomIndexOfFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomIndexOfFunctionExpression() {
|
||||
return randomIndexOfFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static IndexOfFunctionPipe randomIndexOfFunctionPipe() {
|
||||
return (IndexOfFunctionPipe) (new IndexOf(randomSource(),
|
||||
randomStringLiteral(),
|
||||
randomStringLiteral(),
|
||||
randomFrom(true, false) ? randomIntLiteral() : null,
|
||||
EqlTestUtils.randomConfiguration())
|
||||
.makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (input, substring, start) which are tested separately
|
||||
IndexOfFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomIndexOfFunctionExpression());
|
||||
IndexOfFunctionPipe newB = new IndexOfFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.substring(),
|
||||
b1.start(),
|
||||
b1.isCaseSensitive());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
IndexOfFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new IndexOfFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input(),
|
||||
b2.substring(),
|
||||
b2.start(),
|
||||
b2.isCaseSensitive());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
IndexOfFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newSubstring = randomValueOtherThan(b.substring(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newStart = b.start() == null ? null : randomValueOtherThan(b.start(), () -> pipe(randomIntLiteral()));
|
||||
boolean newCaseSensitive = randomValueOtherThan(b.isCaseSensitive(), () -> randomBoolean());
|
||||
|
||||
IndexOfFunctionPipe newB = new IndexOfFunctionPipe(b.source(), b.expression(), b.input(), b.substring(), b.start(),
|
||||
newCaseSensitive);
|
||||
IndexOfFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
Pipe tempNewStart = b.start() == null ? b.start() : (comb.get(2) ? newStart : b.start());
|
||||
transformed = newB.replaceChildren(
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newSubstring : b.substring(),
|
||||
tempNewStart);
|
||||
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.substring(), comb.get(1) ? newSubstring : b.substring());
|
||||
assertEquals(transformed.start(), tempNewStart);
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexOfFunctionPipe mutate(IndexOfFunctionPipe instance) {
|
||||
List<Function<IndexOfFunctionPipe, IndexOfFunctionPipe>> randoms = new ArrayList<>();
|
||||
if (instance.start() == null) {
|
||||
for(int i = 1; i < 3; i++) {
|
||||
for(BitSet comb : new Combinations(2, i)) {
|
||||
randoms.add(f -> new IndexOfFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.substring(), () -> pipe(randomStringLiteral())) : f.substring(),
|
||||
null,
|
||||
randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean())));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
randoms.add(f -> new IndexOfFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.substring(), () -> pipe(randomStringLiteral())) : f.substring(),
|
||||
comb.get(2) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start(),
|
||||
randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexOfFunctionPipe copy(IndexOfFunctionPipe instance) {
|
||||
return new IndexOfFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.input(),
|
||||
instance.substring(),
|
||||
instance.start(),
|
||||
instance.isCaseSensitive());
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class IndexOfProcessorTests extends ESTestCase {
|
||||
public class IndexOfFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
final Configuration caseInsensitive = randomConfigurationWithCaseSensitive(false);
|
||||
|
82
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/LengthFunctionPipeTests.java
Normal file
82
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/LengthFunctionPipeTests.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class LengthFunctionPipeTests extends AbstractNodeTestCase<LengthFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected LengthFunctionPipe randomInstance() {
|
||||
return randomLengthFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomLengthFunctionExpression() {
|
||||
return randomLengthFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static LengthFunctionPipe randomLengthFunctionPipe() {
|
||||
return (LengthFunctionPipe) (new Length(randomSource(), randomStringLiteral()).makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (the input itself) which are tested separately
|
||||
LengthFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomLengthFunctionExpression());
|
||||
LengthFunctionPipe newB = new LengthFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
LengthFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new LengthFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
LengthFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
|
||||
LengthFunctionPipe newB = new LengthFunctionPipe(b.source(), b.expression(), b.input());
|
||||
LengthFunctionPipe transformed = newB.replaceChildren(newInput);
|
||||
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LengthFunctionPipe mutate(LengthFunctionPipe instance) {
|
||||
return new LengthFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
randomValueOtherThan(instance.input(), () -> pipe(randomStringLiteral())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LengthFunctionPipe copy(LengthFunctionPipe instance) {
|
||||
return new LengthFunctionPipe(instance.source(), instance.expression(), instance.input());
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class LengthProcessorTests extends ESTestCase {
|
||||
public class LengthFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
public void testLengthFunctionWithValidInput() {
|
||||
assertEquals(9, new Length(EMPTY, l("foobarbar")).makePipe().asProcessor().process(null));
|
@ -15,7 +15,7 @@ import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfigurationWithCaseSensitive;
|
||||
|
||||
public class StartsWithProcessorTests extends org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWithProcessorTests {
|
||||
public class StartsWithFunctionProcessorTests extends org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWithProcessorTests{
|
||||
|
||||
@Override
|
||||
protected Supplier<Boolean> isCaseSensitiveGenerator() {
|
115
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/StringContainsFunctionPipeTests.java
Normal file
115
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/StringContainsFunctionPipeTests.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class StringContainsFunctionPipeTests extends AbstractNodeTestCase<StringContainsFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected StringContainsFunctionPipe randomInstance() {
|
||||
return randomStringContainsFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomStringContainsFunctionExpression() {
|
||||
return randomStringContainsFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static StringContainsFunctionPipe randomStringContainsFunctionPipe() {
|
||||
return (StringContainsFunctionPipe) (new StringContains(randomSource(), randomStringLiteral(), randomStringLiteral()).makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (string and substring) which are tested separately
|
||||
StringContainsFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomStringContainsFunctionExpression());
|
||||
StringContainsFunctionPipe newB = new StringContainsFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.string(),
|
||||
b1.substring());
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
StringContainsFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new StringContainsFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.string(),
|
||||
b2.substring());
|
||||
assertEquals(newB,
|
||||
b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
StringContainsFunctionPipe b = randomInstance();
|
||||
Pipe newString = pipe(((Expression) randomValueOtherThan(b.string(), () -> randomStringLiteral())));
|
||||
Pipe newSubstring = pipe(((Expression) randomValueOtherThan(b.substring(), () -> randomStringLiteral())));
|
||||
StringContainsFunctionPipe newB =
|
||||
new StringContainsFunctionPipe(b.source(), b.expression(), b.string(), b.substring());
|
||||
|
||||
StringContainsFunctionPipe transformed = newB.replaceChildren(newString, b.substring());
|
||||
assertEquals(transformed.string(), newString);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.substring(), b.substring());
|
||||
|
||||
transformed = newB.replaceChildren(b.string(), newSubstring);
|
||||
assertEquals(transformed.string(), b.string());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.substring(), newSubstring);
|
||||
|
||||
transformed = newB.replaceChildren(newString, newSubstring);
|
||||
assertEquals(transformed.string(), newString);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.substring(), newSubstring);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringContainsFunctionPipe mutate(StringContainsFunctionPipe instance) {
|
||||
List<Function<StringContainsFunctionPipe, StringContainsFunctionPipe>> randoms = new ArrayList<>();
|
||||
randoms.add(f -> new StringContainsFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.string(), () -> randomStringLiteral()))),
|
||||
f.substring()));
|
||||
randoms.add(f -> new StringContainsFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
f.string(),
|
||||
pipe(((Expression) randomValueOtherThan(f.substring(), () -> randomStringLiteral())))));
|
||||
randoms.add(f -> new StringContainsFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.string(), () -> randomStringLiteral()))),
|
||||
pipe(((Expression) randomValueOtherThan(f.substring(), () -> randomStringLiteral())))));
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StringContainsFunctionPipe copy(StringContainsFunctionPipe instance) {
|
||||
return new StringContainsFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.string(),
|
||||
instance.substring());
|
||||
}
|
||||
}
|
136
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/SubstringFunctionPipeTests.java
Normal file
136
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/SubstringFunctionPipeTests.java
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.Combinations;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomIntLiteral;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class SubstringFunctionPipeTests extends AbstractNodeTestCase<SubstringFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected SubstringFunctionPipe randomInstance() {
|
||||
return randomSubstringFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomSubstringFunctionExpression() {
|
||||
return randomSubstringFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static SubstringFunctionPipe randomSubstringFunctionPipe() {
|
||||
return (SubstringFunctionPipe) (new Substring(randomSource(),
|
||||
randomStringLiteral(),
|
||||
randomIntLiteral(),
|
||||
randomFrom(true, false) ? randomIntLiteral() : null)
|
||||
.makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (input, start, end) which are tested separately
|
||||
SubstringFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomSubstringFunctionExpression());
|
||||
SubstringFunctionPipe newB = new SubstringFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.start(),
|
||||
b1.end());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
SubstringFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new SubstringFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input(),
|
||||
b2.start(),
|
||||
b2.end());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
SubstringFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newStart = randomValueOtherThan(b.start(), () -> pipe(randomIntLiteral()));
|
||||
Pipe newEnd = b.end() == null ? null : randomValueOtherThan(b.end(), () -> pipe(randomIntLiteral()));
|
||||
|
||||
SubstringFunctionPipe newB = new SubstringFunctionPipe(b.source(), b.expression(), b.input(), b.start(), b.end());
|
||||
SubstringFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
Pipe tempNewEnd = b.end() == null ? b.end() : (comb.get(2) ? newEnd : b.end());
|
||||
transformed = newB.replaceChildren(
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newStart : b.start(),
|
||||
tempNewEnd);
|
||||
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.start(), comb.get(1) ? newStart : b.start());
|
||||
assertEquals(transformed.end(), tempNewEnd);
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SubstringFunctionPipe mutate(SubstringFunctionPipe instance) {
|
||||
List<Function<SubstringFunctionPipe, SubstringFunctionPipe>> randoms = new ArrayList<>();
|
||||
if (instance.end() == null) {
|
||||
for(int i = 1; i < 3; i++) {
|
||||
for(BitSet comb : new Combinations(2, i)) {
|
||||
randoms.add(f -> new SubstringFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start(),
|
||||
null));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
randoms.add(f -> new SubstringFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start(),
|
||||
comb.get(2) ? randomValueOtherThan(f.end(), () -> pipe(randomIntLiteral())) : f.end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SubstringFunctionPipe copy(SubstringFunctionPipe instance) {
|
||||
return new SubstringFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.input(),
|
||||
instance.start(),
|
||||
instance.end());
|
||||
}
|
||||
}
|
28
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/SubstringFunctionProcessorTests.java
Normal file
28
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/SubstringFunctionProcessorTests.java
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l;
|
||||
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
|
||||
public class SubstringFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
public void testSubstringFunctionInputsValidation() {
|
||||
QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class,
|
||||
() -> new Substring(EMPTY, l(5), l("foo"), null).makePipe().asProcessor().process(null));
|
||||
assertEquals("A string/char is required; received [5]", siae.getMessage());
|
||||
siae = expectThrows(QlIllegalArgumentException.class,
|
||||
() -> new Substring(EMPTY, l("bar"), l(false), null).makePipe().asProcessor().process(null));
|
||||
assertEquals("A number is required; received [false]", siae.getMessage());
|
||||
siae = expectThrows(QlIllegalArgumentException.class,
|
||||
() -> new Substring(EMPTY, l("foo"), l(1), l("abc")).makePipe().asProcessor().process(null));
|
||||
assertEquals("A number is required; received [abc]", siae.getMessage());
|
||||
}
|
||||
}
|
82
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ToStringFunctionPipeTests.java
Normal file
82
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ToStringFunctionPipeTests.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.ql.expression.Expression;
|
||||
import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe;
|
||||
import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase;
|
||||
import org.elasticsearch.xpack.ql.tree.Source;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.Expressions.pipe;
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
|
||||
import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
|
||||
|
||||
public class ToStringFunctionPipeTests extends AbstractNodeTestCase<ToStringFunctionPipe, Pipe> {
|
||||
|
||||
@Override
|
||||
protected ToStringFunctionPipe randomInstance() {
|
||||
return randomToStringFunctionPipe();
|
||||
}
|
||||
|
||||
private Expression randomToStringFunctionExpression() {
|
||||
return randomToStringFunctionPipe().expression();
|
||||
}
|
||||
|
||||
public static ToStringFunctionPipe randomToStringFunctionPipe() {
|
||||
return (ToStringFunctionPipe) (new ToString(randomSource(), randomStringLiteral()).makePipe());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testTransform() {
|
||||
// test transforming only the properties (source, expression),
|
||||
// skipping the children (the input itself) which are tested separately
|
||||
ToStringFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomToStringFunctionExpression());
|
||||
ToStringFunctionPipe newB = new ToStringFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
ToStringFunctionPipe b2 = randomInstance();
|
||||
Source newLoc = randomValueOtherThan(b2.source(), () -> randomSource());
|
||||
newB = new ToStringFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.input());
|
||||
|
||||
assertEquals(newB, b2.transformPropertiesOnly(v -> Objects.equals(v, b2.source()) ? newLoc : v, Source.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
ToStringFunctionPipe b = randomInstance();
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
|
||||
ToStringFunctionPipe newB = new ToStringFunctionPipe(b.source(), b.expression(), b.input());
|
||||
ToStringFunctionPipe transformed = newB.replaceChildren(newInput);
|
||||
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToStringFunctionPipe mutate(ToStringFunctionPipe instance) {
|
||||
return new ToStringFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
randomValueOtherThan(instance.input(), () -> pipe(randomStringLiteral())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToStringFunctionPipe copy(ToStringFunctionPipe instance) {
|
||||
return new ToStringFunctionPipe(instance.source(), instance.expression(), instance.input());
|
||||
}
|
||||
}
|
34
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ToStringFunctionProcessorTests.java
Normal file
34
x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/ToStringFunctionProcessorTests.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.eql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l;
|
||||
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
|
||||
public class ToStringFunctionProcessorTests extends ESTestCase {
|
||||
|
||||
public void testToStringFunctionWithValidInput() {
|
||||
assertToStringWithObject("foo");
|
||||
assertToStringWithObject(123);
|
||||
assertToStringWithObject(1234L);
|
||||
assertToStringWithObject(123.456);
|
||||
assertToStringWithObject(123.456f);
|
||||
assertToStringWithObject(123.456d);
|
||||
assertToStringWithObject('f');
|
||||
assertToStringWithObject(null);
|
||||
}
|
||||
|
||||
private void assertToStringWithObject(Object input) {
|
||||
Object str = new ToString(EMPTY, l(input)).makePipe().asProcessor().process(null);
|
||||
assertEquals(input == null ? null : input.toString(), str);
|
||||
if (str != null) {
|
||||
assertTrue(str instanceof String);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,12 +33,12 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
|
||||
*/
|
||||
public class StartsWith extends CaseSensitiveScalarFunction {
|
||||
|
||||
private final Expression field;
|
||||
private final Expression input;
|
||||
private final Expression pattern;
|
||||
|
||||
public StartsWith(Source source, Expression field, Expression pattern, Configuration configuration) {
|
||||
super(source, Arrays.asList(field, pattern), configuration);
|
||||
this.field = field;
|
||||
public StartsWith(Source source, Expression input, Expression pattern, Configuration configuration) {
|
||||
super(source, Arrays.asList(input, pattern), configuration);
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class StartsWith extends CaseSensitiveScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution fieldResolution = isStringAndExact(field, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution fieldResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (fieldResolution.unresolved()) {
|
||||
return fieldResolution;
|
||||
}
|
||||
@ -56,8 +56,8 @@ public class StartsWith extends CaseSensitiveScalarFunction {
|
||||
return isStringAndExact(pattern, sourceText(), ParamOrdinal.SECOND);
|
||||
}
|
||||
|
||||
public Expression field() {
|
||||
return field;
|
||||
public Expression input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Expression pattern() {
|
||||
@ -71,27 +71,27 @@ public class StartsWith extends CaseSensitiveScalarFunction {
|
||||
|
||||
@Override
|
||||
public Pipe makePipe() {
|
||||
return new StartsWithFunctionPipe(source(), this, Expressions.pipe(field), Expressions.pipe(pattern), isCaseSensitive());
|
||||
return new StartsWithFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(pattern), isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return field.foldable() && pattern.foldable();
|
||||
return input.foldable() && pattern.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(field.fold(), pattern.fold(), isCaseSensitive());
|
||||
return doProcess(input.fold(), pattern.fold(), isCaseSensitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, StartsWith::new, field, pattern, configuration());
|
||||
return NodeInfo.create(this, StartsWith::new, input, pattern, configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate fieldScript = asScript(field);
|
||||
ScriptTemplate fieldScript = asScript(input);
|
||||
ScriptTemplate patternScript = asScript(pattern);
|
||||
|
||||
return asScriptFrom(fieldScript, patternScript);
|
||||
|
@ -17,13 +17,13 @@ import java.util.Objects;
|
||||
|
||||
public class StartsWithFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe field;
|
||||
private final Pipe input;
|
||||
private final Pipe pattern;
|
||||
private final boolean isCaseSensitive;
|
||||
|
||||
public StartsWithFunctionPipe(Source source, Expression expression, Pipe field, Pipe pattern, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(field, pattern));
|
||||
this.field = field;
|
||||
public StartsWithFunctionPipe(Source source, Expression expression, Pipe input, Pipe pattern, boolean isCaseSensitive) {
|
||||
super(source, expression, Arrays.asList(input, pattern));
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
@ -38,9 +38,9 @@ public class StartsWithFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newField = field.resolveAttributes(resolver);
|
||||
Pipe newField = input.resolveAttributes(resolver);
|
||||
Pipe newPattern = pattern.resolveAttributes(resolver);
|
||||
if (newField == field && newPattern == pattern) {
|
||||
if (newField == input && newPattern == pattern) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newField, newPattern);
|
||||
@ -48,12 +48,12 @@ public class StartsWithFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return field.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return field.resolved() && pattern.resolved();
|
||||
return input.resolved() && pattern.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newField, Pipe newPattern) {
|
||||
@ -62,22 +62,22 @@ public class StartsWithFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
field.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
pattern.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<StartsWithFunctionPipe> info() {
|
||||
return NodeInfo.create(this, StartsWithFunctionPipe::new, expression(), field, pattern, isCaseSensitive);
|
||||
return NodeInfo.create(this, StartsWithFunctionPipe::new, expression(), input, pattern, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartsWithFunctionProcessor asProcessor() {
|
||||
return new StartsWithFunctionProcessor(field.asProcessor(), pattern.asProcessor(), isCaseSensitive);
|
||||
return new StartsWithFunctionProcessor(input.asProcessor(), pattern.asProcessor(), isCaseSensitive);
|
||||
}
|
||||
|
||||
public Pipe field() {
|
||||
return field;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe pattern() {
|
||||
@ -90,7 +90,7 @@ public class StartsWithFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(field, pattern, isCaseSensitive);
|
||||
return Objects.hash(input, pattern, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,7 +104,7 @@ public class StartsWithFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
StartsWithFunctionPipe other = (StartsWithFunctionPipe) obj;
|
||||
return Objects.equals(field, other.field)
|
||||
return Objects.equals(input, other.input)
|
||||
&& Objects.equals(pattern, other.pattern)
|
||||
&& Objects.equals(isCaseSensitive, other.isCaseSensitive);
|
||||
}
|
||||
|
@ -385,8 +385,8 @@ public final class ExpressionTranslators {
|
||||
public static Query doKnownTranslate(ScalarFunction f, TranslatorHandler handler) {
|
||||
if (f instanceof StartsWith) {
|
||||
StartsWith sw = (StartsWith) f;
|
||||
if (sw.isCaseSensitive() && sw.field() instanceof FieldAttribute && sw.pattern().foldable()) {
|
||||
String targetFieldName = handler.nameOf(((FieldAttribute) sw.field()).exactAttribute());
|
||||
if (sw.isCaseSensitive() && sw.input() instanceof FieldAttribute && sw.pattern().foldable()) {
|
||||
String targetFieldName = handler.nameOf(((FieldAttribute) sw.input()).exactAttribute());
|
||||
String pattern = (String) sw.pattern().fold();
|
||||
|
||||
return new PrefixQuery(f.source(), targetFieldName, pattern);
|
||||
|
@ -17,6 +17,7 @@ import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER;
|
||||
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
|
||||
@ -32,13 +33,17 @@ public final class FunctionTestUtils {
|
||||
}
|
||||
|
||||
public static Literal randomStringLiteral() {
|
||||
return l(ESTestCase.randomRealisticUnicodeOfLength(1024), KEYWORD);
|
||||
return l(ESTestCase.randomRealisticUnicodeOfLength(10), KEYWORD);
|
||||
}
|
||||
|
||||
public static Literal randomIntLiteral() {
|
||||
return l(ESTestCase.randomInt(), INTEGER);
|
||||
}
|
||||
|
||||
public static Literal randomBooleanLiteral() {
|
||||
return l(ESTestCase.randomBoolean(), BOOLEAN);
|
||||
}
|
||||
|
||||
public static Literal randomDatetimeLiteral() {
|
||||
return l(ZonedDateTime.ofInstant(Instant.ofEpochMilli(ESTestCase.randomLong()), ESTestCase.randomZone()), DATETIME);
|
||||
}
|
||||
|
@ -49,11 +49,11 @@ public class StartsWithFunctionPipeTests extends AbstractNodeTestCase<StartsWith
|
||||
StartsWithFunctionPipe b1 = randomInstance();
|
||||
Expression newExpression = randomValueOtherThan(b1.expression(), () -> randomStartsWithFunctionExpression());
|
||||
StartsWithFunctionPipe newB = new StartsWithFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.field(),
|
||||
b1.pattern(),
|
||||
b1.isCaseSensitive());
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.input(),
|
||||
b1.pattern(),
|
||||
b1.isCaseSensitive());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
|
||||
@ -62,7 +62,7 @@ public class StartsWithFunctionPipeTests extends AbstractNodeTestCase<StartsWith
|
||||
newB = new StartsWithFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.field(),
|
||||
b2.input(),
|
||||
b2.pattern(),
|
||||
b2.isCaseSensitive());
|
||||
|
||||
@ -73,24 +73,24 @@ public class StartsWithFunctionPipeTests extends AbstractNodeTestCase<StartsWith
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
StartsWithFunctionPipe b = randomInstance();
|
||||
Pipe newField = pipe(((Expression) randomValueOtherThan(b.field(), () -> randomStringLiteral())));
|
||||
Pipe newPattern = pipe(((Expression) randomValueOtherThan(b.pattern(), () -> randomStringLiteral())));
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newPattern = randomValueOtherThan(b.pattern(), () -> pipe(randomStringLiteral()));
|
||||
|
||||
StartsWithFunctionPipe newB = new StartsWithFunctionPipe(b.source(), b.expression(), b.field(), b.pattern(), b.isCaseSensitive());
|
||||
StartsWithFunctionPipe transformed = (StartsWithFunctionPipe) newB.replaceChildren(newField, b.pattern());
|
||||
assertEquals(transformed.field(), newField);
|
||||
StartsWithFunctionPipe newB = new StartsWithFunctionPipe(b.source(), b.expression(), b.input(), b.pattern(), b.isCaseSensitive());
|
||||
StartsWithFunctionPipe transformed = (StartsWithFunctionPipe) newB.replaceChildren(newInput, b.pattern());
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), b.pattern());
|
||||
|
||||
transformed = (StartsWithFunctionPipe) newB.replaceChildren(b.field(), newPattern);
|
||||
assertEquals(transformed.field(), b.field());
|
||||
transformed = (StartsWithFunctionPipe) newB.replaceChildren(b.input(), newPattern);
|
||||
assertEquals(transformed.input(), b.input());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), newPattern);
|
||||
|
||||
transformed = (StartsWithFunctionPipe) newB.replaceChildren(newField, newPattern);
|
||||
assertEquals(transformed.field(), newField);
|
||||
transformed = (StartsWithFunctionPipe) newB.replaceChildren(newInput, newPattern);
|
||||
assertEquals(transformed.input(), newInput);
|
||||
assertEquals(transformed.source(), b.source());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.pattern(), newPattern);
|
||||
@ -103,12 +103,9 @@ public class StartsWithFunctionPipeTests extends AbstractNodeTestCase<StartsWith
|
||||
for (BitSet comb : new Combinations(3, i)) {
|
||||
randoms.add(f -> new StartsWithFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.field(),
|
||||
() -> randomStringLiteral()))) : f.field(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.pattern(),
|
||||
() -> randomStringLiteral()))) : f.pattern(),
|
||||
comb.get(2) ? randomValueOtherThan(f.isCaseSensitive(),
|
||||
() -> randomBoolean()) : f.isCaseSensitive()));
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.pattern(), () -> pipe(randomStringLiteral())) : f.pattern(),
|
||||
comb.get(2) ? randomValueOtherThan(f.isCaseSensitive(), () -> randomBoolean()) : f.isCaseSensitive()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +116,7 @@ public class StartsWithFunctionPipeTests extends AbstractNodeTestCase<StartsWith
|
||||
protected StartsWithFunctionPipe copy(StartsWithFunctionPipe instance) {
|
||||
return new StartsWithFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.field(),
|
||||
instance.input(),
|
||||
instance.pattern(),
|
||||
instance.isCaseSensitive());
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ public class NodeSubclassTests<T extends B, B extends Node<B>> extends ESTestCas
|
||||
@SuppressWarnings("unchecked") // we pass a reasonable type so get reasonable results
|
||||
List<B> newCollection = (List<B>) makeListOfSameSizeOtherThan(changedArgType, originalList);
|
||||
|
||||
// Now merge that list of thildren into the original list of children
|
||||
// Now merge that list of children into the original list of children
|
||||
List<B> originalChildren = node.children();
|
||||
List<B> newChildren = new ArrayList<>(originalChildren.size());
|
||||
int originalOffset = 0;
|
||||
@ -672,7 +672,8 @@ public class NodeSubclassTests<T extends B, B extends Node<B>> extends ESTestCas
|
||||
|
||||
// filter the class that are not interested
|
||||
// (and IDE folders like eclipse)
|
||||
if (className.startsWith("org.elasticsearch.xpack.ql") == false && className.startsWith("org.elasticsearch.xpack.sql") == false) {
|
||||
if (className.startsWith("org.elasticsearch.xpack.ql") == false && className.startsWith("org.elasticsearch.xpack.sql") == false
|
||||
&& className.startsWith("org.elasticsearch.xpack.eql") == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,11 @@ import static org.elasticsearch.xpack.sql.expression.function.scalar.string.Inse
|
||||
*/
|
||||
public class Insert extends ScalarFunction {
|
||||
|
||||
private final Expression source, start, length, replacement;
|
||||
private final Expression input, start, length, replacement;
|
||||
|
||||
public Insert(Source source, Expression src, Expression start, Expression length, Expression replacement) {
|
||||
super(source, Arrays.asList(src, start, length, replacement));
|
||||
this.source = src;
|
||||
public Insert(Source source, Expression input, Expression start, Expression length, Expression replacement) {
|
||||
super(source, Arrays.asList(input, start, length, replacement));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.replacement = replacement;
|
||||
@ -50,7 +50,7 @@ public class Insert extends ScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -70,7 +70,7 @@ public class Insert extends ScalarFunction {
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable()
|
||||
return input.foldable()
|
||||
&& start.foldable()
|
||||
&& length.foldable()
|
||||
&& replacement.foldable();
|
||||
@ -78,13 +78,13 @@ public class Insert extends ScalarFunction {
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), start.fold(), length.fold(), replacement.fold());
|
||||
return doProcess(input.fold(), start.fold(), length.fold(), replacement.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new InsertFunctionPipe(source(), this,
|
||||
Expressions.pipe(source),
|
||||
Expressions.pipe(input),
|
||||
Expressions.pipe(start),
|
||||
Expressions.pipe(length),
|
||||
Expressions.pipe(replacement));
|
||||
@ -92,30 +92,30 @@ public class Insert extends ScalarFunction {
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Insert::new, source, start, length, replacement);
|
||||
return NodeInfo.create(this, Insert::new, input, start, length, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate startScript = asScript(start);
|
||||
ScriptTemplate lengthScript = asScript(length);
|
||||
ScriptTemplate replacementScript = asScript(replacement);
|
||||
|
||||
return asScriptFrom(sourceScript, startScript, lengthScript, replacementScript);
|
||||
return asScriptFrom(inputScript, startScript, lengthScript, replacementScript);
|
||||
}
|
||||
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate startScript,
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate startScript,
|
||||
ScriptTemplate lengthScript, ScriptTemplate replacementScript) {
|
||||
// basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2,...)
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s,%s,%s)"),
|
||||
"insert",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
startScript.template(),
|
||||
lengthScript.template(),
|
||||
replacementScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params()).script(startScript.params())
|
||||
.script(inputScript.params()).script(startScript.params())
|
||||
.script(lengthScript.params()).script(replacementScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ import java.util.Objects;
|
||||
|
||||
public class InsertFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, start, length, replacement;
|
||||
private final Pipe input, start, length, replacement;
|
||||
|
||||
public InsertFunctionPipe(Source source, Expression expression,
|
||||
Pipe src, Pipe start,
|
||||
Pipe input, Pipe start,
|
||||
Pipe length, Pipe replacement) {
|
||||
super(source, expression, Arrays.asList(src, start, length, replacement));
|
||||
this.source = src;
|
||||
super(source, expression, Arrays.asList(input, start, length, replacement));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.replacement = replacement;
|
||||
@ -39,22 +39,22 @@ public class InsertFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newStart = start.resolveAttributes(resolver);
|
||||
Pipe newLength = length.resolveAttributes(resolver);
|
||||
Pipe newReplacement = replacement.resolveAttributes(resolver);
|
||||
if (newSource == source
|
||||
if (newInput == input
|
||||
&& newStart == start
|
||||
&& newLength == length
|
||||
&& newReplacement == replacement) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newStart, newLength, newReplacement);
|
||||
return replaceChildren(newInput, newStart, newLength, newReplacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery()
|
||||
return input.supportedByAggsOnlyQuery()
|
||||
&& start.supportedByAggsOnlyQuery()
|
||||
&& length.supportedByAggsOnlyQuery()
|
||||
&& replacement.supportedByAggsOnlyQuery();
|
||||
@ -62,19 +62,19 @@ public class InsertFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && start.resolved() && length.resolved() && replacement.resolved();
|
||||
return input.resolved() && start.resolved() && length.resolved() && replacement.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource,
|
||||
protected Pipe replaceChildren(Pipe newInput,
|
||||
Pipe newStart,
|
||||
Pipe newLength,
|
||||
Pipe newReplacement) {
|
||||
return new InsertFunctionPipe(source(), expression(), newSource, newStart, newLength, newReplacement);
|
||||
return new InsertFunctionPipe(source(), expression(), newInput, newStart, newLength, newReplacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
start.collectFields(sourceBuilder);
|
||||
length.collectFields(sourceBuilder);
|
||||
replacement.collectFields(sourceBuilder);
|
||||
@ -82,16 +82,16 @@ public class InsertFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
protected NodeInfo<InsertFunctionPipe> info() {
|
||||
return NodeInfo.create(this, InsertFunctionPipe::new, expression(), source, start, length, replacement);
|
||||
return NodeInfo.create(this, InsertFunctionPipe::new, expression(), input, start, length, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertFunctionProcessor asProcessor() {
|
||||
return new InsertFunctionProcessor(source.asProcessor(), start.asProcessor(), length.asProcessor(), replacement.asProcessor());
|
||||
return new InsertFunctionProcessor(input.asProcessor(), start.asProcessor(), length.asProcessor(), replacement.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe start() {
|
||||
@ -108,7 +108,7 @@ public class InsertFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, start, length, replacement);
|
||||
return Objects.hash(input, start, length, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,7 +122,7 @@ public class InsertFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
InsertFunctionPipe other = (InsertFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source)
|
||||
return Objects.equals(input, other.input)
|
||||
&& Objects.equals(start, other.start)
|
||||
&& Objects.equals(length, other.length)
|
||||
&& Objects.equals(replacement, other.replacement);
|
||||
|
@ -15,18 +15,18 @@ import java.util.Objects;
|
||||
|
||||
public class InsertFunctionProcessor implements Processor {
|
||||
|
||||
private final Processor source, start, length, replacement;
|
||||
private final Processor input, start, length, replacement;
|
||||
public static final String NAME = "si";
|
||||
|
||||
public InsertFunctionProcessor(Processor source, Processor start, Processor length, Processor replacement) {
|
||||
this.source = source;
|
||||
public InsertFunctionProcessor(Processor input, Processor start, Processor length, Processor replacement) {
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
|
||||
public InsertFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
start = in.readNamedWriteable(Processor.class);
|
||||
length = in.readNamedWriteable(Processor.class);
|
||||
replacement = in.readNamedWriteable(Processor.class);
|
||||
@ -34,7 +34,7 @@ public class InsertFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source());
|
||||
out.writeNamedWriteable(input());
|
||||
out.writeNamedWriteable(start());
|
||||
out.writeNamedWriteable(length());
|
||||
out.writeNamedWriteable(replacement());
|
||||
@ -42,24 +42,24 @@ public class InsertFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source().process(input), start().process(input), length().process(input), replacement().process(input));
|
||||
return doProcess(input().process(input), start().process(input), length().process(input), replacement().process(input));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object start, Object length, Object replacement) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object start, Object length, Object replacement) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(source instanceof String || source instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (!(input instanceof String || input instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (replacement == null) {
|
||||
return source;
|
||||
return input;
|
||||
}
|
||||
if (!(replacement instanceof String || replacement instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", replacement);
|
||||
}
|
||||
if (start == null || length == null) {
|
||||
return source;
|
||||
return input;
|
||||
}
|
||||
if (!(start instanceof Number)) {
|
||||
throw new SqlIllegalArgumentException("A number is required; received [{}]", start);
|
||||
@ -74,11 +74,11 @@ public class InsertFunctionProcessor implements Processor {
|
||||
int startInt = ((Number) start).intValue() - 1;
|
||||
int realStart = startInt < 0 ? 0 : startInt;
|
||||
|
||||
if (startInt > source.toString().length()) {
|
||||
return source;
|
||||
if (startInt > input.toString().length()) {
|
||||
return input;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(source.toString());
|
||||
StringBuilder sb = new StringBuilder(input.toString());
|
||||
String replString = (replacement.toString());
|
||||
|
||||
return sb.replace(realStart,
|
||||
@ -97,7 +97,7 @@ public class InsertFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
InsertFunctionProcessor other = (InsertFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(length(), other.length())
|
||||
&& Objects.equals(replacement(), other.replacement());
|
||||
@ -105,11 +105,11 @@ public class InsertFunctionProcessor implements Processor {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), start(), length(), replacement());
|
||||
return Objects.hash(input(), start(), length(), replacement());
|
||||
}
|
||||
|
||||
public Processor source() {
|
||||
return source;
|
||||
public Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Processor start() {
|
||||
|
@ -38,12 +38,12 @@ import static org.elasticsearch.xpack.sql.expression.function.scalar.string.Loca
|
||||
*/
|
||||
public class Locate extends ScalarFunction implements OptionalArgument {
|
||||
|
||||
private final Expression pattern, source, start;
|
||||
private final Expression pattern, input, start;
|
||||
|
||||
public Locate(Source source, Expression pattern, Expression src, Expression start) {
|
||||
super(source, start != null ? Arrays.asList(pattern, src, start) : Arrays.asList(pattern, src));
|
||||
public Locate(Source source, Expression pattern, Expression input, Expression start) {
|
||||
super(source, start != null ? Arrays.asList(pattern, input, start) : Arrays.asList(pattern, input));
|
||||
this.pattern = pattern;
|
||||
this.source = src;
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ public class Locate extends ScalarFunction implements OptionalArgument {
|
||||
return patternResolution;
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.SECOND);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.SECOND);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -70,54 +70,54 @@ public class Locate extends ScalarFunction implements OptionalArgument {
|
||||
protected Pipe makePipe() {
|
||||
return new LocateFunctionPipe(source(), this,
|
||||
Expressions.pipe(pattern),
|
||||
Expressions.pipe(source),
|
||||
Expressions.pipe(input),
|
||||
start == null ? null : Expressions.pipe(start));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Locate::new, pattern, source, start);
|
||||
return NodeInfo.create(this, Locate::new, pattern, input, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return pattern.foldable()
|
||||
&& source.foldable()
|
||||
&& input.foldable()
|
||||
&& (start == null || start.foldable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(pattern.fold(), source.fold(), (start == null ? null : start.fold()));
|
||||
return doProcess(pattern.fold(), input.fold(), (start == null ? null : start.fold()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate patternScript = asScript(pattern);
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate startScript = start == null ? null : asScript(start);
|
||||
|
||||
return asScriptFrom(patternScript, sourceScript, startScript);
|
||||
return asScriptFrom(patternScript, inputScript, startScript);
|
||||
}
|
||||
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate patternScript, ScriptTemplate sourceScript, ScriptTemplate startScript) {
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate patternScript, ScriptTemplate inputScript, ScriptTemplate startScript) {
|
||||
if (start == null) {
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"),
|
||||
"locate",
|
||||
patternScript.template(),
|
||||
sourceScript.template()),
|
||||
inputScript.template()),
|
||||
paramsBuilder()
|
||||
.script(patternScript.params()).script(sourceScript.params())
|
||||
.script(patternScript.params()).script(inputScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
// basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2,...)
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s,%s)"),
|
||||
"locate",
|
||||
patternScript.template(),
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
startScript.template()),
|
||||
paramsBuilder()
|
||||
.script(patternScript.params()).script(sourceScript.params())
|
||||
.script(patternScript.params()).script(inputScript.params())
|
||||
.script(startScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
@ -17,13 +17,12 @@ import java.util.Objects;
|
||||
|
||||
public class LocateFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe pattern, source, start;
|
||||
private final Pipe pattern, input, start;
|
||||
|
||||
public LocateFunctionPipe(Source source, Expression expression, Pipe pattern,
|
||||
Pipe src, Pipe start) {
|
||||
super(source, expression, start == null ? Arrays.asList(pattern, src) : Arrays.asList(pattern, src, start));
|
||||
public LocateFunctionPipe(Source source, Expression expression, Pipe pattern, Pipe input, Pipe start) {
|
||||
super(source, expression, start == null ? Arrays.asList(pattern, input) : Arrays.asList(pattern, input, start));
|
||||
this.pattern = pattern;
|
||||
this.source = src;
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
@ -39,34 +38,33 @@ public class LocateFunctionPipe extends Pipe {
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newPattern = pattern.resolveAttributes(resolver);
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newStart = start == null ? start : start.resolveAttributes(resolver);
|
||||
if (newPattern == pattern && newSource == source && newStart == start) {
|
||||
if (newPattern == pattern && newInput == input && newStart == start) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newPattern, newSource, newStart);
|
||||
return replaceChildren(newPattern, newInput, newStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return pattern.supportedByAggsOnlyQuery() && source.supportedByAggsOnlyQuery()
|
||||
return pattern.supportedByAggsOnlyQuery() && input.supportedByAggsOnlyQuery()
|
||||
&& (start == null || start.supportedByAggsOnlyQuery());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return pattern.resolved() && source.resolved() && (start == null || start.resolved());
|
||||
return pattern.resolved() && input.resolved() && (start == null || start.resolved());
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newPattern, Pipe newSource,
|
||||
Pipe newStart) {
|
||||
return new LocateFunctionPipe(source(), expression(), newPattern, newSource, newStart);
|
||||
protected Pipe replaceChildren(Pipe newPattern, Pipe newInput, Pipe newStart) {
|
||||
return new LocateFunctionPipe(source(), expression(), newPattern, newInput, newStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
pattern.collectFields(sourceBuilder);
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
if (start != null) {
|
||||
start.collectFields(sourceBuilder);
|
||||
}
|
||||
@ -74,16 +72,16 @@ public class LocateFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
protected NodeInfo<LocateFunctionPipe> info() {
|
||||
return NodeInfo.create(this, LocateFunctionPipe::new, expression(), pattern, source, start);
|
||||
return NodeInfo.create(this, LocateFunctionPipe::new, expression(), pattern, input, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocateFunctionProcessor asProcessor() {
|
||||
return new LocateFunctionProcessor(pattern.asProcessor(), source.asProcessor(), start == null ? null : start.asProcessor());
|
||||
return new LocateFunctionProcessor(pattern.asProcessor(), input.asProcessor(), start == null ? null : start.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe start() {
|
||||
@ -96,7 +94,7 @@ public class LocateFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pattern, source, start);
|
||||
return Objects.hash(pattern, input, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,6 +108,6 @@ public class LocateFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
LocateFunctionPipe other = (LocateFunctionPipe) obj;
|
||||
return Objects.equals(pattern, other.pattern) && Objects.equals(source, other.source) && Objects.equals(start, other.start);
|
||||
return Objects.equals(pattern, other.pattern) && Objects.equals(input, other.input) && Objects.equals(start, other.start);
|
||||
}
|
||||
}
|
@ -15,39 +15,39 @@ import java.util.Objects;
|
||||
|
||||
public class LocateFunctionProcessor implements Processor {
|
||||
|
||||
private final Processor pattern, source, start;
|
||||
private final Processor pattern, input, start;
|
||||
public static final String NAME = "sloc";
|
||||
|
||||
public LocateFunctionProcessor(Processor pattern, Processor source, Processor start) {
|
||||
public LocateFunctionProcessor(Processor pattern, Processor input, Processor start) {
|
||||
this.pattern = pattern;
|
||||
this.source = source;
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public LocateFunctionProcessor(StreamInput in) throws IOException {
|
||||
pattern = in.readNamedWriteable(Processor.class);
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
start = in.readOptionalNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(pattern);
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeOptionalNamedWriteable(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(pattern().process(input), source().process(input), start() == null ? null : start().process(input));
|
||||
return doProcess(pattern().process(input), input().process(input), start() == null ? null : start().process(input));
|
||||
}
|
||||
|
||||
public static Integer doProcess(Object pattern, Object source, Object start) {
|
||||
if (source == null) {
|
||||
public static Integer doProcess(Object pattern, Object input, Object start) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(source instanceof String || source instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (!(input instanceof String || input instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (pattern == null) {
|
||||
return 0;
|
||||
@ -60,12 +60,12 @@ public class LocateFunctionProcessor implements Processor {
|
||||
throw new SqlIllegalArgumentException("A number is required; received [{}]", start);
|
||||
}
|
||||
|
||||
String stringSource = source instanceof Character ? source.toString() : (String) source;
|
||||
String stringInput = input instanceof Character ? input.toString() : (String) input;
|
||||
String stringPattern = pattern instanceof Character ? pattern.toString() : (String) pattern;
|
||||
|
||||
return Integer.valueOf(1 + (start != null ?
|
||||
stringSource.indexOf(stringPattern, ((Number) start).intValue() - 1)
|
||||
: stringSource.indexOf(stringPattern)));
|
||||
stringInput.indexOf(stringPattern, ((Number) start).intValue() - 1)
|
||||
: stringInput.indexOf(stringPattern)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,21 +80,21 @@ public class LocateFunctionProcessor implements Processor {
|
||||
|
||||
LocateFunctionProcessor other = (LocateFunctionProcessor) obj;
|
||||
return Objects.equals(pattern(), other.pattern())
|
||||
&& Objects.equals(source(), other.source())
|
||||
&& Objects.equals(input(), other.input())
|
||||
&& Objects.equals(start(), other.start());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pattern(), source(), start());
|
||||
return Objects.hash(pattern(), input(), start());
|
||||
}
|
||||
|
||||
public Processor pattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public Processor source() {
|
||||
return source;
|
||||
public Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Processor start() {
|
||||
|
@ -32,11 +32,11 @@ import static org.elasticsearch.xpack.sql.expression.function.scalar.string.Repl
|
||||
*/
|
||||
public class Replace extends ScalarFunction {
|
||||
|
||||
private final Expression source, pattern, replacement;
|
||||
private final Expression input, pattern, replacement;
|
||||
|
||||
public Replace(Source source, Expression src, Expression pattern, Expression replacement) {
|
||||
super(source, Arrays.asList(src, pattern, replacement));
|
||||
this.source = src;
|
||||
public Replace(Source source, Expression input, Expression pattern, Expression replacement) {
|
||||
super(source, Arrays.asList(input, pattern, replacement));
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class Replace extends ScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -63,46 +63,46 @@ public class Replace extends ScalarFunction {
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new ReplaceFunctionPipe(source(), this,
|
||||
Expressions.pipe(source),
|
||||
Expressions.pipe(input),
|
||||
Expressions.pipe(pattern),
|
||||
Expressions.pipe(replacement));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Replace::new, source, pattern, replacement);
|
||||
return NodeInfo.create(this, Replace::new, input, pattern, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable()
|
||||
return input.foldable()
|
||||
&& pattern.foldable()
|
||||
&& replacement.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), pattern.fold(), replacement.fold());
|
||||
return doProcess(input.fold(), pattern.fold(), replacement.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate patternScript = asScript(pattern);
|
||||
ScriptTemplate replacementScript = asScript(replacement);
|
||||
|
||||
return asScriptFrom(sourceScript, patternScript, replacementScript);
|
||||
return asScriptFrom(inputScript, patternScript, replacementScript);
|
||||
}
|
||||
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate patternScript, ScriptTemplate replacementScript) {
|
||||
private ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate patternScript, ScriptTemplate replacementScript) {
|
||||
// basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2,...)
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s,%s)"),
|
||||
"replace",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
patternScript.template(),
|
||||
replacementScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params()).script(patternScript.params())
|
||||
.script(inputScript.params()).script(patternScript.params())
|
||||
.script(replacementScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
@ -17,12 +17,11 @@ import java.util.Objects;
|
||||
|
||||
public class ReplaceFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, pattern, replacement;
|
||||
private final Pipe input, pattern, replacement;
|
||||
|
||||
public ReplaceFunctionPipe(Source source, Expression expression, Pipe src,
|
||||
Pipe pattern, Pipe replacement) {
|
||||
super(source, expression, Arrays.asList(src, pattern, replacement));
|
||||
this.source = src;
|
||||
public ReplaceFunctionPipe(Source source, Expression expression, Pipe input, Pipe pattern, Pipe replacement) {
|
||||
super(source, expression, Arrays.asList(input, pattern, replacement));
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
@ -37,49 +36,48 @@ public class ReplaceFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newPattern = pattern.resolveAttributes(resolver);
|
||||
Pipe newReplacement = replacement.resolveAttributes(resolver);
|
||||
if (newSource == source && newPattern == pattern && newReplacement == replacement) {
|
||||
if (newInput == input && newPattern == pattern && newReplacement == replacement) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newPattern, newReplacement);
|
||||
return replaceChildren(newInput, newPattern, newReplacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery() && replacement.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && pattern.supportedByAggsOnlyQuery() && replacement.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && pattern.resolved() && replacement.resolved();
|
||||
return input.resolved() && pattern.resolved() && replacement.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newPattern,
|
||||
Pipe newReplacement) {
|
||||
return new ReplaceFunctionPipe(source(), expression(), newSource, newPattern, newReplacement);
|
||||
protected Pipe replaceChildren(Pipe newInput, Pipe newPattern, Pipe newReplacement) {
|
||||
return new ReplaceFunctionPipe(source(), expression(), newInput, newPattern, newReplacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
pattern.collectFields(sourceBuilder);
|
||||
replacement.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<ReplaceFunctionPipe> info() {
|
||||
return NodeInfo.create(this, ReplaceFunctionPipe::new, expression(), source, pattern, replacement);
|
||||
return NodeInfo.create(this, ReplaceFunctionPipe::new, expression(), input, pattern, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplaceFunctionProcessor asProcessor() {
|
||||
return new ReplaceFunctionProcessor(source.asProcessor(), pattern.asProcessor(), replacement.asProcessor());
|
||||
return new ReplaceFunctionProcessor(input.asProcessor(), pattern.asProcessor(), replacement.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe pattern() {
|
||||
@ -92,7 +90,7 @@ public class ReplaceFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, pattern, replacement);
|
||||
return Objects.hash(input, pattern, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,7 +104,7 @@ public class ReplaceFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
ReplaceFunctionPipe other = (ReplaceFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source)
|
||||
return Objects.equals(input, other.input)
|
||||
&& Objects.equals(pattern, other.pattern)
|
||||
&& Objects.equals(replacement, other.replacement);
|
||||
}
|
||||
|
@ -16,42 +16,42 @@ import java.util.Objects;
|
||||
|
||||
public class ReplaceFunctionProcessor implements Processor {
|
||||
|
||||
private final Processor source, pattern, replacement;
|
||||
private final Processor input, pattern, replacement;
|
||||
public static final String NAME = "srep";
|
||||
|
||||
public ReplaceFunctionProcessor(Processor source, Processor pattern, Processor replacement) {
|
||||
this.source = source;
|
||||
public ReplaceFunctionProcessor(Processor input, Processor pattern, Processor replacement) {
|
||||
this.input = input;
|
||||
this.pattern = pattern;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
|
||||
public ReplaceFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
pattern = in.readNamedWriteable(Processor.class);
|
||||
replacement = in.readNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(pattern);
|
||||
out.writeNamedWriteable(replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source().process(input), pattern().process(input), replacement().process(input));
|
||||
return doProcess(input().process(input), pattern().process(input), replacement().process(input));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object pattern, Object replacement) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object pattern, Object replacement) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(source instanceof String || source instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (!(input instanceof String || input instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (pattern == null || replacement == null) {
|
||||
return source;
|
||||
return input;
|
||||
}
|
||||
if (!(pattern instanceof String || pattern instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", pattern);
|
||||
@ -60,7 +60,7 @@ public class ReplaceFunctionProcessor implements Processor {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", replacement);
|
||||
}
|
||||
|
||||
return Strings.replace(source instanceof Character ? source.toString() : (String)source,
|
||||
return Strings.replace(input instanceof Character ? input.toString() : (String) input,
|
||||
pattern instanceof Character ? pattern.toString() : (String) pattern,
|
||||
replacement instanceof Character ? replacement.toString() : (String) replacement);
|
||||
}
|
||||
@ -76,18 +76,18 @@ public class ReplaceFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
ReplaceFunctionProcessor other = (ReplaceFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(pattern(), other.pattern())
|
||||
&& Objects.equals(replacement(), other.replacement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), pattern(), replacement());
|
||||
return Objects.hash(input(), pattern(), replacement());
|
||||
}
|
||||
|
||||
public Processor source() {
|
||||
return source;
|
||||
public Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Processor pattern() {
|
||||
|
@ -33,11 +33,11 @@ import static org.elasticsearch.xpack.sql.expression.function.scalar.string.Subs
|
||||
*/
|
||||
public class Substring extends ScalarFunction {
|
||||
|
||||
private final Expression source, start, length;
|
||||
private final Expression input, start, length;
|
||||
|
||||
public Substring(Source source, Expression src, Expression start, Expression length) {
|
||||
super(source, Arrays.asList(src, start, length));
|
||||
this.source = src;
|
||||
public Substring(Source source, Expression input, Expression start, Expression length) {
|
||||
super(source, Arrays.asList(input, start, length));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
}
|
||||
@ -48,7 +48,7 @@ public class Substring extends ScalarFunction {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
TypeResolution sourceResolution = isStringAndExact(source, sourceText(), ParamOrdinal.FIRST);
|
||||
TypeResolution sourceResolution = isStringAndExact(input, sourceText(), ParamOrdinal.FIRST);
|
||||
if (sourceResolution.unresolved()) {
|
||||
return sourceResolution;
|
||||
}
|
||||
@ -63,46 +63,43 @@ public class Substring extends ScalarFunction {
|
||||
|
||||
@Override
|
||||
protected Pipe makePipe() {
|
||||
return new SubstringFunctionPipe(source(), this,
|
||||
Expressions.pipe(source),
|
||||
Expressions.pipe(start),
|
||||
Expressions.pipe(length));
|
||||
return new SubstringFunctionPipe(source(), this, Expressions.pipe(input), Expressions.pipe(start), Expressions.pipe(length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return source.foldable() && start.foldable() && length.foldable();
|
||||
return input.foldable() && start.foldable() && length.foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return doProcess(source.fold(), start.fold(), length.fold());
|
||||
return doProcess(input.fold(), start.fold(), length.fold());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, Substring::new, source, start, length);
|
||||
return NodeInfo.create(this, Substring::new, input, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptTemplate asScript() {
|
||||
ScriptTemplate sourceScript = asScript(source);
|
||||
ScriptTemplate inputScript = asScript(input);
|
||||
ScriptTemplate startScript = asScript(start);
|
||||
ScriptTemplate lengthScript = asScript(length);
|
||||
|
||||
return asScriptFrom(sourceScript, startScript, lengthScript);
|
||||
return asScriptFrom(inputScript, startScript, lengthScript);
|
||||
}
|
||||
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate sourceScript, ScriptTemplate startScript,
|
||||
protected ScriptTemplate asScriptFrom(ScriptTemplate inputScript, ScriptTemplate startScript,
|
||||
ScriptTemplate lengthScript) {
|
||||
// basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2,...)
|
||||
return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s,%s)"),
|
||||
"substring",
|
||||
sourceScript.template(),
|
||||
inputScript.template(),
|
||||
startScript.template(),
|
||||
lengthScript.template()),
|
||||
paramsBuilder()
|
||||
.script(sourceScript.params()).script(startScript.params())
|
||||
.script(inputScript.params()).script(startScript.params())
|
||||
.script(lengthScript.params())
|
||||
.build(), dataType());
|
||||
}
|
||||
|
@ -17,12 +17,11 @@ import java.util.Objects;
|
||||
|
||||
public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
private final Pipe source, start, length;
|
||||
private final Pipe input, start, length;
|
||||
|
||||
public SubstringFunctionPipe(Source source, Expression expression, Pipe src,
|
||||
Pipe start, Pipe length) {
|
||||
super(source, expression, Arrays.asList(src, start, length));
|
||||
this.source = src;
|
||||
public SubstringFunctionPipe(Source source, Expression expression, Pipe input, Pipe start, Pipe length) {
|
||||
super(source, expression, Arrays.asList(input, start, length));
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
}
|
||||
@ -37,49 +36,48 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public final Pipe resolveAttributes(AttributeResolver resolver) {
|
||||
Pipe newSource = source.resolveAttributes(resolver);
|
||||
Pipe newInput = input.resolveAttributes(resolver);
|
||||
Pipe newStart = start.resolveAttributes(resolver);
|
||||
Pipe newLength = length.resolveAttributes(resolver);
|
||||
if (newSource == source && newStart == start && newLength == length) {
|
||||
if (newInput == input && newStart == start && newLength == length) {
|
||||
return this;
|
||||
}
|
||||
return replaceChildren(newSource, newStart, newLength);
|
||||
return replaceChildren(newInput, newStart, newLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportedByAggsOnlyQuery() {
|
||||
return source.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery() && length.supportedByAggsOnlyQuery();
|
||||
return input.supportedByAggsOnlyQuery() && start.supportedByAggsOnlyQuery() && length.supportedByAggsOnlyQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolved() {
|
||||
return source.resolved() && start.resolved() && length.resolved();
|
||||
return input.resolved() && start.resolved() && length.resolved();
|
||||
}
|
||||
|
||||
protected Pipe replaceChildren(Pipe newSource, Pipe newStart,
|
||||
Pipe newLength) {
|
||||
return new SubstringFunctionPipe(source(), expression(), newSource, newStart, newLength);
|
||||
protected SubstringFunctionPipe replaceChildren(Pipe newInput, Pipe newStart, Pipe newLength) {
|
||||
return new SubstringFunctionPipe(source(), expression(), newInput, newStart, newLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collectFields(QlSourceBuilder sourceBuilder) {
|
||||
source.collectFields(sourceBuilder);
|
||||
input.collectFields(sourceBuilder);
|
||||
start.collectFields(sourceBuilder);
|
||||
length.collectFields(sourceBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<SubstringFunctionPipe> info() {
|
||||
return NodeInfo.create(this, SubstringFunctionPipe::new, expression(), source, start, length);
|
||||
return NodeInfo.create(this, SubstringFunctionPipe::new, expression(), input, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubstringFunctionProcessor asProcessor() {
|
||||
return new SubstringFunctionProcessor(source.asProcessor(), start.asProcessor(), length.asProcessor());
|
||||
return new SubstringFunctionProcessor(input.asProcessor(), start.asProcessor(), length.asProcessor());
|
||||
}
|
||||
|
||||
public Pipe src() {
|
||||
return source;
|
||||
public Pipe input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Pipe start() {
|
||||
@ -92,7 +90,7 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, start, length);
|
||||
return Objects.hash(input, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,6 +104,6 @@ public class SubstringFunctionPipe extends Pipe {
|
||||
}
|
||||
|
||||
SubstringFunctionPipe other = (SubstringFunctionPipe) obj;
|
||||
return Objects.equals(source, other.source) && Objects.equals(start, other.start) && Objects.equals(length, other.length);
|
||||
return Objects.equals(input, other.input) && Objects.equals(start, other.start) && Objects.equals(length, other.length);
|
||||
}
|
||||
}
|
||||
|
@ -17,41 +17,41 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
|
||||
public static final String NAME = "ssub";
|
||||
|
||||
private final Processor source, start, length;
|
||||
private final Processor input, start, length;
|
||||
|
||||
public SubstringFunctionProcessor(Processor source, Processor start, Processor length) {
|
||||
this.source = source;
|
||||
public SubstringFunctionProcessor(Processor input, Processor start, Processor length) {
|
||||
this.input = input;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public SubstringFunctionProcessor(StreamInput in) throws IOException {
|
||||
source = in.readNamedWriteable(Processor.class);
|
||||
input = in.readNamedWriteable(Processor.class);
|
||||
start = in.readNamedWriteable(Processor.class);
|
||||
length = in.readNamedWriteable(Processor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeNamedWriteable(source);
|
||||
out.writeNamedWriteable(input);
|
||||
out.writeNamedWriteable(start);
|
||||
out.writeNamedWriteable(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object process(Object input) {
|
||||
return doProcess(source.process(input), start.process(input), length.process(input));
|
||||
public Object process(Object o) {
|
||||
return doProcess(input.process(o), start.process(o), length.process(o));
|
||||
}
|
||||
|
||||
public static Object doProcess(Object source, Object start, Object length) {
|
||||
if (source == null) {
|
||||
public static Object doProcess(Object input, Object start, Object length) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(source instanceof String || source instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", source);
|
||||
if (!(input instanceof String || input instanceof Character)) {
|
||||
throw new SqlIllegalArgumentException("A string/char is required; received [{}]", input);
|
||||
}
|
||||
if (start == null || length == null) {
|
||||
return source;
|
||||
return input;
|
||||
}
|
||||
if (!(start instanceof Number)) {
|
||||
throw new SqlIllegalArgumentException("A number is required; received [{}]", start);
|
||||
@ -63,13 +63,13 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
throw new SqlIllegalArgumentException("A positive number is required for [length]; received [{}]", length);
|
||||
}
|
||||
|
||||
return StringFunctionUtils.substring(source instanceof Character ? source.toString() : (String) source,
|
||||
return StringFunctionUtils.substring(input instanceof Character ? input.toString() : (String) input,
|
||||
((Number) start).intValue() - 1, // SQL is 1-based when it comes to string manipulation
|
||||
((Number) length).intValue());
|
||||
}
|
||||
|
||||
protected Processor source() {
|
||||
return source;
|
||||
protected Processor input() {
|
||||
return input;
|
||||
}
|
||||
|
||||
protected Processor start() {
|
||||
@ -91,14 +91,14 @@ public class SubstringFunctionProcessor implements Processor {
|
||||
}
|
||||
|
||||
SubstringFunctionProcessor other = (SubstringFunctionProcessor) obj;
|
||||
return Objects.equals(source(), other.source())
|
||||
return Objects.equals(input(), other.input())
|
||||
&& Objects.equals(start(), other.start())
|
||||
&& Objects.equals(length(), other.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source(), start(), length());
|
||||
return Objects.hash(input(), start(), length());
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,8 +68,8 @@ public class ConcatFunctionPipeTests extends AbstractNodeTestCase<ConcatFunction
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
ConcatFunctionPipe b = randomInstance();
|
||||
Pipe newLeft = pipe(((Expression) randomValueOtherThan(b.left(), () -> randomStringLiteral())));
|
||||
Pipe newRight = pipe(((Expression) randomValueOtherThan(b.right(), () -> randomStringLiteral())));
|
||||
Pipe newLeft = randomValueOtherThan(b.left(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newRight = randomValueOtherThan(b.right(), () -> pipe(randomStringLiteral()));
|
||||
ConcatFunctionPipe newB =
|
||||
new ConcatFunctionPipe(b.source(), b.expression(), b.left(), b.right());
|
||||
BinaryPipe transformed = newB.replaceChildren(newLeft, b.right());
|
||||
@ -97,16 +97,16 @@ public class ConcatFunctionPipeTests extends AbstractNodeTestCase<ConcatFunction
|
||||
List<Function<ConcatFunctionPipe, ConcatFunctionPipe>> randoms = new ArrayList<>();
|
||||
randoms.add(f -> new ConcatFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.left(), () -> randomStringLiteral()))),
|
||||
randomValueOtherThan(f.left(), () -> pipe(randomStringLiteral())),
|
||||
f.right()));
|
||||
randoms.add(f -> new ConcatFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
f.left(),
|
||||
pipe(((Expression) randomValueOtherThan(f.right(), () -> randomStringLiteral())))));
|
||||
randomValueOtherThan(f.right(), () -> pipe(randomStringLiteral()))));
|
||||
randoms.add(f -> new ConcatFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
pipe(((Expression) randomValueOtherThan(f.left(), () -> randomStringLiteral()))),
|
||||
pipe(((Expression) randomValueOtherThan(f.right(), () -> randomStringLiteral())))));
|
||||
randomValueOtherThan(f.left(), () -> pipe(randomStringLiteral())),
|
||||
randomValueOtherThan(f.right(), () -> pipe(randomStringLiteral()))));
|
||||
|
||||
return randomFrom(randoms).apply(instance);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class InsertFunctionPipeTests extends AbstractNodeTestCase<InsertFunction
|
||||
InsertFunctionPipe newB = new InsertFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.src(),
|
||||
b1.input(),
|
||||
b1.start(),
|
||||
b1.length(),
|
||||
b1.replacement());
|
||||
@ -63,7 +63,7 @@ public class InsertFunctionPipeTests extends AbstractNodeTestCase<InsertFunction
|
||||
newB = new InsertFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.src(),
|
||||
b2.input(),
|
||||
b2.start(),
|
||||
b2.length(),
|
||||
b2.replacement());
|
||||
@ -74,23 +74,23 @@ public class InsertFunctionPipeTests extends AbstractNodeTestCase<InsertFunction
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
InsertFunctionPipe b = randomInstance();
|
||||
Pipe newSource = pipe(((Expression) randomValueOtherThan(b.source(), () -> randomStringLiteral())));
|
||||
Pipe newStart = pipe(((Expression) randomValueOtherThan(b.start(), () -> randomIntLiteral())));
|
||||
Pipe newLength = pipe(((Expression) randomValueOtherThan(b.length(), () -> randomIntLiteral())));
|
||||
Pipe newR = pipe(((Expression) randomValueOtherThan(b.replacement(), () -> randomStringLiteral())));
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newStart = randomValueOtherThan(b.start(), () -> pipe(randomIntLiteral()));
|
||||
Pipe newLength = randomValueOtherThan(b.length(), () -> pipe(randomIntLiteral()));
|
||||
Pipe newR = randomValueOtherThan(b.replacement(), () -> pipe(randomStringLiteral()));
|
||||
InsertFunctionPipe newB =
|
||||
new InsertFunctionPipe(b.source(), b.expression(), b.src(), b.start(), b.length(), b.replacement());
|
||||
new InsertFunctionPipe(b.source(), b.expression(), b.input(), b.start(), b.length(), b.replacement());
|
||||
InsertFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 5; i++) {
|
||||
for(BitSet comb : new Combinations(4, i)) {
|
||||
transformed = (InsertFunctionPipe) newB.replaceChildren(
|
||||
comb.get(0) ? newSource : b.src(),
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newStart : b.start(),
|
||||
comb.get(2) ? newLength : b.length(),
|
||||
comb.get(3) ? newR : b.replacement());
|
||||
assertEquals(transformed.src(), comb.get(0) ? newSource : b.src());
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.start(), comb.get(1) ? newStart : b.start());
|
||||
assertEquals(transformed.length(), comb.get(2) ? newLength : b.length());
|
||||
assertEquals(transformed.replacement(), comb.get(3) ? newR : b.replacement());
|
||||
@ -109,14 +109,10 @@ public class InsertFunctionPipeTests extends AbstractNodeTestCase<InsertFunction
|
||||
randoms.add(f -> new InsertFunctionPipe(
|
||||
f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.source(),
|
||||
() -> randomStringLiteral()))) : f.src(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.start(),
|
||||
() -> randomIntLiteral()))) : f.start(),
|
||||
comb.get(2) ? pipe(((Expression) randomValueOtherThan(f.length(),
|
||||
() -> randomIntLiteral()))): f.length(),
|
||||
comb.get(3) ? pipe(((Expression) randomValueOtherThan(f.replacement(),
|
||||
() -> randomStringLiteral()))) : f.replacement()));
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start(),
|
||||
comb.get(2) ? randomValueOtherThan(f.length(), () -> pipe(randomIntLiteral())): f.length(),
|
||||
comb.get(3) ? randomValueOtherThan(f.replacement(), () -> pipe(randomStringLiteral())) : f.replacement()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +123,7 @@ public class InsertFunctionPipeTests extends AbstractNodeTestCase<InsertFunction
|
||||
protected InsertFunctionPipe copy(InsertFunctionPipe instance) {
|
||||
return new InsertFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.src(),
|
||||
instance.input(),
|
||||
instance.start(),
|
||||
instance.length(),
|
||||
instance.replacement());
|
||||
|
@ -52,7 +52,7 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.pattern(),
|
||||
b1.src(),
|
||||
b1.input(),
|
||||
b1.start());
|
||||
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
@ -63,7 +63,7 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.pattern(),
|
||||
b2.src(),
|
||||
b2.input(),
|
||||
b2.start());
|
||||
|
||||
assertEquals(newB,
|
||||
@ -73,11 +73,11 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
LocateFunctionPipe b = randomInstance();
|
||||
Pipe newPattern = pipe(((Expression) randomValueOtherThan(b.pattern(), () -> randomStringLiteral())));
|
||||
Pipe newSource = pipe(((Expression) randomValueOtherThan(b.source(), () -> randomStringLiteral())));
|
||||
Pipe newStart = b.start() == null ? null : pipe(((Expression) randomValueOtherThan(b.start(), () -> randomIntLiteral())));
|
||||
Pipe newPattern = randomValueOtherThan(b.pattern(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newStart = b.start() == null ? null : randomValueOtherThan(b.start(), () -> pipe(randomIntLiteral()));
|
||||
|
||||
LocateFunctionPipe newB = new LocateFunctionPipe(b.source(), b.expression(), b.pattern(), b.src(), b.start());
|
||||
LocateFunctionPipe newB = new LocateFunctionPipe(b.source(), b.expression(), b.pattern(), b.input(), b.start());
|
||||
LocateFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
@ -86,11 +86,11 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
Pipe tempNewStart = b.start() == null ? b.start() : (comb.get(2) ? newStart : b.start());
|
||||
transformed = (LocateFunctionPipe) newB.replaceChildren(
|
||||
comb.get(0) ? newPattern : b.pattern(),
|
||||
comb.get(1) ? newSource : b.src(),
|
||||
comb.get(1) ? newInput : b.input(),
|
||||
tempNewStart);
|
||||
|
||||
assertEquals(transformed.pattern(), comb.get(0) ? newPattern : b.pattern());
|
||||
assertEquals(transformed.src(), comb.get(1) ? newSource : b.src());
|
||||
assertEquals(transformed.input(), comb.get(1) ? newInput : b.input());
|
||||
assertEquals(transformed.start(), tempNewStart);
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
assertEquals(transformed.source(), b.source());
|
||||
@ -106,11 +106,9 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
for(BitSet comb : new Combinations(2, i)) {
|
||||
randoms.add(f -> new LocateFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.pattern(),
|
||||
() -> randomStringLiteral()))) : f.pattern(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.src(),
|
||||
() -> randomStringLiteral()))) : f.src(),
|
||||
null));
|
||||
comb.get(0) ? randomValueOtherThan(f.pattern(), () -> pipe(randomStringLiteral())) : f.pattern(),
|
||||
comb.get(1) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
null));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -118,12 +116,9 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
randoms.add(f -> new LocateFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.pattern(),
|
||||
() -> randomStringLiteral()))) : f.pattern(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.src(),
|
||||
() -> randomStringLiteral()))) : f.src(),
|
||||
comb.get(2) ? pipe(((Expression) randomValueOtherThan(f.start(),
|
||||
() -> randomIntLiteral()))) : f.start()));
|
||||
comb.get(0) ? randomValueOtherThan(f.pattern(), () -> pipe(randomStringLiteral())) : f.pattern(),
|
||||
comb.get(1) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(2) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +131,7 @@ public class LocateFunctionPipeTests extends AbstractNodeTestCase<LocateFunction
|
||||
return new LocateFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.pattern(),
|
||||
instance.src(),
|
||||
instance.input(),
|
||||
instance.start());
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@ public class ReplaceFunctionPipeTests extends AbstractNodeTestCase<ReplaceFuncti
|
||||
ReplaceFunctionPipe newB = new ReplaceFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.src(),
|
||||
b1.input(),
|
||||
b1.pattern(),
|
||||
b1.replacement());
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
@ -61,7 +61,7 @@ public class ReplaceFunctionPipeTests extends AbstractNodeTestCase<ReplaceFuncti
|
||||
newB = new ReplaceFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.src(),
|
||||
b2.input(),
|
||||
b2.pattern(),
|
||||
b2.replacement());
|
||||
assertEquals(newB,
|
||||
@ -71,22 +71,21 @@ public class ReplaceFunctionPipeTests extends AbstractNodeTestCase<ReplaceFuncti
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
ReplaceFunctionPipe b = randomInstance();
|
||||
Pipe newSource = pipe(((Expression) randomValueOtherThan(b.source(), () -> randomStringLiteral())));
|
||||
Pipe newPattern = pipe(((Expression) randomValueOtherThan(b.pattern(), () -> randomStringLiteral())));
|
||||
Pipe newR = pipe(((Expression) randomValueOtherThan(b.replacement(), () -> randomStringLiteral())));
|
||||
ReplaceFunctionPipe newB =
|
||||
new ReplaceFunctionPipe(b.source(), b.expression(), b.src(), b.pattern(), b.replacement());
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newPattern = randomValueOtherThan(b.pattern(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newR = randomValueOtherThan(b.replacement(), () -> pipe(randomStringLiteral()));
|
||||
ReplaceFunctionPipe newB = new ReplaceFunctionPipe(b.source(), b.expression(), b.input(), b.pattern(), b.replacement());
|
||||
ReplaceFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
transformed = (ReplaceFunctionPipe) newB.replaceChildren(
|
||||
comb.get(0) ? newSource : b.src(),
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newPattern : b.pattern(),
|
||||
comb.get(2) ? newR : b.replacement());
|
||||
|
||||
assertEquals(transformed.src(), comb.get(0) ? newSource : b.src());
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.pattern(), comb.get(1) ? newPattern : b.pattern());
|
||||
assertEquals(transformed.replacement(), comb.get(2) ? newR : b.replacement());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
@ -103,12 +102,9 @@ public class ReplaceFunctionPipeTests extends AbstractNodeTestCase<ReplaceFuncti
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
randoms.add(f -> new ReplaceFunctionPipe(f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.src(),
|
||||
() -> randomStringLiteral()))) : f.src(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.pattern(),
|
||||
() -> randomStringLiteral()))) : f.pattern(),
|
||||
comb.get(2) ? pipe(((Expression) randomValueOtherThan(f.replacement(),
|
||||
() -> randomStringLiteral()))) : f.replacement()));
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.pattern(), () -> pipe(randomStringLiteral())) : f.pattern(),
|
||||
comb.get(2) ? randomValueOtherThan(f.replacement(), () -> pipe(randomStringLiteral())) : f.replacement()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +115,7 @@ public class ReplaceFunctionPipeTests extends AbstractNodeTestCase<ReplaceFuncti
|
||||
protected ReplaceFunctionPipe copy(ReplaceFunctionPipe instance) {
|
||||
return new ReplaceFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.src(),
|
||||
instance.input(),
|
||||
instance.pattern(),
|
||||
instance.replacement());
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class SubstringFunctionPipeTests
|
||||
SubstringFunctionPipe newB = new SubstringFunctionPipe(
|
||||
b1.source(),
|
||||
newExpression,
|
||||
b1.src(),
|
||||
b1.input(),
|
||||
b1.start(),
|
||||
b1.length());
|
||||
assertEquals(newB, b1.transformPropertiesOnly(v -> Objects.equals(v, b1.expression()) ? newExpression : v, Expression.class));
|
||||
@ -62,7 +62,7 @@ public class SubstringFunctionPipeTests
|
||||
newB = new SubstringFunctionPipe(
|
||||
newLoc,
|
||||
b2.expression(),
|
||||
b2.src(),
|
||||
b2.input(),
|
||||
b2.start(),
|
||||
b2.length());
|
||||
assertEquals(newB,
|
||||
@ -72,21 +72,20 @@ public class SubstringFunctionPipeTests
|
||||
@Override
|
||||
public void testReplaceChildren() {
|
||||
SubstringFunctionPipe b = randomInstance();
|
||||
Pipe newSource = pipe(((Expression) randomValueOtherThan(b.source(), () -> randomStringLiteral())));
|
||||
Pipe newStart = pipe(((Expression) randomValueOtherThan(b.start(), () -> randomIntLiteral())));
|
||||
Pipe newLength = pipe(((Expression) randomValueOtherThan(b.length(), () -> randomIntLiteral())));
|
||||
SubstringFunctionPipe newB =
|
||||
new SubstringFunctionPipe(b.source(), b.expression(), b.src(), b.start(), b.length());
|
||||
Pipe newInput = randomValueOtherThan(b.input(), () -> pipe(randomStringLiteral()));
|
||||
Pipe newStart = randomValueOtherThan(b.start(), () -> pipe(randomIntLiteral()));
|
||||
Pipe newLength = randomValueOtherThan(b.length(), () -> pipe(randomIntLiteral()));
|
||||
SubstringFunctionPipe newB = new SubstringFunctionPipe(b.source(), b.expression(), b.input(), b.start(), b.length());
|
||||
SubstringFunctionPipe transformed = null;
|
||||
|
||||
// generate all the combinations of possible children modifications and test all of them
|
||||
for(int i = 1; i < 4; i++) {
|
||||
for(BitSet comb : new Combinations(3, i)) {
|
||||
transformed = (SubstringFunctionPipe) newB.replaceChildren(
|
||||
comb.get(0) ? newSource : b.src(),
|
||||
transformed = newB.replaceChildren(
|
||||
comb.get(0) ? newInput : b.input(),
|
||||
comb.get(1) ? newStart : b.start(),
|
||||
comb.get(2) ? newLength : b.length());
|
||||
assertEquals(transformed.src(), comb.get(0) ? newSource : b.src());
|
||||
assertEquals(transformed.input(), comb.get(0) ? newInput : b.input());
|
||||
assertEquals(transformed.start(), comb.get(1) ? newStart : b.start());
|
||||
assertEquals(transformed.length(), comb.get(2) ? newLength : b.length());
|
||||
assertEquals(transformed.expression(), b.expression());
|
||||
@ -104,12 +103,9 @@ public class SubstringFunctionPipeTests
|
||||
randoms.add(f -> new SubstringFunctionPipe(
|
||||
f.source(),
|
||||
f.expression(),
|
||||
comb.get(0) ? pipe(((Expression) randomValueOtherThan(f.src(),
|
||||
() -> randomStringLiteral()))) : f.src(),
|
||||
comb.get(1) ? pipe(((Expression) randomValueOtherThan(f.start(),
|
||||
() -> randomIntLiteral()))) : f.start(),
|
||||
comb.get(2) ? pipe(((Expression) randomValueOtherThan(f.length(),
|
||||
() -> randomIntLiteral()))): f.length()));
|
||||
comb.get(0) ? randomValueOtherThan(f.input(), () -> pipe(randomStringLiteral())) : f.input(),
|
||||
comb.get(1) ? randomValueOtherThan(f.start(), () -> pipe(randomIntLiteral())) : f.start(),
|
||||
comb.get(2) ? randomValueOtherThan(f.length(), () -> pipe(randomIntLiteral())): f.length()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +116,7 @@ public class SubstringFunctionPipeTests
|
||||
protected SubstringFunctionPipe copy(SubstringFunctionPipe instance) {
|
||||
return new SubstringFunctionPipe(instance.source(),
|
||||
instance.expression(),
|
||||
instance.src(),
|
||||
instance.input(),
|
||||
instance.start(),
|
||||
instance.length());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user