Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 20152e16891582f8ff466a93ec2cf01871824d6d
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date:   Tue Feb 27 20:59:51 2024 +1300

    #3341 Update DatabaseConfig for fluid style + javadoc

commit 1c495a7
Author: Roland Praml <roland.praml@foconis.de>
Date:   Mon Feb 26 10:25:42 2024 +0100

    Fix: Compile errors

commit 574876b
Merge: df7b048 77634fc
Author: Roland Praml <roland.praml@foconis.de>
Date:   Fri Feb 23 16:16:39 2024 +0100

    Merge branch 'master-rob' into FOCONIS-string-length-validation

commit df7b048
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date:   Mon Jun 26 21:16:32 2023 +1200

    #3121 BindMaxLength validation

    At deploy time derive a BindMaxLength property to use
    per BeanProperty

commit 4683877
Merge: 9a4b9d4 d0020ab
Author: Rob Bygrave <robin.bygrave@gmail.com>
Date:   Fri Jun 23 16:51:34 2023 +1200

    Merge branch 'string-length-validation' of github.com:FOCONIS/ebean into FOCONIS-string-length-validation

commit d0020ab
Author: Roland Praml <roland.praml@foconis.de>
Date:   Tue Jun 20 14:47:20 2023 +0200

    Length validation less invasive

commit 9b3b8ad
Author: Roland Praml <roland.praml@foconis.de>
Date:   Tue Jun 20 13:03:04 2023 +0200

    extended DataBind, so that it could return the last bound object

commit ca3c02b
Author: Roland Praml <roland.praml@foconis.de>
Date:   Mon Jun 19 09:52:52 2023 +0200

    Failing test for SqlServer
  • Loading branch information
rbygrave committed Feb 27, 2024
1 parent 4a6fc98 commit 11c9bdf
Show file tree
Hide file tree
Showing 20 changed files with 430 additions and 12 deletions.
9 changes: 8 additions & 1 deletion ebean-api/src/main/java/io/ebean/DataIntegrityException.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import jakarta.persistence.PersistenceException;

/**
* Thrown when a foreign key constraint is enforced.
* Thrown when a foreign key constraint is enforced or a field is too large.
*/
public class DataIntegrityException extends PersistenceException {
private static final long serialVersionUID = -6740171949170180970L;
Expand All @@ -14,4 +14,11 @@ public class DataIntegrityException extends PersistenceException {
public DataIntegrityException(String message, Throwable cause) {
super(message, cause);
}

/**
* Create with message only.
*/
public DataIntegrityException(String message) {
super(message);
}
}
10 changes: 10 additions & 0 deletions ebean-api/src/main/java/io/ebean/DatabaseBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ default DatabaseBuilder alsoIf(BooleanSupplier predicate, Consumer<DatabaseBuild
}
return this;
}

