Skip to content

Commit

Permalink
HHH-18033 Fix LimitHandler detect wrong statement end if sql contains…
Browse files Browse the repository at this point in the history
… quoted semicolon
  • Loading branch information
quaff committed Apr 30, 2024
1 parent d414686 commit a0b9edf
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ protected boolean renderOffsetRowsKeyword() {
};

private static final Pattern WITH_OPTION_PATTERN =
Pattern.compile("\\s+with\\s+(" + String.join("|", WITH_OPTIONS) + ")\\b|\\s*(;|$)");
Pattern.compile("\\s+with\\s+(" + String.join("|", WITH_OPTIONS) + ")\\b|\\s*;?$");

/**
* The offset/fetch clauses must come before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public int convertToFirstRowValue(int zeroBasedFirstResult) {
}

private static final Pattern FOR_UPDATE_PATTERN =
compile("\\s+for\\s+update\\b|\\s+with\\s+lock\\b|\\s*(;|$)", CASE_INSENSITIVE);
compile("\\s+for\\s+update\\b|\\s+with\\s+lock\\b|\\s*;?$", CASE_INSENSITIVE);

@Override
protected Pattern getForUpdatePattern() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.community.dialect;

import org.hibernate.community.dialect.pagination.IngresLimitHandler;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.orm.test.dialect.AbstractLimitHandlerTest;

/**
* @author Yanming Zhou
*/
public class IngresLimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return IngresLimitHandler.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.community.dialect;

import org.hibernate.community.dialect.pagination.RowsLimitHandler;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.orm.test.dialect.AbstractLimitHandlerTest;

/**
* @author Yanming Zhou
*/
public class RowsLimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return RowsLimitHandler.INSTANCE;
}

@Override
protected String getLimitClause() {
return " rows ?";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ public abstract class AbstractLimitHandler implements LimitHandler {
compile( "^\\s*select(\\s+(distinct|all))?\\b", CASE_INSENSITIVE );

private static final Pattern END_PATTERN =
compile("\\s*(;|$)", CASE_INSENSITIVE);
compile("\\s*;?$", CASE_INSENSITIVE);

private static final Pattern FOR_UPDATE_PATTERN =
compile("\\s+for\\s+update\\b|\\s*(;|$)", CASE_INSENSITIVE);
compile("\\s+for\\s+update\\b|\\s*;?$", CASE_INSENSITIVE);


@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public DerbyLimitHandler(boolean variableLimit) {
}

private static final Pattern FOR_UPDATE_WITH_LOCK_PATTERN =
Pattern.compile("\\s+for\\s+(update|read|fetch)\\b|\\s+with\\s+(rr|rs|cs|ur)\\b|\\s*(;|$)");
Pattern.compile("\\s+for\\s+(update|read|fetch)\\b|\\s+with\\s+(rr|rs|cs|ur)\\b|\\s*;?$");

/**
* The offset/fetch clauses must come before the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected String offsetOnlyClause() {
}

private static final Pattern FOR_UPDATE_PATTERN =
compile("\\s+for\\s+update\\b|\\s+lock\\s+in\\s+shared\\s+mode\\b|\\s*(;|$)", CASE_INSENSITIVE);
compile("\\s+for\\s+update\\b|\\s+lock\\s+in\\s+shared\\s+mode\\b|\\s*;?$", CASE_INSENSITIVE);

@Override
protected Pattern getForUpdatePattern() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.dialect;

import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.query.spi.Limit;
import org.junit.jupiter.api.Test;

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

/**
* @author Yanming Zhou
*/
public abstract class AbstractLimitHandlerTest {

@Test
public void testSqlWithSemicolonInsideQuotedString() {
String sql = "select * from Person p where p.name like ';'";
String expected = "select * from Person p where p.name like ';'" + getLimitClause();
assertGenerateExpectedSql(expected, sql);
}

@Test
public void testSqlWithSemicolonInsideQuotedStringAndEndsWithSemicolon() {
String sql = "select * from Person p where p.name like ';';";
String expected = "select * from Person p where p.name like ';'" + getLimitClause() + ";";
assertGenerateExpectedSql(expected, sql);
}

protected void assertGenerateExpectedSql(String expected, String sql) {
assertEquals(expected, getLimitHandler().processSql(sql, new Limit(0, 10)));
}

protected abstract LimitHandler getLimitHandler();

protected Limit getLimit() {
return new Limit(0, 10);
}

protected String getLimitClause() {
LimitHandler handler = getLimitHandler();
if (handler instanceof OffsetFetchLimitHandler) {
OffsetFetchLimitHandler oflh = (OffsetFetchLimitHandler) handler;
return " fetch first " + (oflh.supportsVariableLimit() ? "?" : String.valueOf(getLimit().getMaxRows())) + " rows only";
}
return " limit ?";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.dialect;

import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.DB2LimitHandler;

/**
* @author Yanming Zhou
*/
public class DB2LimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return DB2LimitHandler.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.dialect;

import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.DerbyLimitHandler;

/**
* @author Yanming Zhou
*/
public class DerbyLimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return DerbyLimitHandler.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.dialect;

import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitLimitHandler;

/**
* @author Yanming Zhou
*/
public class LimitLimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return LimitLimitHandler.INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.dialect;

import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;

/**
* @author Yanming Zhou
*/
public class OffsetFetchLimitHandlerTest extends AbstractLimitHandlerTest {

@Override
protected AbstractLimitHandler getLimitHandler() {
return OffsetFetchLimitHandler.INSTANCE;
}
}

0 comments on commit a0b9edf

Please sign in to comment.