Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d9b97b9
Support DuckDB GLOB pattern matching operator
hayssams Sep 15, 2026
50a25f0
Support standalone SEMI and ANTI joins
hayssams Sep 15, 2026
a9345f1
Support DuckDB MAP(key, value) column type
hayssams Sep 15, 2026
d7f5fe2
Support DuckDB INSERT ... BY NAME / BY POSITION
hayssams Sep 15, 2026
34c97e4
Support DuckDB USING SAMPLE sizes and methods
hayssams Sep 15, 2026
26a1fba
Support DuckDB DESCRIBE <query>
hayssams Sep 15, 2026
d0b0642
Support PRAGMA statement
hayssams Sep 15, 2026
7d4eac7
Support DuckDB INSTALL and LOAD extension statements
hayssams Sep 15, 2026
068fd29
Support DuckDB ATTACH and DETACH statements
hayssams Sep 15, 2026
804fb5f
Support DuckDB 2.0 CONNECT and DISCONNECT statements
hayssams Sep 15, 2026
4b73b31
Support PREPARE and DEALLOCATE statements
hayssams Sep 15, 2026
588e4a5
Support DuckDB COPY statement
hayssams Sep 15, 2026
9af64f8
Support DuckDB CREATE MACRO
hayssams Sep 15, 2026
1df0033
Support DuckDB 2.0 CREATE EXTENSION REPOSITORY
hayssams Sep 15, 2026
154bb24
Support DuckDB 2.0 triggers with transition tables and a statement body
hayssams Sep 15, 2026
0f685b8
Support DuckDB FROM-first queries
hayssams Sep 15, 2026
6f6dea4
Support DuckDB UNPIVOT statement
hayssams Sep 15, 2026
eb04155
Support DuckDB 2.0 APPROX NEAREST similarity joins
hayssams Sep 15, 2026
c04286d
Support DuckDB 2.0 recursive CTEs with USING KEY
hayssams Sep 15, 2026
aee7cbc
Merge branch 'master' into feature/duckdb-syntax
hayssams Sep 17, 2026
0a9971d
fix: restore lines dropped during conflict resolution and fix LOAD DA…
hayssams Sep 17, 2026
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
Expand Up @@ -119,7 +119,7 @@ public LikeExpression withRightExpression(Expression arg0) {
}

