Skip to content

Commit 937d2d0

Browse files
authored
Merge pull request #35 from ZorTik/development
Development
2 parents 2b63b02 + 5e3502f commit 937d2d0

11 files changed

Lines changed: 151 additions & 37 deletions

File tree

api/src/main/java/me/zort/sqllib/api/data/QueryResult.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ public interface QueryResult {
1313
@Nullable
1414
String getRejectMessage();
1515

16+
QueryResult noChangesResult = successful();
17+
1618
static QueryResult successful() {
1719
return new QueryResult() {
1820
@Override

api/src/main/java/me/zort/sqllib/api/model/TableSchema.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package me.zort.sqllib.api.model;
22

3-
import me.zort.sqllib.util.Pair;
4-
53
public class TableSchema {
64

75
private final String table;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package me.zort.sqllib.internal.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target(ElementType.FIELD)
10+
public @interface Default {
11+
String value();
12+
}

core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
import me.zort.sqllib.mapping.DefaultStatementMappingFactory;
3232
import me.zort.sqllib.mapping.MappingRegistryImpl;
3333
import me.zort.sqllib.mapping.ProxyInstanceImpl;
34-
import me.zort.sqllib.model.DatabaseSchemaBuilder;
35-
import me.zort.sqllib.model.EntitySchemaBuilder;
36-
import me.zort.sqllib.model.SQLSchemaSynchronizer;
34+
import me.zort.sqllib.model.schema.DatabaseSchemaBuilder;
35+
import me.zort.sqllib.model.schema.EntitySchemaBuilder;
36+
import me.zort.sqllib.model.schema.SQLSchemaSynchronizer;
3737
import me.zort.sqllib.pool.PooledSQLDatabaseConnection;
3838
import me.zort.sqllib.transaction.Transaction;
3939
import me.zort.sqllib.util.Validator;
@@ -183,7 +183,7 @@ public void enableCaching(CacheManager cacheManager) {
183183
* <i>Warning:</i> This tries to update all tables that are part of mapping
184184
* proxies. Should be used carefully.
185185
*
186-
* @return True if synchronization was successful
186+
* @return True if there were any changes
187187
*/
188188
@ApiStatus.Experimental
189189
@Override
@@ -192,7 +192,7 @@ public boolean synchronizeModel() {
192192
.stream().flatMap(i -> i.getTableSchemas(
193193
getOptions().getNamingStrategy(),
194194
this instanceof SQLiteDatabaseConnectionImpl).stream())
195-
.allMatch(schema -> synchronizeModel(schema, schema.getTable()));
195+
.anyMatch(schema -> synchronizeModel(schema, schema.getTable()));
196196
}
197197

198198
/**
@@ -202,13 +202,14 @@ public boolean synchronizeModel() {
202202
*
203203
* @param entitySchema Entity schema
204204
* @param table Table name
205-
* @return True if synchronization was successful
205+
* @return True if there were any changes
206206
*/
207207
@ApiStatus.Experimental
208208
@Override
209209
public boolean synchronizeModel(TableSchema entitySchema, String table) {
210-
return getSchemaSynchronizer().synchronize(this, entitySchema,
211-
getSchemaBuilder(table).buildTableSchema()).isSuccessful();
210+
QueryResult result = getSchemaSynchronizer().synchronize(this, entitySchema,
211+
getSchemaBuilder(table).buildTableSchema());
212+
return result != QueryResult.noChangesResult && result.isSuccessful();
212213
}
213214

214215
/**
@@ -219,7 +220,7 @@ public boolean synchronizeModel(TableSchema entitySchema, String table) {
219220
*
220221
* @param entity The entity (model) class
221222
* @param table Table name
222-
* @return True if synchronization was successful
223+
* @return True if there were any changes
223224
*/
224225
@ApiStatus.Experimental
225226
@Override

core/src/main/java/me/zort/sqllib/mapping/ProxyInstanceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import me.zort.sqllib.api.model.TableSchema;
1111
import me.zort.sqllib.api.options.NamingStrategy;
1212
import me.zort.sqllib.mapping.annotation.Table;
13-
import me.zort.sqllib.model.EntitySchemaBuilder;
13+
import me.zort.sqllib.model.schema.EntitySchemaBuilder;
1414

1515
import java.lang.reflect.Method;
1616
import java.lang.reflect.Modifier;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package me.zort.sqllib.model.column;
2+
3+
import me.zort.sqllib.api.model.ColumnDefinition;
4+
5+
public class InnoColumnQueryBuilder implements SQLColumnQueryBuilder {
6+
@Override
7+
public String buildActionQuery(SQLColumnQueryBuilder.ColumnAction action, String table, ColumnDefinition from, ColumnDefinition to) {
8+
if (action == SQLColumnQueryBuilder.ColumnAction.ADD) {
9+
return "ALTER TABLE " + table + " ADD COLUMN " + from + ";";
10+
} else if (action == SQLColumnQueryBuilder.ColumnAction.DROP) {
11+
return "ALTER TABLE " + table + " DROP COLUMN " + to.getName() + ";";
12+
} else if (action == SQLColumnQueryBuilder.ColumnAction.RENAME) {
13+
return "ALTER TABLE " + table + " RENAME COLUMN " + to.getName() + " TO " + from.getName() + ";";
14+
} else if (action == SQLColumnQueryBuilder.ColumnAction.MODIFY) {
15+
return "ALTER TABLE " + table + " MODIFY COLUMN " + from.getName() + " " + from.getType() + ";";
16+
}
17+
throw new RuntimeException("Unknown action: " + action);
18+
}
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package me.zort.sqllib.model.column;
2+
3+
import me.zort.sqllib.api.model.ColumnDefinition;
4+
5+
public interface SQLColumnQueryBuilder {
6+
7+
String buildActionQuery(ColumnAction action, String table, ColumnDefinition from, ColumnDefinition to);
8+
9+
enum ColumnAction {
10+
ADD, DROP, MODIFY, RENAME
11+
}
12+
13+
}

core/src/main/java/me/zort/sqllib/model/DatabaseSchemaBuilder.java renamed to core/src/main/java/me/zort/sqllib/model/schema/DatabaseSchemaBuilder.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
package me.zort.sqllib.model;
1+
package me.zort.sqllib.model.schema;
22

33
import me.zort.sqllib.api.model.ColumnDefinition;
44
import me.zort.sqllib.api.model.TableSchema;
55
import me.zort.sqllib.api.model.TableSchemaBuilder;
66

7-
import java.sql.PreparedStatement;
8-
import java.sql.ResultSet;
9-
import java.sql.ResultSetMetaData;
10-
import java.sql.SQLException;
7+
import java.sql.*;
8+
import java.util.HashMap;
119
import java.util.HashSet;
10+
import java.util.Map;
1211
import java.util.Set;
1312
import java.util.function.Function;
1413

@@ -31,24 +30,37 @@ public DatabaseSchemaBuilder(Function<String, PreparedStatement> statementFactor
3130
public TableSchema buildTableSchema() {
3231
try(PreparedStatement statement = statementFactory.apply("SELECT * FROM " + table + " LIMIT 0;");
3332
ResultSet rs = statement.executeQuery()) {
34-
ResultSetMetaData meta = rs.getMetaData();
35-
ResultSet primaryKeysRS = statement.getConnection().getMetaData().getPrimaryKeys(null, null, table);
33+
ResultSetMetaData rsMeta = rs.getMetaData();
34+
DatabaseMetaData connectionMeta = statement.getConnection().getMetaData();
35+
ResultSet primaryKeysRS = connectionMeta.getPrimaryKeys(null, null, table);
36+
ResultSet defaultValuesRS = connectionMeta.getColumns(null, null, table, null);
3637
Set<String> primaryKeys = new HashSet<>();
38+
Map<String, String> defaultValues = new HashMap<>();
3739
while (primaryKeysRS.next()) {
3840
primaryKeys.add(primaryKeysRS.getString("COLUMN_NAME").toUpperCase());
3941
}
42+
while (defaultValuesRS.next()) {
43+
String defaultValue = defaultValuesRS.getString("COLUMN_DEF");
44+
if (defaultValue != null) {
45+
defaultValues.put(defaultValuesRS.getString("COLUMN_NAME").toUpperCase(), defaultValue);
46+
}
47+
}
4048
primaryKeysRS.close();
49+
defaultValuesRS.close();
4150

42-
ColumnDefinition[] definitions = new ColumnDefinition[meta.getColumnCount()];
51+
ColumnDefinition[] definitions = new ColumnDefinition[rsMeta.getColumnCount()];
4352
for (int i = 0; i < definitions.length; i++) {
44-
String name = meta.getColumnName(i + 1);
45-
String type = prepareColumnType(meta.getColumnTypeName(i + 1));
46-
if (meta.getColumnClassName(i + 1).equals(String.class.getName()) && meta.getColumnDisplaySize(i + 1) > 0) {
47-
type += "(" + meta.getColumnDisplaySize(i + 1) + ")";
53+
String name = rsMeta.getColumnName(i + 1);
54+
String type = prepareColumnType(rsMeta.getColumnTypeName(i + 1));
55+
if (rsMeta.getColumnClassName(i + 1).equals(String.class.getName()) && rsMeta.getColumnDisplaySize(i + 1) > 0) {
56+
type += "(" + rsMeta.getColumnDisplaySize(i + 1) + ")";
4857
}
49-
if (primaryKeys.contains(meta.getColumnName(i + 1).toUpperCase())) {
58+
if (primaryKeys.contains(name.toUpperCase())) {
5059
type += " PRIMARY KEY";
5160
}
61+
if (defaultValues.containsKey(name.toUpperCase())) {
62+
type += " DEFAULT " + defaultValues.get(name.toUpperCase());
63+
}
5264
definitions[i] = new ColumnDefinition(name, type);
5365
}
5466
return new TableSchema(table, definitions);

core/src/main/java/me/zort/sqllib/model/EntitySchemaBuilder.java renamed to core/src/main/java/me/zort/sqllib/model/schema/EntitySchemaBuilder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package me.zort.sqllib.model;
1+
package me.zort.sqllib.model.schema;
22

33
import com.google.gson.internal.Primitives;
44
import lombok.RequiredArgsConstructor;
@@ -7,6 +7,7 @@
77
import me.zort.sqllib.api.model.TableSchema;
88
import me.zort.sqllib.api.model.TableSchemaBuilder;
99
import me.zort.sqllib.api.options.NamingStrategy;
10+
import me.zort.sqllib.internal.annotation.Default;
1011
import me.zort.sqllib.internal.annotation.JsonField;
1112
import me.zort.sqllib.internal.annotation.NullableField;
1213
import me.zort.sqllib.internal.annotation.PrimaryKey;
@@ -66,6 +67,13 @@ public TableSchema buildTableSchema() {
6667
colType += " NOT NULL";
6768
}
6869
}
70+
if (colType != null && field.isAnnotationPresent(Default.class)) {
71+
String defaultValue = field.getAnnotation(Default.class).value();
72+
if ((field.getType().equals(String.class) || field.isAnnotationPresent(JsonField.class))
73+
&& !(defaultValue.startsWith("'") && defaultValue.endsWith("'")))
74+
defaultValue = "'" + defaultValue + "'";
75+
colType += " DEFAULT " + defaultValue;
76+
}
6977

7078
defs = Arrays.add(defs, new ColumnDefinition(colName, colType));
7179

core/src/main/java/me/zort/sqllib/model/SQLSchemaSynchronizer.java renamed to core/src/main/java/me/zort/sqllib/model/schema/SQLSchemaSynchronizer.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
package me.zort.sqllib.model;
1+
package me.zort.sqllib.model.schema;
22

3+
import lombok.Setter;
34
import me.zort.sqllib.SQLDatabaseConnection;
45
import me.zort.sqllib.api.data.QueryResult;
56
import me.zort.sqllib.api.model.ColumnDefinition;
67
import me.zort.sqllib.api.model.SchemaSynchronizer;
78
import me.zort.sqllib.api.model.TableSchema;
9+
import me.zort.sqllib.model.column.InnoColumnQueryBuilder;
10+
import me.zort.sqllib.model.column.SQLColumnQueryBuilder;
811

912
public class SQLSchemaSynchronizer implements SchemaSynchronizer<SQLDatabaseConnection> {
13+
14+
@Setter
15+
private SQLColumnQueryBuilder columnQueryBuilder = new InnoColumnQueryBuilder();
16+
1017
@Override
1118
public QueryResult synchronize(SQLDatabaseConnection source, TableSchema from, TableSchema to) {
1219
StringBuilder query = new StringBuilder();
@@ -15,18 +22,18 @@ public QueryResult synchronize(SQLDatabaseConnection source, TableSchema from, T
1522
ColumnDefinition toDefinition = to.size() > i ? to.getDefinitionDetails(i) : null;
1623

1724
if (fromDefinition == null && toDefinition != null) {
18-
query.append("ALTER TABLE ").append(from.getTable()).append(" DROP COLUMN ").append(toDefinition.getName()).append(";");
25+
query.append(columnQueryBuilder.buildActionQuery(SQLColumnQueryBuilder.ColumnAction.DROP, from.getTable(), fromDefinition, toDefinition));
1926
} else if (fromDefinition != null && toDefinition == null) {
20-
query.append("ALTER TABLE ").append(from.getTable()).append(" ADD ").append(fromDefinition).append(";");
27+
query.append(columnQueryBuilder.buildActionQuery(SQLColumnQueryBuilder.ColumnAction.ADD, from.getTable(), fromDefinition, toDefinition));
2128
} else {
2229
assert fromDefinition != null;
2330
if (!fromDefinition.getName().equals(toDefinition.getName())) {
24-
query.append("ALTER TABLE ").append(from.getTable()).append(" RENAME COLUMN ").append(toDefinition.getName()).append(" TO ").append(fromDefinition.getName()).append(";");
31+
query.append(columnQueryBuilder.buildActionQuery(SQLColumnQueryBuilder.ColumnAction.RENAME, from.getTable(), fromDefinition, toDefinition));
2532
} else if(!fromDefinition.getType().equals(toDefinition.getType())) {
26-
query.append("ALTER TABLE ").append(from.getTable()).append(" ALTER COLUMN ").append(fromDefinition.getName()).append(" ").append(fromDefinition.getType()).append(";");
33+
query.append(columnQueryBuilder.buildActionQuery(SQLColumnQueryBuilder.ColumnAction.MODIFY, from.getTable(), fromDefinition, toDefinition));
2734
}
2835
}
2936
}
30-
return query.length() == 0 ? QueryResult.successful() : source.exec(query.toString());
37+
return query.length() == 0 ? QueryResult.noChangesResult : source.exec(query.toString());
3138
}
3239
}

0 commit comments

Comments
 (0)