Skip to content
Open
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
Expand Up @@ -781,4 +781,10 @@ default void visit(Inverse inverse) {
<S> T visit(FromQuery fromQuery, S context);

<S> T visit(DateUnitExpression dateUnitExpression, S context);

<S> T visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context);

default void visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter) {
this.visit(postgresNamedFunctionParameter, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,11 @@ public <S> T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S
return oracleNamedFunctionParameter.getExpression().accept(this, context);
}

@Override
public <S> T visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context) {
return postgresNamedFunctionParameter.getExpression().accept(this, context);
}

@Override
public <S> T visit(GeometryDistance geometryDistance, S context) {
return visitBinaryExpression(geometryDistance, context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2021 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.expression;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

import java.util.Objects;

/**
* @author <a href="mailto:andreas@manticore-projects.com">Andreas Reichel</a>
*/
public class PostgresNamedFunctionParameter extends ASTNodeAccessImpl implements Expression {
private final String name;
private final Expression expression;

public PostgresNamedFunctionParameter(String name, Expression expression) {
this.name = Objects.requireNonNull(name,
"The NAME of the PostgresNamedFunctionParameter must not be null.");
this.expression = Objects.requireNonNull(expression,
"The EXPRESSION of the PostgresNamedFunctionParameter must not be null.");
}

public String getName() {
return name;
}

public Expression getExpression() {
return expression;
}

@Override
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
return expressionVisitor.visit(this, context);
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append(name)
.append(" := ")
.append(expression);

return builder;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}
}
6 changes: 6 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,12 @@ public <S> Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter,
return null;
}

@Override
public <S> Void visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context) {
postgresNamedFunctionParameter.getExpression().accept(this, context);
return null;
}

@Override
public <S> Void visit(RenameTableStatement renameTableStatement, S context) {
for (Map.Entry<Table, Table> e : renameTableStatement.getTableNames()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
import net.sf.jsqlparser.expression.OverlapsCondition;
import net.sf.jsqlparser.expression.PostgresNamedFunctionParameter;
import net.sf.jsqlparser.expression.RangeExpression;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.RowGetExpression;
Expand Down Expand Up @@ -1835,4 +1836,13 @@ public <S> StringBuilder visit(FromQuery fromQuery, S context) {
public <S> StringBuilder visit(DateUnitExpression dateUnitExpression, S context) {
return builder.append(dateUnitExpression.toString());
}

@Override
public <S> StringBuilder visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter,
S context) {
builder.append(postgresNamedFunctionParameter.getName()).append(" := ");

postgresNamedFunctionParameter.getExpression().accept(this, context);
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
import net.sf.jsqlparser.expression.OverlapsCondition;
import net.sf.jsqlparser.expression.PostgresNamedFunctionParameter;
import net.sf.jsqlparser.expression.RangeExpression;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.RowGetExpression;
Expand Down Expand Up @@ -1052,6 +1053,12 @@ public <S> Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter,
return null;
}

@Override
public <S> Void visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context) {
postgresNamedFunctionParameter.getExpression().accept(this, context);
return null;
}

@Override
public <S> Void visit(AllColumns allColumns, S context) {
return null;
Expand Down
19 changes: 19 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_OR:"OR">
| <K_ORA: "ORA">
| <K_ORACLE_NAMED_PARAMETER_ASSIGNMENT: "=>">
| <K_POSTGRES_NAMED_PARAMETER_ASSIGNMENT: ":=">
| <K_ORDER:"ORDER">
| <K_ORDINALITY:"ORDINALITY">
| <K_OUTER:"OUTER">
Expand Down Expand Up @@ -6224,6 +6225,8 @@ ExpressionList ComplexExpressionList():
(
LOOKAHEAD(2) expr=OracleNamedFunctionParameter()
|
LOOKAHEAD(2) expr=PostgresNamedFunctionParameter()
|
expr=Expression()
)
{
Expand All @@ -6235,6 +6238,8 @@ ExpressionList ComplexExpressionList():
(
LOOKAHEAD(2) expr=OracleNamedFunctionParameter()
|
LOOKAHEAD(2) expr=PostgresNamedFunctionParameter()
|
LOOKAHEAD(7) expr=LambdaExpression()
|
expr=Expression()
Expand Down Expand Up @@ -6786,6 +6791,20 @@ OracleNamedFunctionParameter OracleNamedFunctionParameter() : {
}
}

PostgresNamedFunctionParameter PostgresNamedFunctionParameter() : {
Token token = null;
String name = null;
Expression expression;
}
{
( name=RelObjectNameExt2() | token=<K_OUTER> )
<K_POSTGRES_NAMED_PARAMETER_ASSIGNMENT>
expression=Expression()
{
return new PostgresNamedFunctionParameter(name != null ? name : token.image, expression);
}
}

UserVariable UserVariable() : {
Token tk;
String varName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2021 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.expression;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.test.TestUtils;
import net.sf.jsqlparser.util.TablesNamesFinder;
import net.sf.jsqlparser.util.validation.ValidationTestAsserts;
import net.sf.jsqlparser.util.validation.feature.DatabaseType;
import net.sf.jsqlparser.util.validation.validator.ExpressionValidator;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
*
* @author <a href="mailto:andreas@manticore-projects.com">Andreas Reichel</a>
*/
public class PostgresNamedFunctionParameterTest {

/**
* This test will parse and deparse the statement and assures the functional coverage by
* JSQLParser.
*
* @throws JSQLParserException
*/
@Test
public void testExpression() throws JSQLParserException {
String sqlStr =
"SELECT concat_lower_or_upper(a := 'Hello', uppercase := true, b := 'World')";

TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
}

/**
* This test will trigger the method {@link ExpressionVisitorAdaptor#visit() Visit Method} in
* the ExpressionVisitorAdaptor needed for the Code Coverage.
*
* @throws JSQLParserException
*/
@Test
public void testExpressionVisitorAdaptor() throws JSQLParserException {
String sqlStr =
"SELECT concat_lower_or_upper(a := 'Hello', uppercase := true, b := 'World')";

CCJSqlParserUtil.parse(sqlStr).accept(new StatementVisitorAdapter());

// alternatively, for the Expression only
CCJSqlParserUtil.parseExpression("a := 'Hello'").accept(new ExpressionVisitorAdapter(),
null);
}

/**
* This test will trigger the method {@link TableNamesFinder#visit() Visit Method} in the
* TableNamesFinder needed for the Code Coverage.
*
* @throws JSQLParserException
*/
@Test
public void testTableNamesFinder() throws JSQLParserException {
String sqlStr =
"SELECT concat_lower_or_upper(a := 'Hello', uppercase := true, b := 'World') FROM test_table";

Statement statement = CCJSqlParserUtil.parse(sqlStr);
List<String> tables = new TablesNamesFinder<>().getTableList(statement);
assertEquals(1, tables.size());
assertTrue(tables.contains("test_table"));
}

/**
* This test will trigger the method {@link ExpressionValidator#visit() Visit Method} in the
* ExpressionValidator needed for the Code Coverage.
*
* @throws JSQLParserException
*/
@Test
public void testValidator() throws JSQLParserException {
String sqlStr =
"SELECT concat_lower_or_upper(a := 'Hello', uppercase := true, b := 'World') FROM test_table";

ValidationTestAsserts.validateNoErrors(sqlStr, 1, DatabaseType.POSTGRESQL);
}
}