Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.common.utils;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* Utility class for debugging operations. This class is only for debugging purpose, and not
* intended to be used in production code.
*/
public class DebugUtils {
// Update this to true while you are debugging. (Safe guard to avoid usage in production code. )
private static final boolean IS_DEBUG = false;
private static final Logger logger = LogManager.getLogger(DebugUtils.class);

public static <T> T debug(T obj, String message) {
verifyDebug();
print("### %s: %s (at %s)", message, stringify(obj), getCalledFrom(1));
return obj;
}

public static <T> T debug(T obj) {
verifyDebug();
print("### %s (at %s)", stringify(obj), getCalledFrom(1));
return obj;
}

private static void verifyDebug() {
if (!IS_DEBUG) {
throw new RuntimeException("DebugUtils can be used only for local debugging.");
}
}

private static void print(String format, Object... args) {
logger.info(String.format(format, args));
}

private static String getCalledFrom(int pos) {
RuntimeException e = new RuntimeException();
StackTraceElement item = e.getStackTrace()[pos + 1];
return item.getClassName() + "." + item.getMethodName() + ":" + item.getLineNumber();
}

private static String stringify(Collection<?> items) {
if (items == null) {
return "null";
}

if (items.isEmpty()) {
return "()";
}

String result = items.stream().map(i -> stringify(i)).collect(Collectors.joining(","));

return "(" + result + ")";
}

private static String stringify(Map<?, ?> map) {
if (map == null) {
return "[[null]]";
}

if (map.isEmpty()) {
return "[[EMPTY]]";
}

String result =
map.entrySet().stream()
.map(entry -> entry.getKey() + ": " + stringify(entry.getValue()))
.collect(Collectors.joining(","));
return "{" + result + "}";
}

private static String stringify(Object obj) {
if (obj instanceof Collection) {
return stringify((Collection) obj);
} else if (obj instanceof Map) {
return stringify((Map) obj);
}
return String.valueOf(obj);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.common.utils;

import static org.junit.Assert.assertThrows;

import org.junit.Test;

public class DebugUtilsTest {

@Test
public void testDebugThrowsRuntimeException() {
assertThrows(RuntimeException.class, () -> DebugUtils.debug("test", "test message"));
}

@Test
public void testDebugWithoutMessageThrowsRuntimeException() {
assertThrows(RuntimeException.class, () -> DebugUtils.debug("test"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
import org.opensearch.sql.ast.tree.Values;
import org.opensearch.sql.ast.tree.Window;
import org.opensearch.sql.common.antlr.SyntaxCheckException;
import org.opensearch.sql.common.patterns.PatternUtils;
import org.opensearch.sql.data.model.ExprMissingValue;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.data.type.ExprType;
Expand Down Expand Up @@ -952,10 +953,10 @@ private Aggregation analyzePatternsAgg(Patterns node) {
List<UnresolvedExpression> aggExprs =
Stream.of(
new Alias(
"pattern_count",
PatternUtils.PATTERN_COUNT,
new AggregateFunction(BuiltinFunctionName.COUNT.name(), AllFields.of())),
new Alias(
"sample_logs",
PatternUtils.SAMPLE_LOGS,
new AggregateFunction(
BuiltinFunctionName.TAKE.name(),
node.getSourceField(),
Expand Down
40 changes: 40 additions & 0 deletions core/src/main/java/org/opensearch/sql/ast/AstNodeUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.ast;

import lombok.experimental.UtilityClass;
import org.opensearch.sql.ast.expression.Let;
import org.opensearch.sql.ast.expression.subquery.SubqueryExpression;

/** Utility class for AST node operations shared among visitor classes. */
@UtilityClass
public class AstNodeUtils {

/**
* Checks if an AST node contains a subquery expression.
*
* @param expr The AST node to check
* @return true if the node or any of its children contains a subquery expression
*/
public static boolean containsSubqueryExpression(Node expr) {
if (expr == null) {
return false;
}
if (expr instanceof SubqueryExpression) {
return true;
}
if (expr instanceof Let) {
Let l = (Let) expr;
return containsSubqueryExpression(l.getExpression());
}
for (Node child : expr.getChild()) {
if (containsSubqueryExpression(child)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.ast.analysis;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.Getter;
import org.opensearch.sql.ast.tree.Relation;
import org.opensearch.sql.ast.tree.UnresolvedPlan;

/** Context for field resolution using stack-based traversal. */
public class FieldResolutionContext {

@Getter private final Map<UnresolvedPlan, FieldResolutionResult> results;
private final Deque<FieldResolutionResult> requirementsStack;

public FieldResolutionContext() {
this.results = new IdentityHashMap<>();
this.requirementsStack = new ArrayDeque<>();
this.requirementsStack.push(new FieldResolutionResult(Set.of(), "*"));
}

public void pushRequirements(FieldResolutionResult result) {
requirementsStack.push(result);
}

public FieldResolutionResult popRequirements() {
return requirementsStack.pop();
}

public FieldResolutionResult getCurrentRequirements() {
if (requirementsStack.isEmpty()) {
throw new RuntimeException("empty stack");
} else {
return requirementsStack.peek();
}
}

public void setResult(UnresolvedPlan relation, FieldResolutionResult result) {
results.put(relation, result);
}

public Set<Relation> getRelations() {
return results.keySet().stream()
.filter(k -> k instanceof Relation)
.map(k -> (Relation) k)
.collect(Collectors.toSet());
}

public static String mergeWildcardPatterns(Set<String> patterns) {
if (patterns == null || patterns.isEmpty()) {
return null;
}
if (patterns.size() == 1) {
return patterns.iterator().next();
}
return String.join(" | ", patterns.stream().sorted().collect(Collectors.toList()));
}

@Override
public String toString() {
return "FieldResolutionContext{relationResults=" + results + "}";
}
}
Loading
Loading