Skip to content
18 changes: 8 additions & 10 deletions src/main/java/net/sf/jsqlparser/parser/ASTNodeAccessImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,20 @@ public StringBuilder appendTo(StringBuilder builder) {
return builder;
}

/**
* The nearest enclosing object in the tree, or null when there is none. A node that carries
* only a token range, for an object no grammar rule opens a tree node for, has no parent.
*/
public ASTNodeAccess getParent() {
Node parent = (Node) node.jjtGetParent();
while (parent.jjtGetValue() == null) {
parent = (Node) parent.jjtGetParent();
}

return ASTNodeAccess.class.cast(parent.jjtGetValue());
return getParent(ASTNodeAccess.class);
}

public <T extends ASTNodeAccess> T getParent(Class<T> clazz) {
Node parent = (Node) node.jjtGetParent();
while (parent.jjtGetValue() == null || !clazz.isInstance(parent.jjtGetValue())) {
Node parent = node == null ? null : (Node) node.jjtGetParent();
while (parent != null && !clazz.isInstance(parent.jjtGetValue())) {
parent = (Node) parent.jjtGetParent();
}

return clazz.cast(parent.jjtGetValue());
return parent == null ? null : clazz.cast(parent.jjtGetValue());
}

@Override
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/RangeNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.parser;

/**
* A node outside the parse tree that records the tokens an object spans. It serves an object no
* grammar rule opens a tree node for, or one whose text runs past its tree node. In that second
* case it stands in for the tree node, answering its parent, children and id, with the wider range.
*/
final class RangeNode extends Node {
private final Node treeNode;

RangeNode(Token first, Token last, Node treeNode) {
super(CCJSqlParserTreeConstants.JJTEXPRESSION);
this.treeNode = treeNode;
jjtSetFirstToken(first);
jjtSetLastToken(last);
}

@Override
public Node jjtGetParent() {
return treeNode == null ? null : treeNode.jjtGetParent();
}

@Override
public Node[] jjtGetChildren() {
return treeNode == null ? super.jjtGetChildren() : treeNode.jjtGetChildren();
}

@Override
public Node jjtGetChild(int i) {
return treeNode == null ? super.jjtGetChild(i) : treeNode.jjtGetChild(i);
}

@Override
public int jjtGetNumChildren() {
return treeNode == null ? super.jjtGetNumChildren() : treeNode.jjtGetNumChildren();
}

@Override
public Object childrenAccept(CCJSqlParserVisitor visitor, Object data) {
return treeNode == null ? super.childrenAccept(visitor, data)
: treeNode.childrenAccept(visitor, data);
}

@Override
public int getId() {
return treeNode == null ? super.getId() : treeNode.getId();
}

@Override
public String toString() {
return treeNode == null ? super.toString() : treeNode.toString();
}

@Override
public void dump(String prefix) {
if (treeNode == null) {
super.dump(prefix);
} else {
treeNode.dump(prefix);
}
}
}
37 changes: 37 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/SimpleCharStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public class SimpleCharStream {
protected boolean trackLineColumn = true;
protected int totalCharsRead = 0;
protected int absoluteTokenBegin = 0;
// line, column and absolute position of each match begun since the last positionSpecialTokens()
private int[] matchBegins = new int[24];
private int matchBeginCount = 0;
int bufsize;
int available;
int tokenBegin;
Expand Down Expand Up @@ -107,6 +110,38 @@ public final int getAbsoluteTokenBegin() {
return absoluteTokenBegin;
}

/**
* Gives the comments in front of {@code token} the positions where their matches began, from
* the begins recorded since the last call, and forgets those. Comments come through no token
* action, so this is how they get a position. The comments chain backwards from the token while
* the begins are recorded forwards, so one backwards pass pairs them.
*/
public final void positionSpecialTokens(Token token) {
int i = matchBeginCount - 3;
for (Token comment = token.specialToken; comment != null; comment = comment.specialToken) {
while (i >= 0 && (matchBegins[i] != comment.beginLine
|| matchBegins[i + 1] != comment.beginColumn)) {
i -= 3;
}
if (i < 0) {
break;
}
comment.absoluteBegin = matchBegins[i + 2];
comment.absoluteEnd = comment.absoluteBegin + comment.image.length();
i -= 3;
}
matchBeginCount = 0;
}

private void recordMatchBegin() {
if (matchBeginCount + 3 > matchBegins.length) {
matchBegins = java.util.Arrays.copyOf(matchBegins, matchBegins.length * 2);
}
matchBegins[matchBeginCount++] = getBeginLine();
matchBegins[matchBeginCount++] = getBeginColumn();
matchBegins[matchBeginCount++] = absoluteTokenBegin;
}

protected void ExpandBuff(boolean wrapAround) {
final int newSize = bufsize * 2;
char[] newbuffer = new char[newSize];
Expand Down Expand Up @@ -200,6 +235,7 @@ public final char BeginToken() throws java.io.IOException {
tokenBegin = bufpos;

absoluteTokenBegin = totalCharsRead;
recordMatchBegin();

if (c == '#' && featureConfiguration != null
&& featureConfiguration.getAsBoolean(Feature.allowHashLineComments)) {
Expand Down Expand Up @@ -441,6 +477,7 @@ public final void backup(int amount) {
* Reinitialise.
*/
public void ReInit(Provider dstream, int startline, int startcolumn, int buffersize) {
matchBeginCount = 0;
inputStream = dstream;
line = startline;
column = startcolumn - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

import java.util.function.Consumer;

Expand All @@ -22,7 +23,7 @@
* "https://cloud.google.com/bigquery/docs/reference/standard-sql/debugging-statements">Debugging
* statements</a>
*/
public class AssertStatement implements Statement {
public class AssertStatement extends ASTNodeAccessImpl implements Statement {
private Expression expression;
private StringValue description;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.util.List;
Expand All @@ -19,7 +20,7 @@
*
* @see <a href="https://duckdb.org/docs/stable/sql/statements/attach">ATTACH</a>
*/
public class AttachStatement implements Statement {
public class AttachStatement extends ASTNodeAccessImpl implements Statement {
private String databasePath;
private String alias;
private boolean usingDatabaseKeyword;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/sf/jsqlparser/statement/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
package net.sf.jsqlparser.statement;

import java.util.function.Consumer;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

public class Block implements Statement {
public class Block extends ASTNodeAccessImpl implements Statement {
private boolean hasSemicolonAfterEnd = false;

private Statements statements;
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/net/sf/jsqlparser/statement/Commit.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
*/
package net.sf.jsqlparser.statement;

public class Commit implements Statement {
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

public class Commit extends ASTNodeAccessImpl implements Statement {
private TransactionKeyword keyword;
private TransactionChain chain;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* DuckDB's {@code CONNECT target [AS alias]}, which routes the session's queries to a remote
* database.
*/
public class ConnectStatement implements Statement {
public class ConnectStatement extends ASTNodeAccessImpl implements Statement {
private String target;
private String alias;

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/sf/jsqlparser/statement/CopyStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
Expand All @@ -25,7 +26,7 @@
*
* @see <a href="https://duckdb.org/docs/stable/sql/statements/copy">COPY</a>
*/
public class CopyStatement implements Statement {
public class CopyStatement extends ASTNodeAccessImpl implements Statement {
private Table table;
private ExpressionList<Column> columns;
private Select select;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.function.FunctionReturnType;
import net.sf.jsqlparser.statement.create.table.TableElement;

/**
* A base for the declaration of function like statements
*/
public abstract class CreateFunctionalStatement implements Statement {
public abstract class CreateFunctionalStatement extends ASTNodeAccessImpl implements Statement {

private String kind;
private boolean orReplace = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* {@code DEALLOCATE [PREPARE] name}, which drops a statement prepared by {@link PrepareStatement}.
*/
public class DeallocateStatement implements Statement {
public class DeallocateStatement extends ASTNodeAccessImpl implements Statement {
private String name;
private boolean usingPrepareKeyword;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.table.ColDataType;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;

public final class DeclareStatement implements Statement {
public final class DeclareStatement extends ASTNodeAccessImpl implements Statement {

private UserVariable userVariable = null;
private DeclareType declareType = DeclareType.TYPE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.Select;

public class DescribeStatement implements Statement {
public class DescribeStatement extends ASTNodeAccessImpl implements Statement {

private Table table;
private Select select;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* DuckDB's {@code DETACH [DATABASE] [IF EXISTS] name}, the counterpart of {@link AttachStatement}.
*
* @see <a href="https://duckdb.org/docs/stable/sql/statements/attach">DETACH</a>
*/
public class DetachStatement implements Statement {
public class DetachStatement extends ASTNodeAccessImpl implements Statement {
private String databaseName;
private boolean usingDatabaseKeyword;
private boolean ifExists;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* DuckDB's {@code DISCONNECT [name]}, the counterpart of {@link ConnectStatement}.
*/
public class DisconnectStatement implements Statement {
public class DisconnectStatement extends ASTNodeAccessImpl implements Statement {
private String name;

public DisconnectStatement() {}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/sf/jsqlparser/statement/DoStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@

import java.util.function.Consumer;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/** A PostgreSQL anonymous routine. The language-specific body remains a string literal. */
public class DoStatement implements Statement {
public class DoStatement extends ASTNodeAccessImpl implements Statement {
private StringValue code;
private String language;
private boolean languageBeforeCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.schema.Table;

/**
* An {@code EXPLAIN} statement
*/
public class ExplainStatement implements Statement {
public class ExplainStatement extends ASTNodeAccessImpl implements Statement {
private String keyword;
private Statement statement;
private List<Option> options = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* DuckDB's extension management statements {@code [FORCE] INSTALL extension [FROM repository]} and
* {@code LOAD extension}.
*
* @see <a href="https://duckdb.org/docs/stable/extensions/overview">Extensions</a>
*/
public class ExtensionStatement implements Statement {
public class ExtensionStatement extends ASTNodeAccessImpl implements Statement {
private Operation operation;
private boolean force;
private String extensionName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
import java.util.function.Consumer;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* @author <a href="mailto:andreas@manticore-projects.com">Andreas Reichel</a>
*/
public class IfElseStatement implements Statement {
public class IfElseStatement extends ASTNodeAccessImpl implements Statement {
private final Expression condition;
private final Statement ifStatement;
private Statement elseStatement;
Expand Down
Loading
Loading