fix quoting in change processors. Fixes #11

This commit is contained in:
f43nd1r 2018-06-25 17:12:44 +02:00
parent 6f8c7271c3
commit e3a256221e
4 changed files with 107 additions and 50 deletions

View file

@ -13,42 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.faendir.acra.liquibase;
import liquibase.changelog.ChangeSet;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.Query;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @author lukas
* @since 01.06.18
* @since 25.06.18
*/
public abstract class LiquibaseChangePostProcessor {
private final String changeId;
protected LiquibaseChangePostProcessor(String changeId) {
this.changeId = changeId;
}
public interface LiquibaseChangePostProcessor {
@Transactional
protected void iterate(Supplier<Query> supplier, Consumer<Object> consumer) {
int offset = 0;
List<?> list;
while (!(list = supplier.get().setFirstResult(offset).setMaxResults(64).getResultList()).isEmpty()) {
list.forEach(consumer::accept);
offset += list.size();
}
}
void handle(ChangeSet changeSet) {
if (changeId.equals(changeSet.getId())) {
afterChange();
}
}
protected abstract void afterChange();
void handle(ChangeSet changeSet);
}

View file

@ -0,0 +1,84 @@
/*
* (C) Copyright 2018 Lukas Morawietz (https://github.com/F43nd1r)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.faendir.acra.liquibase.change;
import com.faendir.acra.liquibase.LiquibaseChangePostProcessor;
import liquibase.changelog.ChangeSet;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @author lukas
* @since 01.06.18
*/
public abstract class BaseChange implements LiquibaseChangePostProcessor {
private final String changeId;
private final EntityManager entityManager;
private Dialect dialect;
protected BaseChange(@NonNull String changeId, @NonNull EntityManager entityManager) {
this.changeId = changeId;
this.entityManager = entityManager;
}
@NonNull
private Dialect getDialect() {
if (dialect == null) {
dialect = ((SessionFactoryImplementor) entityManager.unwrap(Session.class).getSessionFactory()).getServiceRegistry().getService(JdbcServices.class).getDialect();
}
return dialect;
}
@NonNull
protected EntityManager getEntityManager() {
return entityManager;
}
@Nullable
protected String quote(@Nullable String s) {
return getDialect().quote(s);
}
@Transactional
protected void iterate(@NonNull Supplier<Query> supplier, @NonNull Consumer<Object> consumer) {
int offset = 0;
List<?> list;
while (!(list = supplier.get().setFirstResult(offset).setMaxResults(64).getResultList()).isEmpty()) {
list.forEach(consumer::accept);
offset += list.size();
}
}
@Override
public void handle(@NonNull ChangeSet changeSet) {
if (changeId.equals(changeSet.getId())) {
afterChange();
}
}
protected abstract void afterChange();
}

View file

@ -15,7 +15,6 @@
*/
package com.faendir.acra.liquibase.change;
import com.faendir.acra.liquibase.LiquibaseChangePostProcessor;
import org.acra.ReportField;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,24 +29,22 @@ import javax.persistence.EntityManager;
* @since 01.06.18
*/
@Component
public class ReportColumnsChange extends LiquibaseChangePostProcessor {
@NonNull private final EntityManager entityManager;
public class ReportColumnsChange extends BaseChange {
@Autowired
public ReportColumnsChange(@NonNull @Lazy EntityManager entityManager) {
super("2018-06-01-add-report-columns");
this.entityManager = entityManager;
super("2018-06-01-add-report-columns", entityManager);
}
@Override
protected void afterChange() {
iterate(() -> entityManager.createNativeQuery("SELECT \"content\" FROM \"report\""), o -> {
iterate(() -> getEntityManager().createNativeQuery("SELECT " + quote("content") + " FROM " + quote("report")), o -> {
String content = (String) o;
JSONObject json = new JSONObject(content);
String id = json.getString(ReportField.REPORT_ID.name());
String brand = json.optString(ReportField.BRAND.name());
String installationId = json.optString(ReportField.INSTALLATION_ID.name());
entityManager.createNativeQuery("UPDATE \"report\" SET \"brand\" = ?1, \"installation_id\" = ?2 WHERE \"id\" = ?3")
getEntityManager().createNativeQuery(
"UPDATE " + quote("report") + " SET " + quote("brand") + " = ?1, " + quote("installation_id") + " = ?2 WHERE " + quote("id") + " = ?3")
.setParameter(1, brand)
.setParameter(2, installationId)
.setParameter(3, id)

View file

@ -15,7 +15,6 @@
*/
package com.faendir.acra.liquibase.change;
import com.faendir.acra.liquibase.LiquibaseChangePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.lang.NonNull;
@ -28,40 +27,41 @@ import javax.persistence.EntityManager;
* @since 04.06.18
*/
@Component
public class StacktraceChange extends LiquibaseChangePostProcessor {
public class StacktraceChange extends BaseChange {
@NonNull private final EntityManager entityManager;
@Autowired
public StacktraceChange(@NonNull @Lazy EntityManager entityManager) {
super("2018-06-04-add-stacktrace-table");
super("2018-06-04-add-stacktrace-table", entityManager);
this.entityManager = entityManager;
}
@Override
protected void afterChange() {
iterate(() -> entityManager.createNativeQuery(
"SELECT \"stacktrace\", \"version_code\", \"version_name\", \"bug_id\", \"id\" FROM \"report\""), o -> {
"SELECT " + quote("stacktrace") + ", " + quote("version_code") + ", " + quote("version_name") + ", " + quote("bug_id") + ", " + quote("id") + " FROM " + quote(
"report") + ""), o -> {
Object[] result = (Object[]) o;
String trace = (String) result[0];
int versionCode = (int) result[1];
String versionName = (String) result[2];
int bugId = (int) result[3];
int reportId = (int) result[4];
Long stacktraceId = (Long) entityManager.createNativeQuery("SELECT \"id\" FROM \"stacktrace\" WHERE \"stacktrace\" = ?1 AND \"version_code\" = ?2")
Long stacktraceId = (Long) entityManager.createNativeQuery(
"SELECT " + quote("id") + " FROM " + quote("stacktrace") + " WHERE " + quote("stacktrace") + " = ?1 AND " + quote("version_code") + " = ?2")
.setParameter(1, trace)
.setParameter(2, versionCode)
.setMaxResults(1)
.getSingleResult();
if(stacktraceId == null) {
entityManager.createNativeQuery("INSERT INTO \"stacktrace\" (\"bug_id\", \"stacktrace\", \"version_code\", \"version_name\") VALUES(?1, ?2, ?3, ?4)")
.setParameter(1, bugId)
.setParameter(2, trace)
.setParameter(3, versionCode)
.setParameter(4, versionName)
.executeUpdate();
stacktraceId = (Long) entityManager.createNativeQuery("SELECT \"id\" FROM \"stacktrace\" ORDER BY \"id\" DESC").setMaxResults(1).getSingleResult();
if (stacktraceId == null) {
entityManager.createNativeQuery(
"INSERT INTO " + quote("stacktrace") + " (" + quote("bug_id") + ", " + quote("stacktrace") + ", " + quote("version_code") + ", " + quote("version_name")
+ ") VALUES(?1, ?2, ?3, ?4)").setParameter(1, bugId).setParameter(2, trace).setParameter(3, versionCode).setParameter(4, versionName).executeUpdate();
stacktraceId = (Long) entityManager.createNativeQuery("SELECT " + quote("id") + " FROM " + quote("stacktrace") + " ORDER BY " + quote("id") + " DESC")
.setMaxResults(1)
.getSingleResult();
}
entityManager.createNativeQuery("UPDATE \"report\" SET \"stacktrace_id\" = ?1 WHERE \"id\" = ?2")
entityManager.createNativeQuery("UPDATE " + quote("report") + " SET " + quote("stacktrace_id") + " = ?1 WHERE " + quote("id") + " = ?2")
.setParameter(1, stacktraceId)
.setParameter(2, reportId)
.executeUpdate();