public enum KeyWord {
LIKE, ILIKE, RLIKE, REGEXP_LIKE, REGEXP, SIMILAR_TO, MATCH_ANY, MATCH_ALL, MATCH_PHRASE, MATCH_PHRASE_PREFIX, MATCH_REGEXP;
LIKE, ILIKE, RLIKE, REGEXP_LIKE, REGEXP, GLOB, SIMILAR_TO, MATCH_ANY, MATCH_ALL, MATCH_PHRASE, MATCH_PHRASE_PREFIX, MATCH_REGEXP;

public static KeyWord from(String keyword) {
return Enum.valueOf(KeyWord.class,
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ public enum Feature {
* "SEMI" join
*/
joinSemi,
/**
* @see net.sf.jsqlparser.statement.select.Join#isAnti()
*/
joinAnti,
/**
* "INNER" join
*/
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/AttachStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*-
* #%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.statement;

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

import java.util.List;

/**
* DuckDB's {@code ATTACH [DATABASE] [IF NOT EXISTS] path [AS alias] [(options)]}, which adds
* another database file or remote database to the session.
*
* @see <a href="https://duckdb.org/docs/stable/sql/statements/attach">ATTACH</a>
*/
public class AttachStatement implements Statement {
private String databasePath;
private String alias;
private boolean usingDatabaseKeyword;
private boolean ifNotExists;
private List<String> options;

public String getDatabasePath() {
return databasePath;
}

public void setDatabasePath(String databasePath) {
this.databasePath = databasePath;
}

public AttachStatement withDatabasePath(String databasePath) {
setDatabasePath(databasePath);
return this;
}

public String getAlias() {
return alias;
}

public void setAlias(String alias) {
this.alias = alias;
}

public AttachStatement withAlias(String alias) {
setAlias(alias);
return this;
}

public boolean isUsingDatabaseKeyword() {
return usingDatabaseKeyword;
}

public void setUsingDatabaseKeyword(boolean usingDatabaseKeyword) {
this.usingDatabaseKeyword = usingDatabaseKeyword;
}

public AttachStatement withUsingDatabaseKeyword(boolean usingDatabaseKeyword) {
setUsingDatabaseKeyword(usingDatabaseKeyword);
return this;
}

public boolean isIfNotExists() {
return ifNotExists;
}

public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
}

public AttachStatement withIfNotExists(boolean ifNotExists) {
setIfNotExists(ifNotExists);
return this;
}

public List<String> getOptions() {
return options;
}

public void setOptions(List<String> options) {
this.options = options;
}

public AttachStatement withOptions(List<String> options) {
setOptions(options);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("ATTACH ");
if (usingDatabaseKeyword) {
builder.append("DATABASE ");
}
if (ifNotExists) {
builder.append("IF NOT EXISTS ");
}
builder.append(databasePath);
if (alias != null) {
builder.append(" AS ").append(alias);
}
if (options != null && !options.isEmpty()) {
builder.append(" ").append(PlainSelect.getStringList(options, true, true));
}
return builder;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}
}
69 changes: 69 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/ConnectStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*-
* #%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.statement;

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

public ConnectStatement() {}

public ConnectStatement(String target) {
this.target = target;
}

public String getTarget() {
return target;
}

public void setTarget(String target) {
this.target = target;
}

public ConnectStatement withTarget(String target) {
setTarget(target);
return this;
}

public String getAlias() {
return alias;
}

public void setAlias(String alias) {
this.alias = alias;
}

public ConnectStatement withAlias(String alias) {
setAlias(alias);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("CONNECT ").append(target);
if (alias != null) {
builder.append(" AS ").append(alias);
}
return builder;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}
}
139 changes: 139 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/CopyStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*-
* #%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.statement;

import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;

import java.util.List;

/**
* {@code COPY table [(columns)] FROM path [(options)]} and
* {@code COPY {table | (query)} TO path [(options)]}, DuckDB's bulk import and export statement.
*
* @see <a href="https://duckdb.org/docs/stable/sql/statements/copy">COPY</a>
*/
public class CopyStatement implements Statement {
private Table table;
private ExpressionList<Column> columns;
private Select select;
private boolean from;
private String path;
private List<String> options;

public Table getTable() {
return table;
}

public void setTable(Table table) {
this.table = table;
}

public CopyStatement withTable(Table table) {
setTable(table);
return this;
}

public ExpressionList<Column> getColumns() {
return columns;
}

public void setColumns(ExpressionList<Column> columns) {
this.columns = columns;
}

public CopyStatement withColumns(ExpressionList<Column> columns) {
setColumns(columns);
return this;
}

public Select getSelect() {
return select;
}

public void setSelect(Select select) {
this.select = select;
}

public CopyStatement withSelect(Select select) {
setSelect(select);
return this;
}

/** {@code true} for COPY ... FROM (import), {@code false} for COPY ... TO (export). */
public boolean isFrom() {
return from;
}

public void setFrom(boolean from) {
this.from = from;
}

public CopyStatement withFrom(boolean from) {
setFrom(from);
return this;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public CopyStatement withPath(String path) {
setPath(path);
return this;
}

public List<String> getOptions() {
return options;
}

public void setOptions(List<String> options) {
this.options = options;
}

public CopyStatement withOptions(List<String> options) {
setOptions(options);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("COPY ");
if (select != null) {
builder.append("(").append(select).append(")");
} else {
builder.append(table);
if (columns != null && !columns.isEmpty()) {
builder.append(" (").append(columns).append(")");
}
}
builder.append(from ? " FROM " : " TO ").append(path);
if (options != null && !options.isEmpty()) {
builder.append(" ").append(PlainSelect.getStringList(options, true, true));
}
return builder;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}
}
Loading
Loading