/**
* Set the name of the Database.
*/
Expand Down Expand Up @@ -2221,6 +2222,11 @@ default DatabaseBuilder metricNaming(Function<String, String> metricNaming) {
@Deprecated
DatabaseBuilder setMetricNaming(Function<String, String> metricNaming);

/**
* Sets the length check mode.
*/
DatabaseConfig lengthCheck(LengthCheck lengthCheck);

/**
* Provides read access (getters) for the DatabaseBuilder configuration
* that has been set.
Expand Down Expand Up @@ -3103,5 +3109,9 @@ interface Settings extends DatabaseBuilder {
*/
Function<String, String> getMetricNaming();

/**
* Returns the length check mode.
*/
LengthCheck getLengthCheck();
}
}
15 changes: 15 additions & 0 deletions ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {

private String dumpMetricsOptions;

private LengthCheck lengthCheck = LengthCheck.OFF;
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;

/**
Expand Down Expand Up @@ -2195,6 +2196,7 @@ protected void loadSettings(PropertiesWrapper p) {
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
lengthCheck = p.getEnum(LengthCheck.class, "lengthCheck", lengthCheck);

uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
Expand Down Expand Up @@ -2571,6 +2573,19 @@ public DatabaseConfig setMetricNaming(Function<String, String> metricNaming) {
return this;
}

/**
* Returns the length check mode.
*/
public LengthCheck getLengthCheck() {
return lengthCheck;
}

@Override
public DatabaseConfig lengthCheck(LengthCheck lengthCheck) {
this.lengthCheck = lengthCheck;
return this;
}

public enum UuidVersion {
VERSION4,
VERSION1,
Expand Down
22 changes: 22 additions & 0 deletions ebean-api/src/main/java/io/ebean/config/LengthCheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.ebean.config;

/**
* Defines the length-check mode.
*
* @author Roland Praml, FOCONIS AG
*/
public enum LengthCheck {
/**
* By default, length checking is off. This means, strings/jsons and files are passed to the DB and the DB might or might not check the length.
* The DB has to check the data length. Note this is not possible for certain datatypes (e.g. clob without size)
*/
OFF,
/**
* When enabling length check, ebean validates strings/json strings and files before saving them to DB.
*/
ON,
/**
* Same as "ON", but take the UTF8-bytelength for validation. This may be useful, if you have an UTF8 based charset (default for DB2)
*/
UTF8
}
11 changes: 9 additions & 2 deletions ebean-api/src/test/java/io/ebean/config/DatabaseConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ void testLoadWithProperties() {
props.setProperty("defaultServer", "false");
props.setProperty("skipDataSourceCheck", "true");
props.setProperty("readOnlyDatabase", "true");
props.setProperty("lengthCheck", "ON");

props.setProperty("queryPlan.enable", "true");
props.setProperty("queryPlan.thresholdMicros", "10000");
Expand All @@ -95,6 +96,7 @@ void testLoadWithProperties() {
assertTrue(settings.isLoadModuleInfo());
assertTrue(settings.skipDataSourceCheck());
assertTrue(settings.readOnlyDatabase());
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);

assertTrue(settings.isIdGeneratorAutomatic());
assertFalse(settings.getPlatformConfig().isCaseSensitiveCollation());
Expand Down Expand Up @@ -128,8 +130,11 @@ void testLoadWithProperties() {

assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");

config.setPersistBatch(PersistBatch.NONE);
config.setPersistBatchOnCascade(PersistBatch.NONE);
config.persistBatch(PersistBatch.NONE)
.persistBatchOnCascade(PersistBatch.NONE)
.lengthCheck(LengthCheck.ON)
.lengthCheck(LengthCheck.UTF8);


Properties props1 = new Properties();
props1.setProperty("ebean.persistBatch", "ALL");
Expand All @@ -146,6 +151,7 @@ void testLoadWithProperties() {

assertEquals(PersistBatch.ALL, settings.getPersistBatch());
assertEquals(PersistBatch.ALL, settings.getPersistBatchOnCascade());
assertEquals(LengthCheck.UTF8, settings.getLengthCheck());

config.setEnabledL2Regions("r0,orgs");
assertEquals("r0,orgs", settings.getEnabledL2Regions());
Expand Down Expand Up @@ -174,6 +180,7 @@ void test_defaults() {
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
assertEquals(10, config.getQueryPlanCaptureMaxCount());
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);

config.setLoadModuleInfo(false);
assertFalse(config.isAutoLoadModuleInfo());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,9 @@ public interface DataBinder {
*/
String popJson();

/**
* Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo.
*/
Object popLastObject();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.ebean.core.type;

import java.io.InputStream;

/**
* Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation
*
* @author Roland Praml, FOCONIS AG
*/
public final class InputStreamInfo {

private final InputStream stream;
private final long length;

public InputStreamInfo(InputStream stream, long length) {
this.stream = stream;
this.length = length;
}

public InputStream stream() {
return stream;
}

public long length() {
return length;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.ebeaninternal.server.bind;

import io.ebean.core.type.DataBinder;
import io.ebean.core.type.InputStreamInfo;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.core.timezone.DataTimeZone;

import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
Expand All @@ -23,6 +27,8 @@ public class DataBind implements DataBinder {
protected int pos;
private String json;

private Object lastObject = null;

public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) {
this.dataTimeZone = dataTimeZone;
this.pstmt = pstmt;
Expand Down Expand Up @@ -65,16 +71,19 @@ public final int currentPos() {
@Override
public void setObject(Object value) throws SQLException {
pstmt.setObject(++pos, value);
lastObject = value;
}

@Override
public final void setObject(Object value, int sqlType) throws SQLException {
pstmt.setObject(++pos, value, sqlType);
lastObject = value;
}

@Override
public void setNull(int jdbcType) throws SQLException {
pstmt.setNull(++pos, jdbcType);
lastObject = null;
}

@Override
Expand All @@ -96,7 +105,7 @@ public final int executeUpdate() throws SQLException {
}
}

private void closeInputStreams() {
public void closeInputStreams() {
if (inputStreams != null) {
for (InputStream inputStream : inputStreams) {
try {
Expand All @@ -117,36 +126,43 @@ public final PreparedStatement getPstmt() {
@Override
public void setString(String value) throws SQLException {
pstmt.setString(++pos, value);
lastObject = value;
}

@Override
public final void setInt(int value) throws SQLException {
pstmt.setInt(++pos, value);
lastObject = null;
}

@Override
public final void setLong(long value) throws SQLException {
pstmt.setLong(++pos, value);
lastObject = null;
}

@Override
public final void setShort(short value) throws SQLException {
pstmt.setShort(++pos, value);
lastObject = null;
}

@Override
public final void setFloat(float value) throws SQLException {
pstmt.setFloat(++pos, value);
lastObject = null;
}

@Override
public final void setDouble(double value) throws SQLException {
pstmt.setDouble(++pos, value);
lastObject = null;
}

@Override
public final void setBigDecimal(BigDecimal value) throws SQLException {
pstmt.setBigDecimal(++pos, value);
lastObject = null;
}

@Override
Expand All @@ -157,6 +173,7 @@ public final void setDate(java.sql.Date value) throws SQLException {
} else {
pstmt.setDate(++pos, value);
}
lastObject = null;
}

@Override
Expand All @@ -167,6 +184,7 @@ public final void setTimestamp(Timestamp value) throws SQLException {
} else {
pstmt.setTimestamp(++pos, value);
}
lastObject = null;
}

@Override
Expand All @@ -177,26 +195,31 @@ public final void setTime(Time value) throws SQLException {
} else {
pstmt.setTime(++pos, value);
}
lastObject = null;
}

@Override
public void setBoolean(boolean value) throws SQLException {
pstmt.setBoolean(++pos, value);
lastObject = null;
}

@Override
public void setBytes(byte[] value) throws SQLException {
pstmt.setBytes(++pos, value);
lastObject = value;
}

@Override
public void setByte(byte value) throws SQLException {
pstmt.setByte(++pos, value);
lastObject = null;
}

@Override
public void setChar(char value) throws SQLException {
pstmt.setString(++pos, String.valueOf(value));
lastObject = null;
}

@Override
Expand All @@ -211,21 +234,31 @@ public void setBinaryStream(InputStream inputStream, long length) throws SQLExce
}
inputStreams.add(inputStream);
pstmt.setBinaryStream(++pos, inputStream, length);
lastObject = new InputStreamInfo(inputStream, length);
}

@Override
public void setBlob(byte[] bytes) throws SQLException {
pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length);
lastObject = bytes;
}

@Override
public void setClob(String content) throws SQLException {
pstmt.setCharacterStream(++pos, new StringReader(content), content.length());
lastObject = content;
}

@Override
public void setArray(String arrayType, Object[] elements) throws SQLException {
pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements));
lastObject = null;
}

@Override
public Object popLastObject() {
Object ret = lastObject;
lastObject = null;
return ret;
}
}
Loading

0 comments on commit 11c9bdf

Please sign in to comment.