diff --git a/.gitignore b/.gitignore index 655e74f..0344bec 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ preprocessor/target common/target build *.keystore +*.~* +projectBackupFiles \ No newline at end of file diff --git a/README.md b/README.md index f238a2c..45ee8cc 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ annotations and CRUD classes expose an expressive api for executing SQLite queri preprocessors on Android.* ```groovy dependencies { - apt 'com.memtrip.sqlking:preprocessor:1.1.5' - compile 'com.memtrip.sqlking:client:1.1.5' + apt 'com.memtrip.sqlking:preprocessor:1.1.6' + compile 'com.memtrip.sqlking:client:1.1.6' } ``` @@ -230,12 +230,27 @@ User[] users = Select.getBuilder() ####Joins#### Joins can be performed using the `InnerJoin`, `LeftOutJoin`, `CrossInnerJoin`, `NaturalInnerJoin`, `NaturalLeftOuterJoin` classes. The target table for the join must be defined as an @Column, the object will be populated with any join results. +Single Column Constraints and Foreignk Keys can also be defined. ```java @Table public class Comment { @Column(index = true) int id; - @Column int userId; + @Column([@ForeignKey // Single column ForeignKey (not required for joins, but will be enforced by SQLite DBMS) + ( + foreignTablename="User", + localColumnNames ={"user_id"}, + foreignColumnNames = {"id"}, + [update/deleteRule=RIRule.Cascade|...][,...] + ) + int userId;] + @Constraints = {@Constraint // Single column Constraints, see SQLite documentation fot `table_constraint` + ( + constraintName = "constraintName", // will be created as "table_name_constraint_name_constraint". the constraint name must be unique within the constraints for the table + expression = "some expression eg, PRIMARY|FOREIGN KEY, UNIQUE, CHECK" + [,@onConflict (ConflictAction.ROLLBACK|ABORT|FAIL|etc)] // optional ON CONFLICT clause, if required and appropriate + )[, ...] // optional additional @Constraint statements + @Column User user; // The target table for a potential join public int getId() { @@ -265,7 +280,7 @@ public class Comment { @Table public class User { - @Column(index = true) int id; + @Column(index = true) int id; // Single column index (short form syntax) public int getId() { return id; @@ -282,13 +297,18 @@ Comment[] comments = Select.getBuilder() User user = comments[0].getUser(); // The nested User object is populated by the join ``` -####Primary Key#### -An auto incrementing primary key can be defined using: + +####Primary Keys#### +Primary Keys can be defined at Table-level or Column-level, but not both, and only one Primary can be defined per table; +a Primary Key at Table-level can contain multiple columns in the key, but Column-level Primary Keys are only defined for the single column on which it is annotated. + +An auto incrementing primary key can be defined on an `int` or `long` column using: ```java @Table public class Data { - @Column(primary_key = true, auto_increment = true) int id; + @Column(primary_key = @PrimaryKey(active = true, true, auto_increment = true) + int id; public int getId() { return id; @@ -300,6 +320,95 @@ public class Data { } ``` +Table level Primary keys are annotated with the following syntax: + +```java +@Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, // Note, multiple columns can be defined, but in this case, no auto-increment is allowed + auto_increment = true + ) +) +public class Post { + @Column int id; + @Column String title; + @Column byte[] blob; + @Column long timestamp; + @Column User user; + @Column Data data; + +``` + +####Table Constraints, Composite Indexes and Foreign Keys#### +Multiple table Constraints, Composite Indexes and Composite Foreign Keys can be defined for the table with the + +```java +@Table ( + foreignkeys = {@ForeignKey ( // not required for joins (yet), but will be enforced by SQLite RDDBMS) + foreignTableName = "xxxx", // will be created as "fk_localTableName_foreignTableName_n", _n increments for multiple links to the same foreign table + localColumnNames = {"localcolumn"[, ...]}, // Multiple columns possible + }, + foreignColumnNames = {"foreignColumn"[, ...]// Multiple columns possible + [,updateRule = ] + [,deleteRule = ] + + } + )[, ...] // optional additional @ForeignKey statements + }, + indexes = {@Index ( + indexName = "index_name", // will be created as "table_name_index_name_index". index_name must be unique within the indexes on the parent table + columns = {@IndexColumn ( + column = "column1" + [,sortOrder = SortOrder.ASC|SortOrder.DESC] // optional column sort order (default is SortOrder.ASC) + )[, ...] // optional additional @IndexColumn statements + } + )[, ...] // optional additional @Index statements + }, + constraints = {@Constraint ( + constraintName = "constraintName", // will be created as "table_name_constraint_name_constraint". the constraint name must be unique within the constraints for the table + expression = "some expression eg, PRIMARY|FOREIGN KEY, UNIQUE, CHECK" // see SQLite documentation fot `table_constraint` clause + [,@onConflict (ConflictAction.ROLLBACK|ABORT|FAIL|IGNORE|REPLACE)] // as appropriate, if required + )[, ...] // optional additional @Constraint statements + } +) +``` + +####Triggers#### +Triggers can be defined at the Table Level with the following syntax: + +```java +@Table ( + triggers = {@Trigger(triggerName = "my_trigger_name", + [,triggerTime = ] + [,triggerType = ] + [,updateOfColumns = { [,...] }] // one or more columns + [,forEachRow = ] // optional; defaults to false. SQLite does not currently support FOR_EACH_STATEMENT + [,whenExpression = <"my_when_expression">] // optional; see SQLite document for the 'my_when_expression' syntax + <,statement = "my_trigger_statement"> // see SQLite document for the 'my_trigger_expression' syntax + )[,...] // optional addition @Trigger statements + } +) + +``` + + ####Tests#### The `tests/java/com/memtrip/sqlking` package contains a full set of unit and integration tests. The tests can be used as a good reference on how to structure queries. @@ -307,6 +416,8 @@ tests can be used as a good reference on how to structure queries. ####TODO#### - Validate that object relationships defined by @Column are annotated with @Table - Validate that auto_increment columns must be int or long -- @Table annotation should support foreign_key functionality - @NotNull annotation and handle this validation in the software layer -- Composite Foreign Key Constraints \ No newline at end of file +- Add table Alias support for Queries, Foreign keys and Joins +- Allow for join creation based on Foreign key Annotations (including aliases) +- Add support for database version upgrades scripts, so that exisiting data is retained during an upgrade +- Add validation and tests for triggers and constraints \ No newline at end of file diff --git a/build-allw.cmd b/build-allw.cmd new file mode 100644 index 0000000..85295ee --- /dev/null +++ b/build-allw.cmd @@ -0,0 +1,6 @@ +cd common +cmd /C mvn clean install +cd ..\preprocessor +cmd /C mvn clean install +cd .. +cmd /C gradlew build install diff --git a/build.gradle b/build.gradle index 2894dab..7315f49 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,8 @@ buildscript { } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' } } \ No newline at end of file diff --git a/client/build.gradle b/client/build.gradle index c3c4e8f..0d03c2d 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -19,7 +19,7 @@ ext { siteUrl = 'https://github.com/memtrip/SQLKing' gitUrl = 'https://github.com/memtrip/SQLKing.git' - libraryVersion = '1.1.5' + libraryVersion = '1.1.8' developerId = 'samkirton' developerName = 'Samuel Kirton' @@ -44,7 +44,7 @@ android { minSdkVersion 11 targetSdkVersion 24 versionCode 7 - versionName "1.1.1" + versionName "1.1.8" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -137,11 +137,11 @@ install { } dependencies { - compile 'com.memtrip.sqlking:common:1.1.5' + compile 'com.memtrip.sqlking:common:1.1.8' compile 'io.reactivex:rxjava:1.1.1' compile 'io.reactivex:rxandroid:1.1.0' - androidTestApt 'com.memtrip.sqlking:preprocessor:1.1.5' + androidTestApt 'com.memtrip.sqlking:preprocessor:1.1.8' androidTestCompile( 'com.android.support.test:runner:0.3', diff --git a/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java b/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java index 25d6c07..70d4977 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java +++ b/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java @@ -49,17 +49,18 @@ public class ClauseHelper { private static final String AND = "AND"; private static final String OR = "OR"; - protected ClauseHelper() { } + protected ClauseHelper() {} public String getClause(Clause[] clause) { StringBuilder clauseBuilder = new StringBuilder(); if (clause != null) { for (Clause item : clause) { - clauseBuilder.append(getClause(item)); + String strClause = getClause(item); +// clauseBuilder.append(getClause(item)); + clauseBuilder.append(strClause); } } - return clauseBuilder.toString(); } @@ -74,7 +75,9 @@ private String getClause(Clause clause) { clauseBuilder.append(buildOnCondition((On) clause)); } else if (clause instanceof And) { clauseBuilder.append(BRACKET_START); + And and = (And)clause; + for (Clause item : and.getClause()) { clauseBuilder.append(getClause(item)); clauseBuilder.append(SPACE); @@ -85,6 +88,7 @@ private String getClause(Clause clause) { // remove the excess AND with its 2 spaces clauseBuilder.delete(clauseBuilder.length() - 5, clauseBuilder.length()); clauseBuilder.append(BRACKET_END); + } else if (clause instanceof Or) { clauseBuilder.append(BRACKET_START); Or or = (Or)clause; @@ -133,7 +137,6 @@ private String buildInCondition(In in) { stringBuilder.append(VALUE); stringBuilder.append(COMMA); } - stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length()); } @@ -241,52 +244,60 @@ public String getLimit(Limit limit) { } public String getJoinStatement(Join[] joins, Resolver resolver) { - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder sb = new StringBuilder(); for (Join join : joins) { SQLQuery sqlQuery = resolver.getSQLQuery(join.getTable()); + String tableAliasName = join.getTableAliasName(); + String tableName = sqlQuery.getTableName(); - stringBuilder - .append(" ") - .append(getJoinType(join)) - .append(" ") - .append(tableName) - .append(" ") - .append(getClause(join.getClauses())); + sb.append(" ") + .append(getJoinType(join)) + .append(" ") + .append(tableName); + + if (tableAliasName != null && tableAliasName.length() > 0) + { + sb.append(" AS ") + .append(tableAliasName); + } + + sb.append(" ") + .append(getClause(join.getClauses())); if (join.getJoin() != null) { - stringBuilder.append(" ") - .append(getJoinStatement(new Join[] { join.getJoin() }, resolver)); + sb.append(" ") + .append(getJoinStatement(new Join[] { join.getJoin() }, resolver)); } } - return stringBuilder.toString(); + return sb.toString(); } - public String buildJoinQuery(String[] tableColumns, Join[] joins, String tableName, Clause[] clause, + public String buildJoinQuery(String[] tableColumns, Join[] joins, String tableName, String tableAlias, Clause[] clause, OrderBy orderBy, Limit limit, Resolver resolver) { String[] joinColumns = getJoinColumns(joins, resolver); - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - stringBuilder.append("SELECT "); + sb.append("SELECT "); for (String column : tableColumns) { - stringBuilder.append(column).append(", "); + sb.append(column).append(", "); } for (String column : joinColumns) { String columnAlias = column.replace(".","_"); - stringBuilder.append(column) + sb.append(column) .append(" as ") .append(columnAlias) .append(", "); } // remove the trailing comma - stringBuilder.delete(stringBuilder.length()-2, stringBuilder.length()); + sb.delete(sb.length()-2, sb.length()); String clauseString = getClause(clause); if (clauseString != null && clauseString.length() > 0) { @@ -303,9 +314,14 @@ public String buildJoinQuery(String[] tableColumns, Join[] joins, String tableNa limitString = "LIMIT " + limitString; } - stringBuilder.append(" FROM ") - .append(tableName) - .append(" ") + sb.append(" FROM ") + .append(tableName); + if (tableAlias != null && tableAlias.length() > 0) + { + sb.append(" AS ") + .append(tableAlias); + } + sb.append(" ") .append(getJoinStatement(joins, resolver)) .append(" ") .append(clauseString) @@ -314,7 +330,7 @@ public String buildJoinQuery(String[] tableColumns, Join[] joins, String tableNa .append(" ") .append(limitString); - return stringBuilder.toString(); + return sb.toString(); } private String[] getJoinColumns(Join[] joins, Resolver resolver) { diff --git a/client/src/main/java/com/memtrip/sqlking/database/Query.java b/client/src/main/java/com/memtrip/sqlking/database/Query.java index 4defa26..1be41ec 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/Query.java +++ b/client/src/main/java/com/memtrip/sqlking/database/Query.java @@ -29,6 +29,7 @@ protected static Cursor selectCursor(Select select, Class classDef, SQLProvid return sqlProvider.query( sqlQuery.getTableName(), + select.getTableAliasName(), sqlQuery.getColumnNames(), select.getClause(), select.getJoin(), diff --git a/client/src/main/java/com/memtrip/sqlking/database/SQLInit.java b/client/src/main/java/com/memtrip/sqlking/database/SQLInit.java index 7b707d5..8d766df 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/SQLInit.java +++ b/client/src/main/java/com/memtrip/sqlking/database/SQLInit.java @@ -39,18 +39,29 @@ public static SQLProvider createDatabase(String name, String[] schemaArray = new String[modelCount]; String[] tableNameArray = new String[modelCount]; + String[] createIndexArray = new String[modelCount]; List indexNameArray = new ArrayList<>(); + String[] createTriggerArray = new String[modelCount];; + List triggerNameArray = new ArrayList<>(); + for (int i = 0; i < modelClassDef.length; i++) { SQLQuery sqlQuery = resolver.getSQLQuery(modelClassDef[i]); - schemaArray[i] = sqlQuery.getTableInsertQuery(); + + schemaArray[i] = sqlQuery.getTableCreateQuery(); tableNameArray[i] = sqlQuery.getTableName(); - createIndexArray[i] = sqlQuery.getCreateIndexQuery(); + createIndexArray[i] = sqlQuery.getCreateIndexesQuery(); + createTriggerArray[i] = sqlQuery.getCreateTriggersQuery(); for (String indexName : sqlQuery.getIndexNames()) { indexNameArray.add(indexName); } + + for (String triggerName : sqlQuery.getTriggerNames()) { + triggerNameArray.add(triggerName); + } + } SQLOpen sqlOpen = new SQLOpen( @@ -60,6 +71,8 @@ public static SQLProvider createDatabase(String name, tableNameArray, createIndexArray, indexNameArray, + createTriggerArray, + triggerNameArray, context ); diff --git a/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java b/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java index c54b616..b9b1aa4 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java +++ b/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java @@ -23,30 +23,39 @@ /** * @author Samuel Kirton [sam@memtrip.com] + * @author Adrian Velcich [adrian@higration.co.za] + * */ public class SQLOpen extends SQLiteOpenHelper { private SQLiteDatabase mDatabase; private String[] mSchemaArray; private String[] mTableNameArray; - private String[] mCreateIndexQuery; - private List mIndexNames; - + private String[] mCreateIndexStatements; + private List mIndexNames; + private String[] mCreateTriggerStatements; + private List mTriggerNames; + protected SQLiteDatabase getDatabase() { return mDatabase; } protected SQLOpen(String name, int version, String[] schemaArray, String[] tableNameArray, - String[] indexQuery, + String[] createIndexStatements, List indexNames, + String[] createTriggerStatements, + List triggerNames, Context context) { super(context, name, null, version); mSchemaArray = schemaArray; mTableNameArray = tableNameArray; - mCreateIndexQuery = indexQuery; - mIndexNames = indexNames; + mCreateIndexStatements = createIndexStatements; + mIndexNames = indexNames; + mCreateTriggerStatements = createTriggerStatements; + mTriggerNames = triggerNames; + mDatabase = getWritableDatabase(); } @@ -57,11 +66,17 @@ public void onCreate(SQLiteDatabase db) { db.execSQL(schema); } - for (String createIndex : mCreateIndexQuery) { - if (createIndex != null) { - db.execSQL(createIndex); - } - } + for (String createIndex : mCreateIndexStatements) { + if (createIndex != null && createIndex.length() > 0) { + db.execSQL(createIndex); + } + } + + for (String createTrigger : mCreateTriggerStatements) { + if (createTrigger != null && createTrigger.length() > 0) { + db.execSQL(createTrigger); + } + } } @Override diff --git a/client/src/main/java/com/memtrip/sqlking/database/SQLProvider.java b/client/src/main/java/com/memtrip/sqlking/database/SQLProvider.java index 7234f02..1981145 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/SQLProvider.java +++ b/client/src/main/java/com/memtrip/sqlking/database/SQLProvider.java @@ -67,7 +67,7 @@ protected int update(String tableName, ContentValues values, Clause[] clause) { ); } - protected Cursor query(String tableName, String[] columns, Clause[] clause, Join[] joins, + protected Cursor query(String tableName, String TableAliasName, String[] columns, Clause[] clause, Join[] joins, String groupBy, String having, OrderBy orderBy, Limit limit) { if (joins != null && joins.length > 0) { @@ -76,6 +76,7 @@ protected Cursor query(String tableName, String[] columns, Clause[] clause, Join columns, joins, tableName, + TableAliasName, clause, orderBy, limit, diff --git a/client/src/main/java/com/memtrip/sqlking/operation/function/Select.java b/client/src/main/java/com/memtrip/sqlking/operation/function/Select.java index d8a9cda..a38395f 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/function/Select.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/function/Select.java @@ -31,10 +31,13 @@ * @author Samuel Kirton [sam@memtrip.com] */ public class Select extends Query { - private Clause[] mClause; - private Join[] mJoin; - private OrderBy mOrderBy; - private Limit mLimit; + private String mTableAlias; + private Clause[] mClause; + private Join[] mJoin; + private OrderBy mOrderBy; + private Limit mLimit; + + public String getTableAliasName() { return mTableAlias; } public Clause[] getClause() { return mClause; @@ -59,29 +62,39 @@ private Select(Clause[] clause, Join[] join, OrderBy orderBy, Limit limit) { mLimit = limit; } - public static Builder getBuilder() { - return new Builder(); + private Select(String tableAlias, Clause[] clause, Join[] join, OrderBy orderBy, Limit limit) { + mTableAlias = tableAlias; + mClause = clause; + mJoin = join; + mOrderBy = orderBy; + mLimit = limit; } - public static class Builder { - private Clause[] mClause; - private Join[] mJoin; + + public static SelectBuilder getBuilder () { + return new SelectBuilder(); + } + + public static class SelectBuilder { + private Clause[] mClause; + private Join[] mJoin; + private OrderBy mOrderBy; private Limit mLimit; - private Builder() { } + private SelectBuilder() { } /** * Specify a Where clause for the Select query * @param clause Where clause * @return Call Builder#execute, Builder#rx, or Builder#rxSingle to run the query */ - public Builder where(Clause... clause) { + public SelectBuilder where(Clause... clause) { mClause = clause; return this; } - public Builder join(Join... joins) { + public SelectBuilder join(Join... joins) { mJoin = joins; return this; } @@ -92,7 +105,7 @@ public Builder join(Join... joins) { * @param order The direction of the Order By clause * @return Call Builder#executem Builder#rx or Builder#rxSingle to run the query */ - public Builder orderBy(String column, OrderBy.Order order) { + public SelectBuilder orderBy(String column, OrderBy.Order order) { mOrderBy = new OrderBy(column, order); return this; } @@ -103,7 +116,7 @@ public Builder orderBy(String column, OrderBy.Order order) { * @param end The ending index to select from * @return Call Builder#execute, Builder#rx or Builder#rxSingle to run the query */ - public Builder limit(int start, int end) { + public SelectBuilder limit(int start, int end) { mLimit = new Limit(start, end); return this; } @@ -123,6 +136,22 @@ public T[] execute(Class classDef, SQLProvider sqlProvider) { ); } + /** + * Executes a Select query + * @param classDef The class definition that the query should run on + * @param tableAlias The table name to be used as an alias during the query + * @param sqlProvider Where the magic happens! + * @param The model object returned from the query + * @return The rows returned by the Select query + */ + public T[] execute(Class classDef, String tableAlias, SQLProvider sqlProvider) { + return select( + new Select(tableAlias, mClause, mJoin, mOrderBy, mLimit), + classDef, + sqlProvider + ); + } + /** * Executes a Select query that expects a single result * @param classDef The class definition that the query should run on diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/CrossInnerJoin.java b/client/src/main/java/com/memtrip/sqlking/operation/join/CrossInnerJoin.java index 41f2f54..191f7be 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/CrossInnerJoin.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/CrossInnerJoin.java @@ -23,15 +23,15 @@ @SuppressWarnings("unchecked") public class CrossInnerJoin extends Join { - public CrossInnerJoin(Class table, Join join, Clause... clauses) { - super(table, join, clauses); + public CrossInnerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + super(table, tableAlias, join, clauses); } - public static CrossInnerJoin crossInnerJoin(Class table, Clause... clauses) { - return new CrossInnerJoin(table, null, clauses); + public static CrossInnerJoin crossInnerJoin(Class table, String tableAlias, Clause... clauses) { + return new CrossInnerJoin(table, tableAlias, null, clauses); } - public static CrossInnerJoin crossInnerJoin(Class table, Join join, Clause... clauses) { - return new CrossInnerJoin(table, join, clauses); + public static CrossInnerJoin crossInnerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + return new CrossInnerJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/InnerJoin.java b/client/src/main/java/com/memtrip/sqlking/operation/join/InnerJoin.java index 06d9bea..97de4aa 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/InnerJoin.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/InnerJoin.java @@ -23,15 +23,35 @@ @SuppressWarnings("unchecked") public class InnerJoin extends Join { + public InnerJoin (Class table, Clause... clauses) { + super(table, clauses); + } + public InnerJoin(Class table, Join join, Clause... clauses) { super(table, join, clauses); } + public InnerJoin(Class table, String tableAlias, Clause... clauses) { + super(table, tableAlias, clauses); + } + + public InnerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + super(table, tableAlias, join, clauses); + } + public static InnerJoin innerJoin(Class table, Clause... clauses) { - return new InnerJoin(table, null, clauses); + return new InnerJoin(table, clauses); } public static InnerJoin innerJoin(Class table, Join join, Clause... clauses) { - return new InnerJoin(table, join, clauses); + return new InnerJoin(table, clauses); + } + + public static InnerJoin innerJoin(Class table, String tableAlias, Clause... clauses) { + return new InnerJoin(table, tableAlias, clauses); + } + + public static InnerJoin innerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + return new InnerJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/Join.java b/client/src/main/java/com/memtrip/sqlking/operation/join/Join.java index 27a003b..e6c0cb5 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/Join.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/Join.java @@ -22,6 +22,7 @@ */ public abstract class Join { private Class mTable; + private String mTableAlias; private Join mJoin; private Clause[] mClauses; @@ -37,9 +38,29 @@ public Clause[] getClauses() { return mClauses; } + public String getTableAliasName() { return mTableAlias; } + + public Join(Class table, Clause... clauses) { + mTable = table; + mClauses = clauses; + } + public Join(Class table, Join join, Clause... clauses) { mTable = table; mJoin = join; mClauses = clauses; } + + public Join(Class table, String tableAlias, Clause... clauses) { + mTable = table; + mTableAlias = tableAlias; + mClauses = clauses; + } + + public Join(Class table, String tableAlias, Join join, Clause... clauses) { + mTable = table; + mTableAlias = tableAlias; + mJoin = join; + mClauses = clauses; + } } \ No newline at end of file diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/LeftOuterJoin.java b/client/src/main/java/com/memtrip/sqlking/operation/join/LeftOuterJoin.java index 61ea0b8..bda41e5 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/LeftOuterJoin.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/LeftOuterJoin.java @@ -23,15 +23,35 @@ @SuppressWarnings("unchecked") public class LeftOuterJoin extends Join { + public LeftOuterJoin (Class table, Clause... clauses) { + super(table, clauses); + } + public LeftOuterJoin(Class table, Join join, Clause... clauses) { - super(table, join, clauses); + super(table, join, clauses); } - + + public LeftOuterJoin(Class table, String tableAlias, Clause... clauses) { + super(table, tableAlias, clauses); + } + + public LeftOuterJoin(Class table, String tableAlias, Join join, Clause... clauses) { + super(table, tableAlias, join, clauses); + } + public static LeftOuterJoin leftOuterJoin(Class table, Clause... clauses) { - return new LeftOuterJoin(table, null, clauses); + return new LeftOuterJoin(table, clauses); } - + public static LeftOuterJoin leftOuterJoin(Class table, Join join, Clause... clauses) { - return new LeftOuterJoin(table, join, clauses); + return new LeftOuterJoin(table, clauses); + } + + public static LeftOuterJoin leftOuterJoin(Class table, String tableAlias, Clause... clauses) { + return new LeftOuterJoin(table, tableAlias, clauses); + } + + public static LeftOuterJoin leftOuterJoin(Class table, String tableAlias, Join join, Clause... clauses) { + return new LeftOuterJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalInnerJoin.java b/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalInnerJoin.java index c715bca..a812b31 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalInnerJoin.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalInnerJoin.java @@ -23,15 +23,15 @@ @SuppressWarnings("unchecked") public class NaturalInnerJoin extends Join { - public NaturalInnerJoin(Class table, Join join, Clause... clauses) { - super(table, join, clauses); + public NaturalInnerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + super(table, tableAlias, join, clauses); } - public static NaturalInnerJoin naturalInnerJoin(Class table, Clause... clauses) { - return new NaturalInnerJoin(table, null, clauses); + public static NaturalInnerJoin naturalInnerJoin(Class table, String tableAlias, Clause... clauses) { + return new NaturalInnerJoin(table, tableAlias, null, clauses); } - public static NaturalInnerJoin naturalInnerJoin(Class table, Join join, Clause... clauses) { - return new NaturalInnerJoin(table, join, clauses); + public static NaturalInnerJoin naturalInnerJoin(Class table, String tableAlias, Join join, Clause... clauses) { + return new NaturalInnerJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalLeftOuterJoin.java b/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalLeftOuterJoin.java index 0450833..3d8baff 100644 --- a/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalLeftOuterJoin.java +++ b/client/src/main/java/com/memtrip/sqlking/operation/join/NaturalLeftOuterJoin.java @@ -23,15 +23,15 @@ @SuppressWarnings("unchecked") public class NaturalLeftOuterJoin extends Join { - public NaturalLeftOuterJoin(Class table, Join join, Clause... clauses) { - super(table, join, clauses); + public NaturalLeftOuterJoin(Class table, String tableAlias, Join join, Clause... clauses) { + super(table, tableAlias, join, clauses); } - public static NaturalLeftOuterJoin naturalLeftOuterJoin(Class table, Clause... clauses) { - return new NaturalLeftOuterJoin(table, null, clauses); + public static NaturalLeftOuterJoin naturalLeftOuterJoin(Class table, String tableAlias, Clause... clauses) { + return new NaturalLeftOuterJoin(table, tableAlias, null, clauses); } - public static NaturalLeftOuterJoin naturalLeftOuterJoin(Class table, Join join, Clause... clauses) { - return new NaturalLeftOuterJoin(table, join, clauses); + public static NaturalLeftOuterJoin naturalLeftOuterJoin(Class table, String tableAlias, Join join, Clause... clauses) { + return new NaturalLeftOuterJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/CreateTest.java b/client/src/tests/java/com/memtrip/sqlking/integration/CreateTest.java index 168bfb5..3a6ac1b 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/CreateTest.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/CreateTest.java @@ -101,7 +101,7 @@ public void testMultipleInsert() { }; // exercise - Insert.getBuilder().values(users).execute(getSQLProvider()); + Insert.getBuilder().values((Object[])users).execute(getSQLProvider()); // verify User angieUser = Select.getBuilder() @@ -148,7 +148,7 @@ public void testMoreThan500RowInsert() { ); } - Insert.getBuilder().values(users).execute(getSQLProvider()); + Insert.getBuilder().values((Object[])users).execute(getSQLProvider()); User[] usersInserted = Select.getBuilder().execute(User.class, getSQLProvider()); diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/ForeignKeyTest.java b/client/src/tests/java/com/memtrip/sqlking/integration/ForeignKeyTest.java new file mode 100644 index 0000000..f762beb --- /dev/null +++ b/client/src/tests/java/com/memtrip/sqlking/integration/ForeignKeyTest.java @@ -0,0 +1,80 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.integration; + +import android.database.Cursor; + +import com.memtrip.sqlking.operation.function.Raw; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ +public class ForeignKeyTest extends IntegrationTest + { + @Before + public void setUp() + { + super.setUp(); + + getSetupData().tearDownTestData(getSQLProvider()); + getSetupData().setupTestData(getSQLProvider()); + + getSetupLog().tearDownTestLogs(getSQLProvider()); + getSetupLog().setupTestLogs(getSQLProvider()); + } + + @Test + public void testUserForeignKeyIsCreated() + { + Cursor cursor = Raw.getBuilder() + .query("PRAGMA foreign_key_list('User');") + .execute(getSQLProvider()); + + List foreignKeys = getForeignKeys(cursor); + + assertEquals(1, foreignKeys.size()); + } + + private List getForeignKeys(Cursor cursor) + { + List foreignKeys = new ArrayList<>(); + + try { + while (cursor.moveToNext()) + { + int foreignKey = cursor.getColumnIndex("name"); + + if (foreignKey != -1) + { + String foreignKeyName = cursor.getString(foreignKey); + foreignKeys.add(foreignKeyName); + } + } + } + finally + { + cursor.close(); + } + + return foreignKeys; + } + } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/IndexTest.java b/client/src/tests/java/com/memtrip/sqlking/integration/IndexTest.java index a6300b2..bc9a821 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/IndexTest.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/IndexTest.java @@ -47,7 +47,7 @@ public void setUp() { @Test public void testPostIndexesAreCreated() { Cursor cursor = Raw.getBuilder() - .query("PRAGMA INDEX_LIST('Post');") + .query("PRAGMA index_list('Post');") .execute(getSQLProvider()); List indexes = getIndexes(cursor); diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/JoinTest.java b/client/src/tests/java/com/memtrip/sqlking/integration/JoinTest.java index 7ec0af8..e8ec4e2 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/JoinTest.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/JoinTest.java @@ -54,19 +54,30 @@ public void setUp() { @Test public void testInnerJoin() { - User[] users = Select .getBuilder() - .join(innerJoin(Log.class, on("User.logId", "Log.id"))) + User[] users = Select.getBuilder() + .join(innerJoin(Log.class, "L", on("User.logId", "L.id"))) .execute(User.class, getSQLProvider()); - assertEquals(1, users.length); - assertEquals(SetupLog.LOG_1_ID, users[0].getLog().getId()); - assertEquals(SetupLog.LOG_1_TIMESTAMP, users[0].getLog().getTimestamp()); + assertEquals(1, users.length); + assertEquals(SetupLog.LOG_1_ID, users[0].getLog().getId()); + assertEquals(SetupLog.LOG_1_TIMESTAMP, users[0].getLog().getTimestamp()); } +// @Test +// public void testInnerJoin() { +// User[] users = Select.getBuilder() +// .join.JoinBuilder((innerJoin(Log.class, on("User.logId", "Log.id"))) +// .execute(User.class, getSQLProvider()); +// +// +// assertEquals(1, users.length); +// assertEquals(SetupLog.LOG_1_ID, users[0].getLog().getId()); +// assertEquals(SetupLog.LOG_1_TIMESTAMP, users[0].getLog().getTimestamp()); +// } @Test public void testNestedInnerJoin() { - Post[] posts = Select .getBuilder() + Post[] posts = Select.getBuilder() .join( innerJoin( User.class, @@ -105,7 +116,7 @@ public void testJoinWithOrderBy() { @Test public void testJoinWithLimit() { - Post[] posts = Select .getBuilder() + Post[] posts = Select.getBuilder() .join( innerJoin( User.class, @@ -142,7 +153,7 @@ public void testNaturalLeftOuterJoin() { @Test public void testJoinWithCondition() { - User[] users = Select .getBuilder() + User[] users = Select.getBuilder() .join(innerJoin(Log.class, on("User.logId", "Log.id"))) .where(where(Q.User.USERNAME, Where.Exp.EQUAL_TO, SetupUser.ANGIE_USER_NAME)) .execute(User.class, getSQLProvider()); diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/models/Data.java b/client/src/tests/java/com/memtrip/sqlking/integration/models/Data.java index 15613a0..1275146 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/models/Data.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/models/Data.java @@ -11,7 +11,6 @@ public class Data { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +18,6 @@ public void setId(int id) { public String getName() { return name; } - public void setName(String name) { this.name = name; } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/models/Log.java b/client/src/tests/java/com/memtrip/sqlking/integration/models/Log.java index faad87b..5d184a7 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/models/Log.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/models/Log.java @@ -1,17 +1,18 @@ package com.memtrip.sqlking.integration.models; import com.memtrip.sqlking.common.Column; +import com.memtrip.sqlking.common.PrimaryKey; import com.memtrip.sqlking.common.Table; @Table public class Log { - @Column(primary_key = true) int id; + @Column(@PrimaryKey(value = true)) + int id; @Column long timestamp; public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +20,6 @@ public void setId(int id) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long timestamp) { this.timestamp = timestamp; } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/models/Post.java b/client/src/tests/java/com/memtrip/sqlking/integration/models/Post.java index cb2e811..bab0c35 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/models/Post.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/models/Post.java @@ -7,9 +7,9 @@ @Table( foreignKeys = { @ForeignKey( - targetTable = "User", - targetColumn = "id", - localColumn = "userId" + foreignTableName = "User", + localColumnNames = {"id"}, + foreignColumnNames = {"userId"} ) } ) @@ -25,7 +25,6 @@ public class Post { public int getId() { return id; } - public void setId(int newVal) { id = newVal; } @@ -33,7 +32,6 @@ public void setId(int newVal) { public String getTitle() { return title; } - public void setTitle(String newVal) { title = newVal; } @@ -41,7 +39,6 @@ public void setTitle(String newVal) { public String getBody() { return body; } - public void setBody(String body) { this.body = body; } @@ -49,7 +46,6 @@ public void setBody(String body) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -57,7 +53,6 @@ public void setTimestamp(long newVal) { public int getUserId() { return userId; } - public void setUserId(int userId) { this.userId = userId; } @@ -65,7 +60,6 @@ public void setUserId(int userId) { public User getUser() { return user; } - public void setUser(User user) { this.user = user; } @@ -73,7 +67,6 @@ public void setUser(User user) { public Data getData() { return data; } - public void setData(Data data) { this.data = data; } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/models/User.java b/client/src/tests/java/com/memtrip/sqlking/integration/models/User.java index e28aef8..53f15d0 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/models/User.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/models/User.java @@ -2,15 +2,22 @@ import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.ForeignKey; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; import com.memtrip.sqlking.common.Table; @Table( foreignKeys = { - @ForeignKey( - targetTable = "Log", - targetColumn = "id", - localColumn = "logId" - ) + @ForeignKey( + foreignTableName = "Log", + localColumnNames = {"logId"}, + foreignColumnNames = {"id"} + ) + }, + indexes = { + @Index(indexName = "username", + columns = { @IndexColumn(column = "username") } + ) } ) public class User { @@ -27,7 +34,6 @@ public class User { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -35,7 +41,6 @@ public void setId(int id) { public String getUsername() { return username; } - public void setUsername(String newVal) { username = newVal; } @@ -43,7 +48,6 @@ public void setUsername(String newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -51,7 +55,6 @@ public void setTimestamp(long newVal) { public boolean getIsRegistered() { return isRegistered; } - public void setIsRegistered(boolean newVal) { isRegistered = newVal; } @@ -59,7 +62,6 @@ public void setIsRegistered(boolean newVal) { public byte[] getProfilePicture() { return profilePicture; } - public void setProfilePicture(byte[] newVal) { profilePicture = newVal; } @@ -67,7 +69,6 @@ public void setProfilePicture(byte[] newVal) { public double getRating() { return rating; } - public void setRating(double rating) { this.rating = rating; } @@ -75,7 +76,6 @@ public void setRating(double rating) { public int getCount() { return count; } - public void setCount(int count) { this.count = count; } @@ -83,7 +83,6 @@ public void setCount(int count) { public int getLogId() { return logId; } - public void setLogId(int logId) { this.logId = logId; } @@ -91,7 +90,6 @@ public void setLogId(int logId) { public Log getLog() { return log; } - public void setLog(Log log) { this.log = log; } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupData.java b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupData.java index 185815b..c6b2707 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupData.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupData.java @@ -26,7 +26,7 @@ public void setupTestData(SQLProvider sqlProvider) { }; Insert.getBuilder() - .values(data) + .values((Object[])data) .execute(sqlProvider); } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupLog.java b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupLog.java index 31348d5..93434b0 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupLog.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupLog.java @@ -26,7 +26,7 @@ public void setupTestLogs(SQLProvider sqlProvider) { }; Insert.getBuilder() - .values(logs) + .values((Object[]) logs) .execute(sqlProvider); } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupPost.java b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupPost.java index 6b68cab..10f0caf 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupPost.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupPost.java @@ -56,7 +56,7 @@ public void setupTestPosts(SQLProvider sqlProvider) { }; Insert.getBuilder() - .values(posts) + .values((Object[]) posts) .execute(sqlProvider); } diff --git a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupUser.java b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupUser.java index 885269f..a0dc0fe 100644 --- a/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupUser.java +++ b/client/src/tests/java/com/memtrip/sqlking/integration/utils/SetupUser.java @@ -97,7 +97,7 @@ public void setupFourTestUsers(SQLProvider sqlProvider) { }; Insert.getBuilder() - .values(users) + .values((Object[]) users) .execute(sqlProvider); } diff --git a/common/pom.xml b/common/pom.xml index 1a663c9..c06861d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.8 SQLKing common diff --git a/common/src/main/java/com/memtrip/sqlking/common/Check.java b/common/src/main/java/com/memtrip/sqlking/common/Check.java new file mode 100644 index 0000000..d7e0b72 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/Check.java @@ -0,0 +1,25 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public @interface Check { + String checkName() default ""; + String expression() default ""; +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/Column.java b/common/src/main/java/com/memtrip/sqlking/common/Column.java index f440083..e507965 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Column.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Column.java @@ -17,9 +17,19 @@ /** * @author Samuel Kirton [sam@memtrip.com] + * @author Adrian Velcich [adrian@higration.co.za] */ + public @interface Column { - boolean primary_key() default false; - boolean auto_increment() default false; - boolean index() default false; + boolean isIndex() default false; + + PrimaryKey primaryKey() default @PrimaryKey(); // sortOrder = SortOrder.ASC, onConflict = ConflictAction.ROLLBACK); + + NotNull notNull() default @NotNull(onConflict = ConflictAction.NONE); + boolean isUnique() default false; + Check check() default @Check(); + String defaultValue() default ""; + ForeignKey foreignKey() default @ForeignKey(); // Only one column recognised if this is a column constraint + Constraint[] constraints() default {}; + } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java b/common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java new file mode 100644 index 0000000..203d6a0 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java @@ -0,0 +1,36 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum ConflictAction + { + NONE ("NONE"), + ROLLBACK ("ROLLBACK"), + ABORT ("ABORT"), + FAIL ("FAIL"), + IGNORE ("IGNORE"), + REPLACE ("REPLACE"); + + private final String text; + + ConflictAction (String newVal) { text = newVal; } + public final static ConflictAction values[] = values(); + public String toString() { return text; } + } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/Constraint.java b/common/src/main/java/com/memtrip/sqlking/common/Constraint.java new file mode 100644 index 0000000..a0e8c76 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/Constraint.java @@ -0,0 +1,26 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public @interface Constraint { + String constraintName() default ""; + String expression(); + ConflictAction onConflict() default ConflictAction.NONE; +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java b/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java index 9808352..1251bbc 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java +++ b/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java @@ -17,10 +17,17 @@ /** * @author Samuel Kirton [sam@memtrip.com] + * @author Adrian Velcich {adrian@higration.co.za} */ + @SuppressWarnings("WeakerAccess") -public @interface ForeignKey { - String targetTable() default ""; - String targetColumn() default ""; - String localColumn() default ""; +public @interface ForeignKey // table level Foreign Key - allows for a composite key (multiple columns) + { + String foreignTableName () default ""; + String foreignTableAlias () default ""; + String[] foreignColumnNames () default {}; + String[] localColumnNames () default {}; + RIRule updateRule () default RIRule.Cascade; + RIRule deleteRule () default RIRule.Restrict; + String userText() default ""; } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/ForeignKeys.java b/common/src/main/java/com/memtrip/sqlking/common/ForeignKeys.java new file mode 100644 index 0000000..c35b435 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/ForeignKeys.java @@ -0,0 +1,24 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] - 2016-09-16 - Added Composite Foreign Key support + */ + +public @interface ForeignKeys { + ForeignKey[] foreignKeys(); +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/Index.java b/common/src/main/java/com/memtrip/sqlking/common/Index.java new file mode 100644 index 0000000..c498681 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/Index.java @@ -0,0 +1,28 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +import com.memtrip.sqlking.common.IndexColumn; + +public @interface Index { + String indexName() default ""; + IndexColumn[] columns() default {}; + boolean unique() default false; +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/IndexColumn.java b/common/src/main/java/com/memtrip/sqlking/common/IndexColumn.java new file mode 100644 index 0000000..d87f015 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/IndexColumn.java @@ -0,0 +1,25 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] - 2016-09-16 - Added Composite and Unique Index support + */ + +public @interface IndexColumn { + String column(); + SortOrder sortOrder() default SortOrder.ASC; +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/NotNull.java b/common/src/main/java/com/memtrip/sqlking/common/NotNull.java new file mode 100644 index 0000000..c81d75f --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/NotNull.java @@ -0,0 +1,24 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public @interface NotNull { + ConflictAction onConflict() default ConflictAction.NONE; +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java b/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java new file mode 100644 index 0000000..9a82cba --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java @@ -0,0 +1,29 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public @interface PrimaryKey // Table Level Primary key + { + boolean active() default false; + String[] columns() default {}; // Used when the annotation is at table-level + boolean auto_increment () default true; + SortOrder sortOrder() default SortOrder.ASC; + ConflictAction onConflict() default ConflictAction.NONE; + } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/RIRule.java b/common/src/main/java/com/memtrip/sqlking/common/RIRule.java new file mode 100644 index 0000000..570ac12 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/RIRule.java @@ -0,0 +1,43 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public enum RIRule + { + SetNull ("SET NULL"), + SetDefault ("SET DEFAULT"), + Cascade ("CASCADE"), + Restrict ("RESTRICT"), + NotNull ("NOT NULL"), + NoAction ("NO ACTION"); + + private final String name; + public final static RIRule values[] = values(); + + RIRule (String name) + { + this.name = name; + } + + public String getName() + { + return this.name; + } + }; diff --git a/common/src/main/java/com/memtrip/sqlking/common/SQLQuery.java b/common/src/main/java/com/memtrip/sqlking/common/SQLQuery.java index 941f32f..2968262 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/SQLQuery.java +++ b/common/src/main/java/com/memtrip/sqlking/common/SQLQuery.java @@ -20,15 +20,25 @@ /** * @author Samuel Kirton [sam@memtrip.com] + * @author Adrian Velcich [adrian@higration.co.za] */ + @SuppressWarnings("WeakerAccess") public interface SQLQuery { String getTableName(); - String getTableInsertQuery(); + String getTableCreateQuery (); + + String[] getColumnNames(); + + String getCreateIndexesQuery(); String[] getIndexNames(); - String getCreateIndexQuery(); + + String getCreateTriggersQuery(); + String[] getTriggerNames(); + String[] buildUnionInsertQuery(Object[] models); - String[] getColumnNames(); + ContentValues getContentValues(Object model); + T[] retrieveSQLSelectResults(Cursor cursor); } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/SortOrder.java b/common/src/main/java/com/memtrip/sqlking/common/SortOrder.java new file mode 100644 index 0000000..9ece3d5 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/SortOrder.java @@ -0,0 +1,31 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum SortOrder + { + ASC ("ASC"), + DESC ("DESC"); + + private final String text; + + SortOrder (String newVal) { text = newVal; } + public final static SortOrder values[] = values(); + } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/Table.java b/common/src/main/java/com/memtrip/sqlking/common/Table.java index dc170e7..cc13d59 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Table.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Table.java @@ -19,5 +19,9 @@ * @author Samuel Kirton [sam@memtrip.com] */ public @interface Table { + Index[] indexes() default {}; + PrimaryKey primaryKey() default @PrimaryKey(); ForeignKey[] foreignKeys() default {}; + Constraint[] constraints() default {}; + Trigger[] triggers() default {}; } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/Trigger.java b/common/src/main/java/com/memtrip/sqlking/common/Trigger.java new file mode 100644 index 0000000..c7e8954 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/Trigger.java @@ -0,0 +1,30 @@ +/** + * Copyright 2013-present memtrip LTD. + * + * 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.memtrip.sqlking.common; + +/** + * @author Adrian Velcich [adrian@higration.co.za] + */ + +public @interface Trigger { + String triggerName() default ""; + TriggerTime triggerTime() default TriggerTime.NONE; + TriggerType triggerType() default TriggerType.NONE; + String[] updateOfColumnNames() default {}; + boolean forEachRow() default false; + String whenExpression() default ""; + String statement(); +} \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java b/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java new file mode 100644 index 0000000..28b2f6a --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java @@ -0,0 +1,23 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum TriggerTime + { + BEFORE ("BEFORE"), + AFTER ("AFTER"), + INSTEAD_OF ("INSTEAD OF"), + NONE ("NONE"); + + private final String text; + + TriggerTime (String newVal) { text = newVal; } + public final static TriggerTime values[] = values(); + public String toString() { return text; } + } \ No newline at end of file diff --git a/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java b/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java new file mode 100644 index 0000000..1deb572 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java @@ -0,0 +1,23 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum TriggerType + { + DELETE ("DELETE"), + INSERT ("INSERT"), + UPDATE ("UPDATE"), + NONE ("NONE"); + + private final String text; + + TriggerType (String newVal) { text = newVal; } + public final static TriggerType values[] = values(); + public String toString() { return text; } + } \ No newline at end of file diff --git a/preprocessor/buildw.cmd b/preprocessor/buildw.cmd new file mode 100644 index 0000000..f98141f --- /dev/null +++ b/preprocessor/buildw.cmd @@ -0,0 +1,4 @@ +cd ..\common +cmd /C mvn clean install +cd ..\preprocessor +cmd /C mvn clean install diff --git a/preprocessor/pom.xml b/preprocessor/pom.xml index ee38e1a..5a95d56 100644 --- a/preprocessor/pom.xml +++ b/preprocessor/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking preprocessor - 1.1.5 + 1.1.8 SQLKing preprocessor @@ -56,7 +56,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.8 diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/FreeMarker.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/FreeMarker.java index 8ad9d11..f3e0c89 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/FreeMarker.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/FreeMarker.java @@ -10,32 +10,54 @@ import java.io.Writer; import java.util.Map; -final class FreeMarker { +final class FreeMarker + { private Configuration mConfiguration; private static final String TEMPLATE_ENCODING = "UTF-8"; - FreeMarker() throws IOException { + FreeMarker () throws IOException + { mConfiguration = createConfiguration(); - } + } - private Configuration createConfiguration() throws IOException { + private Configuration createConfiguration () throws IOException + { Configuration configuration = new Configuration(Configuration.VERSION_2_3_21); configuration.setDefaultEncoding(TEMPLATE_ENCODING); - configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - configuration.setClassForTemplateLoading(FreeMarker.class,"/"); +// configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + configuration.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER); + configuration.setClassForTemplateLoading(FreeMarker.class, "/"); + return configuration; - } + } - String getMappedFileBodyFromTemplate(String fileName, Map map) { - try { + String getMappedFileBodyFromTemplate (String fileName, Map map) + { + try + { return createFile(fileName, map); - } catch (Exception e) { + } + catch (IOException ioe) + { + ioe.printStackTrace(); + throw new IllegalStateException("Mapping template FAILED: " + ioe.getMessage()); + } + catch (TemplateException te) + { + te.printStackTrace(); + throw new IllegalStateException("Mapping template FAILED: " + te.getMessage()); + } + catch (Exception e) + { + e.printStackTrace(); throw new IllegalStateException("Mapping template FAILED: " + e.getMessage()); + } } - } - private String createFile(String file, Map map) throws TemplateException, IOException { + private String createFile (String file, Map map) throws TemplateException, + IOException + { Template template = getTemplate(file); Writer out = new StringWriter(); @@ -44,9 +66,11 @@ private String createFile(String file, Map map) throws TemplateE out.close(); return output; - } + } - private Template getTemplate(String fileName) throws IOException { + private Template getTemplate (String fileName) throws IOException + { return mConfiguration.getTemplate(fileName); - } -} \ No newline at end of file + } + + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/Processor.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/Processor.java index 5448e24..3f0e606 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/Processor.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/Processor.java @@ -5,6 +5,13 @@ import com.google.googlejavaformat.java.FormatterException; import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.Table; +import com.memtrip.sqlking.common.PrimaryKey; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; +import com.memtrip.sqlking.common.ForeignKey; +import com.memtrip.sqlking.common.Constraint; +import com.memtrip.sqlking.common.Trigger; + import com.memtrip.sqlking.preprocessor.processor.data.Data; import com.memtrip.sqlking.preprocessor.processor.data.parse.ParseAnnotations; import com.memtrip.sqlking.preprocessor.processor.data.validator.MembersHaveGetterSettersValidator; @@ -12,6 +19,8 @@ import com.memtrip.sqlking.preprocessor.processor.data.validator.TableNamesMustBeUniqueValidator; import com.memtrip.sqlking.preprocessor.processor.freemarker.DataModel; +import freemarker.template.TemplateException; + import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; @@ -36,7 +45,7 @@ public synchronized void init(ProcessingEnvironment env) { } @Override - public boolean process(Set annoations, RoundEnvironment env) { + public boolean process(Set annotations, RoundEnvironment env) { Set elements = env.getElementsAnnotatedWith(Table.class); if (elements != null && elements.size() > 0) { @@ -61,7 +70,7 @@ public boolean process(Set annoations, RoundEnvironment e try { String body = mFreeMarker.getMappedFileBodyFromTemplate(GENERATED_FILE_PATH, DataModel.create(data)); createFile(GENERATED_FILE_PACKAGE, GENERATED_FILE_NAME, body); - } catch (IOException | FormatterException e) { + } catch (IOException | FormatterException | TemplateException e) { Context.getInstance().getMessager().printMessage( Diagnostic.Kind.ERROR, e.getMessage() @@ -82,6 +91,13 @@ public Set getSupportedAnnotationTypes() { Set set = new HashSet<>(); set.add(Table.class.getCanonicalName()); set.add(Column.class.getCanonicalName()); + set.add(Index.class.getCanonicalName()); + set.add(IndexColumn.class.getCanonicalName()); + set.add(PrimaryKey.class.getCanonicalName()); + set.add(ForeignKey.class.getCanonicalName()); + set.add(Constraint.class.getCanonicalName()); + set.add(Trigger.class.getCanonicalName()); + return set; } @@ -101,7 +117,7 @@ private Validator[] getValidators(Data data) { }; } - private void createFile(String packageName, String name, String body) throws IOException, FormatterException { + private void createFile(String packageName, String name, String body) throws IOException, FormatterException, TemplateException { String nameWithPackage = packageName + "." + name; JavaFileObject jfo = Context.getInstance().getFiler().createSourceFile(nameWithPackage); diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Column.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Column.java index 6083806..49d0129 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Column.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Column.java @@ -2,18 +2,22 @@ import java.util.List; + public class Column { - private String mName; - private String mClassName; - private String mType; + private String mName; + private String mClassName; + private String mType; + private PrimaryKey mPrimaryKey; + private ForeignKey mForeignKey; private boolean mIsIndex; - private boolean mPrimaryKey; - private boolean mHasAutoIncrement; + private NotNull mNotNull; + private boolean mUnique; + private String mDefaultValue; + private List mConstraints; public String getName() { return mName; } - public void setName(String newVal) { mName = newVal; } @@ -21,7 +25,6 @@ public void setName(String newVal) { public String getClassName() { return mClassName; } - public void setClassName(String newVal) { mClassName = newVal; } @@ -29,39 +32,48 @@ public void setClassName(String newVal) { public String getType() { return mType; } - public void setType(String newVal) { mType = newVal; } - /** - * (Used in Q.java freemarker template) - */ + public PrimaryKey getPrimaryKey() { return mPrimaryKey; } + public void setPrimaryKey(PrimaryKey newVal) { mPrimaryKey = newVal; } + public boolean isIndex() { return mIsIndex; } - public void setIsIndex(boolean newVal) { mIsIndex = newVal; } - public boolean hasPrimaryKey() { - return mPrimaryKey; - } + public NotNull getNotNull () + { + return mNotNull; + } + public void setNotNull (NotNull newVal) + { + this.mNotNull = newVal; + } - public void setHasPrimaryKey(boolean newVal) { - mPrimaryKey = newVal; - } + public boolean isUnique () { return mUnique; } + public void setUnique (boolean mUnique) { this.mUnique = mUnique; } - public boolean hasAutoIncrement() { - return mHasAutoIncrement; - } + public String getDefaultValue () + { + return mDefaultValue; + } + public void setDefaultValue (String newVal) + { + this.mDefaultValue = newVal; + } - public void setHasAutoIncrement(boolean newVal) { - mHasAutoIncrement = newVal; - } + public ForeignKey getForeignKey () { return mForeignKey; } + public void setForeignKey (ForeignKey newVal) { this.mForeignKey = newVal; } + + public List getConstraints () { return mConstraints; } + public void setConstraints (List newVal) { this.mConstraints = newVal; } - public Table getRootTable(List tables) { + public Table getRootTable (List
tables) { if (isJoinable(tables)) { for (Table table : tables) { if (table.getType().equals(mType)) { diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Constraint.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Constraint.java new file mode 100644 index 0000000..50a139c --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Constraint.java @@ -0,0 +1,33 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import java.util.List; +import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; +import com.memtrip.sqlking.common.ConflictAction; + +public class Constraint + { + private String mConstraintName; + private String mConstraintExpression; + private ConflictAction mOnConflict = ConflictAction.NONE; + + public String getConstraintName () + { + return mConstraintName; + } + public void setConstraintName (String newVal) + { + this.mConstraintName = newVal; + } + + public String getConstraintExpression () + { + return mConstraintExpression; + } + public void setConstraintExpression (String newVal) + { + this.mConstraintExpression = newVal; + } + + public ConflictAction getOnConflict () { return mOnConflict; } + public void setOnConflict (ConflictAction newVal) { this.mOnConflict = newVal; } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Data.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Data.java index 970feec..7fef0c3 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Data.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Data.java @@ -4,12 +4,31 @@ public class Data { private List
mTables; + private List mIndexes; + private PrimaryKey mPrimaryKey; + private List mForeignKeys; + private List mConstraints; + private List mTriggers; public List
getTables() { return mTables; } - public void setTables(List
newVal) { mTables = newVal; } + + public List getIndexes() { return mIndexes; } + public void setIndexes(List newVal) { mIndexes = newVal; } + + public PrimaryKey getPrimaryKey () { return mPrimaryKey; } + public void setPrimaryKey (PrimaryKey newVal) { this.mPrimaryKey = newVal; } + + public List getForeignKeys () { return mForeignKeys; } + public void setForeignKeys (List newVal) { this.mForeignKeys = newVal; } + + public List getConstraints () { return mConstraints; } + public void setConstraints (List newVal) { this.mConstraints = mConstraints; } + + public List getTriggers () { return mTriggers; } + public void setTriggers (List newVal) { this.mTriggers = newVal; } } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/ForeignKey.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/ForeignKey.java index 908b6e1..443e685 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/ForeignKey.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/ForeignKey.java @@ -1,31 +1,54 @@ package com.memtrip.sqlking.preprocessor.processor.data; -public class ForeignKey { - private String mTable; - private String mThisColumn; - private String mForeignColumn; +/** + * Author: A.Velcich + */ - public String getTable() { - return mTable; - } +import java.util.List; +import com.memtrip.sqlking.common.RIRule; - public void setTable(String newVal) { - mTable = newVal; - } +public class ForeignKey + { + private String mForeignTableName; + private String mForeignTableAliasName; + private List mLocalColumnNames; + private List mForeignColumnNames; + private RIRule mRIUpdateRule; + private RIRule mRIDeleteRule; - public String getThisColumn() { - return mThisColumn; + public String getForeignTableName() { + return mForeignTableName; + } + public void setForeignTableName(String newVal) { + mForeignTableName = newVal; } - public void setLocalColumn(String newVal) { - mThisColumn = newVal; + public String getForeignTableAliasName () { return mForeignTableAliasName; } + public void setForeignTableAliasName (String newVal) { this.mForeignTableAliasName = newVal; } + + public List getLocalColumnNames () { return mLocalColumnNames; } + public void setLocalColumnNames(List newVal) { mLocalColumnNames = newVal; } + + public List getForeignColumnNames() { return mForeignColumnNames; } + public void setForeignColumnNames(List newVals) { + mForeignColumnNames = newVals; } - public String getForeignColumn() { - return mForeignColumn; + public RIRule getRIUpdateRule () + { + return mRIUpdateRule; + } + public void setRIUpdateRule (RIRule newVal) + { + this.mRIUpdateRule = newVal; } - public void setTargetColumn(String newVal) { - mForeignColumn = newVal; + public RIRule getRIDeleteRule () + { + return mRIDeleteRule; + } + public void setRIDeleteRule (RIRule newVal) + { + this.mRIDeleteRule = newVal; } } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java new file mode 100644 index 0000000..33ef9b1 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java @@ -0,0 +1,40 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import java.util.List; + +public class Index { + private String mTableName; + private String mIndexName; + private boolean mIsUnique; + private List mColumns; + + public String getTableName () { return mTableName; } + public void setTableName (String newVal) { this.mTableName = newVal; } + + public String getIndexName () + { + return mIndexName; + } + public void setIndexName (String newVal) + { + this.mIndexName = newVal; + } + + public List getColumns () + { + return mColumns; + } + public void setColumns (List newVal) + { + this.mColumns = newVal; + } + + public boolean isUnique () + { + return mIsUnique; + } + public void setUnique (boolean newVal) + { + this.mIsUnique = newVal; + } +} \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java new file mode 100644 index 0000000..cd4ae93 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java @@ -0,0 +1,26 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import com.memtrip.sqlking.common.SortOrder; + +public class IndexColumn { + private String mColumn; + private SortOrder mSortOrder; + + public String getColumn () + { + return mColumn; + } + public void setColumn (String newVal) + { + this.mColumn = newVal; + } + + public SortOrder getSortOrder () + { + return mSortOrder; + } + public void setSortOrder (SortOrder newVal) + { + this.mSortOrder = newVal; + } +} \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Indexes.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Indexes.java new file mode 100644 index 0000000..5780dce --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Indexes.java @@ -0,0 +1,29 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import java.util.List; + +public class Indexes + { + private String tableName; + private Index[] mIndexes; + + public String getTableName () + { + return tableName; + } + + public void setTableName (String tableName) + { + this.tableName = tableName; + } + + public Index[] getIndexes () + { + return mIndexes; + } + + public void setIndexes (List newVal) + { + this.mIndexes = newVal.toArray(new Index[newVal.size()]); + } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/NotNull.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/NotNull.java new file mode 100644 index 0000000..7cbfc04 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/NotNull.java @@ -0,0 +1,15 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +/** + * Author: A.Velcich + */ + +import com.memtrip.sqlking.common.ConflictAction; + +public class NotNull + { + private ConflictAction mOnConflict = ConflictAction.NONE; + + public ConflictAction getOnConflict () { return mOnConflict; } + public void setOnConflict (ConflictAction newVal) { this.mOnConflict = newVal; } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/PrimaryKey.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/PrimaryKey.java new file mode 100644 index 0000000..a45643d --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/PrimaryKey.java @@ -0,0 +1,23 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import com.memtrip.sqlking.common.ConflictAction; + +public class PrimaryKey + { + private boolean mActive; + private boolean mAutoNumber; + private String[] mColumns; + private ConflictAction mOnConflict; + + public boolean isActive () { return mActive; } + public void setIsActive (boolean newVal) { this.mActive = newVal; } + + public boolean isAutoNumber () { return mAutoNumber; } + public void setAutoNumber (boolean newVal) { this.mAutoNumber = newVal; } + + public String[] getColumns () { return mColumns; } + public void setColumns (String[] newVal) { this.mColumns = newVal; } + + public ConflictAction getOnConflict () { return mOnConflict; } + public void setOnConflict (ConflictAction newVal) { mOnConflict = newVal; } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java index 9c26d87..95148ec 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java @@ -10,12 +10,15 @@ public class Table { private String mPackage; private String mType; private List mColumns; + private PrimaryKey mPrimaryKey; private List mForeignKeys; + private List mIndexes; + private List mConstraints; + private List mTriggers; public Element getElement() { return mElement; } - public void setElement(Element newVal) { mElement = newVal; } @@ -23,26 +26,20 @@ public void setElement(Element newVal) { public String getName() { return mName; } - public void setName(String newVal) { mName = newVal; } - public String getPackage() { + public String getPackage () { return mPackage; } - public void setPackage(String newVal) { mPackage = newVal; } - /** - * (Used in Q.java freemarker template) - */ public String getType() { return mType; } - public void setType(String newVal) { mType = newVal; } @@ -50,23 +47,33 @@ public void setType(String newVal) { public List getColumns() { return mColumns; } - public void setColumns(List newVal) { mColumns = newVal; } + public PrimaryKey getPrimaryKey() { return mPrimaryKey; } + public void setPrimaryKey(PrimaryKey newVal) { mPrimaryKey = newVal; } + public List getForeignKeys() { - return mForeignKeys; + return mForeignKeys; } - public void setForeignKeys(List newVal) { - mForeignKeys = newVal; + mForeignKeys = newVal; + } + + public List getIndexes() { + return mIndexes; + } + public void setIndexes(List newVal) { + mIndexes = newVal; } - /** - * (Used in Q.java freemarker template) - * @return all columns ignoring any object mappings - */ + public List getConstraints () { return mConstraints; } + public void setConstraints (List newVal) { this.mConstraints = newVal; } + + public List getTriggers () { return mTriggers; } + public void setTriggers (List newVal) { this.mTriggers = newVal; } + public List getMutableColumns(List
tables) { List withoutObjects = new ArrayList<>(); diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Trigger.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Trigger.java new file mode 100644 index 0000000..9a7e780 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Trigger.java @@ -0,0 +1,49 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +/** + * Author: A.Velcich + */ + +import java.util.List; +import com.memtrip.sqlking.common.TriggerTime; +import com.memtrip.sqlking.common.TriggerType; + +public class Trigger + { + private String mTriggerName; + private TriggerType mTriggerType; + private TriggerTime mTriggerTime; + private List mOnUpdateOfColumnNames; + private boolean mForEachRow; + private String mWhenExpression; + private String mStatement; + + public String getTriggerName () + { + return mTriggerName; + } + public void setTriggerName (String newVal) + { + this.mTriggerName = newVal; + } + + public TriggerType getTriggerType () { return mTriggerType; } + public void setTriggerType (TriggerType newVal) { this.mTriggerType = newVal; } + + public TriggerTime getTriggerTime () { return mTriggerTime; } + public void setTriggerTime (TriggerTime mTriggerTime) { this.mTriggerTime = mTriggerTime; } + + public List getOnUpdateOfColumnNames () { return mOnUpdateOfColumnNames; } + public void setOnUpdateOfColumnNames (List mOnUpdateOfColumnNames) { + this.mOnUpdateOfColumnNames = mOnUpdateOfColumnNames; + } + + public boolean isForEachRow () { return mForEachRow; } + public void setForEachRow (boolean mForEachRow) { this.mForEachRow = mForEachRow; } + + public String getWhenExpression () { return mWhenExpression; } + public void setWhenExpression (String newVal) { this.mWhenExpression = newVal; } + + public String getStatement () { return mStatement; } + public void setStatement (String mStatement) { this.mStatement = mStatement; } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseColumnAnnotation.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseColumnAnnotation.java index d350944..2b0a551 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseColumnAnnotation.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseColumnAnnotation.java @@ -1,29 +1,45 @@ package com.memtrip.sqlking.preprocessor.processor.data.parse; import com.memtrip.sqlking.preprocessor.processor.data.Column; +import com.memtrip.sqlking.preprocessor.processor.data.Index; +import com.memtrip.sqlking.preprocessor.processor.data.Constraint; +import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; +import com.memtrip.sqlking.preprocessor.processor.data.PrimaryKey; +import com.memtrip.sqlking.preprocessor.processor.data.NotNull; import javax.lang.model.element.Element; import javax.lang.model.element.Name; import javax.lang.model.type.TypeMirror; +import java.util.ArrayList; +import java.util.List; class ParseColumnAnnotation { static Column parseColumn(Element element) { String name = assembleName(element); - boolean isIndex = assembleIsIndex(element); - boolean hasPrimaryKey = assemblePrimaryKey(element); - boolean hasAutoIncrement = assembleAutoIncrement(element); String type = assembleType(element); String className = assembleClassName(type); + boolean isIndex = assembleIsIndex(element); + PrimaryKey primaryKey = assemblePrimaryKey(element); + NotNull notNull = assembleNotNull(element); + String defaultValue = assembleDefaultValue(element); + ForeignKey foreignKey = assembleForeignKey(element); + List constraints = assembleConstraints(element); + + System.out.println(" ++ column: " + name); + Column column = new Column(); column.setName(name); - column.setIsIndex(isIndex); - column.setHasPrimaryKey(hasPrimaryKey); - column.setHasAutoIncrement(hasAutoIncrement); column.setType(type); column.setClassName(className); + column.setIsIndex(isIndex); + column.setPrimaryKey(primaryKey); + column.setNotNull(notNull); + column.setDefaultValue(defaultValue); + column.setConstraints(constraints); + column.setForeignKey(foreignKey); return column; } @@ -45,16 +61,95 @@ private static String assembleClassName(String type) { private static boolean assembleIsIndex(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column != null && column.index(); + return column != null && column.isIndex(); + } + + private static PrimaryKey assemblePrimaryKey(Element element) { + com.memtrip.sqlking.common.Column columnAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + String columnName = element.getSimpleName().toString(); + + com.memtrip.sqlking.common.PrimaryKey primaryKeyAnnotation = columnAnnotation.primaryKey(); + + if (primaryKeyAnnotation != null && primaryKeyAnnotation.active() == true) + { + PrimaryKey primaryKey = new PrimaryKey(); + + primaryKey.setIsActive(true); + primaryKey.setColumns(new String[] {columnName}); + primaryKey.setAutoNumber(primaryKeyAnnotation.auto_increment()); + primaryKey.setOnConflict (primaryKeyAnnotation.onConflict()); + + return primaryKey; + } + return null; } - private static boolean assemblePrimaryKey(Element element) { + private static NotNull assembleNotNull(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column.primary_key(); + com.memtrip.sqlking.common.NotNull notNullAnnotation = column.notNull(); + + NotNull notNull = null; + + if (column.notNull() != null) + { + notNull = new NotNull(); + + notNull.setOnConflict(notNullAnnotation.onConflict()); + } + + return notNull; } - private static boolean assembleAutoIncrement(Element element) { + private static String assembleDefaultValue(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column.auto_increment(); + return column.defaultValue(); } + + private static ForeignKey assembleForeignKey(Element element) { + com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + com.memtrip.sqlking.common.ForeignKey foreignKeyAnnotation = column.foreignKey(); + + ForeignKey foreignKey = new ForeignKey(); + + foreignKey.setForeignTableName(foreignKeyAnnotation.foreignTableName()); + + List localColumnNames = new ArrayList<>(); + + for (String columnName : foreignKeyAnnotation.localColumnNames()) + { + localColumnNames.add(columnName); + } + + List foreignColumnNames = new ArrayList<>(); + + for (String columnName : foreignKeyAnnotation.foreignColumnNames()) + { + foreignColumnNames.add(columnName); + } + + foreignKey.setRIUpdateRule(foreignKeyAnnotation.updateRule()); + foreignKey.setRIDeleteRule(foreignKeyAnnotation.deleteRule()); + + return foreignKey; + } + + private static List assembleConstraints(Element element) { + com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + com.memtrip.sqlking.common.Constraint[] constraintsAnnotation = column.constraints(); + + List constraints = new ArrayList<>(); + + for (com.memtrip.sqlking.common.Constraint constraintAnnotation : constraintsAnnotation) + { + Constraint constraint = new Constraint(); + + constraint.setConstraintName(""); + constraint.setConstraintExpression(constraintAnnotation.expression()); + constraint.setOnConflict(constraintAnnotation.onConflict()); + + constraints.add(constraint); + } + return constraints; + } + } diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseTableAnnotation.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseTableAnnotation.java index 740c3ad..99bd186 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseTableAnnotation.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/parse/ParseTableAnnotation.java @@ -1,34 +1,59 @@ package com.memtrip.sqlking.preprocessor.processor.data.parse; +import com.memtrip.sqlking.common.ConflictAction; + +import com.memtrip.sqlking.common.TriggerType; +import com.memtrip.sqlking.common.TriggerTime; +import com.memtrip.sqlking.common.SortOrder; + import com.memtrip.sqlking.preprocessor.processor.Context; import com.memtrip.sqlking.preprocessor.processor.data.Column; +import com.memtrip.sqlking.preprocessor.processor.data.PrimaryKey; import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; +import com.memtrip.sqlking.preprocessor.processor.data.Index; +import com.memtrip.sqlking.preprocessor.processor.data.IndexColumn; import com.memtrip.sqlking.preprocessor.processor.data.Table; +import com.memtrip.sqlking.preprocessor.processor.data.Constraint; +import com.memtrip.sqlking.preprocessor.processor.data.Trigger; import javax.lang.model.element.Element; import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import java.util.ArrayList; import java.util.List; +import freemarker.ext.beans.StringModel; import static com.memtrip.sqlking.preprocessor.processor.data.parse.ParseColumnAnnotation.parseColumn; -class ParseTableAnnotation { +class ParseTableAnnotation + { + static Table parseTable(Element element) + { + String name = assembleName(element); + String tablePackage = assemblePackage(element); + String type = tablePackage + "." + name; - static Table parseTable(Element element) { + System.out.println("++ Preprocessing table: " + type); - String name = assembleName(element); - String tablePackage = assemblePackage(element); - String type = tablePackage + "." + name; - List columns = assembleColumns(element); + List columns = assembleColumns(element); + PrimaryKey primaryKey = assemblePrimaryKey(element); + List foreignKeys = assembleForeignKeys(element); + List indexes = assembleIndexes(element, columns); + List constraints = assembleConstraints(element); + List triggers = assembleTriggers(element); Table table = new Table(); + table.setElement(element); table.setName(name); table.setPackage(tablePackage); table.setType(type); table.setColumns(columns); - table.setForeignKeys(assembleForeignKeys(element)); + table.setPrimaryKey(primaryKey); + table.setForeignKeys(foreignKeys); + table.setIndexes(indexes); + table.setConstraints (constraints); + table.setTriggers (triggers); return table; } @@ -54,25 +79,179 @@ private static List assembleColumns(Element element) { } } } - return columns; } - private static List assembleForeignKeys(Element element) { + private static PrimaryKey assemblePrimaryKey(Element element) { + com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); + com.memtrip.sqlking.common.PrimaryKey primaryKeyAnnotation = tableAnnotation.primaryKey(); + + if (primaryKeyAnnotation != null && primaryKeyAnnotation.active() == true) + { + PrimaryKey primaryKey = new PrimaryKey(); + + primaryKey.setColumns(primaryKeyAnnotation.columns()); + primaryKey.setAutoNumber(primaryKeyAnnotation.auto_increment()); + primaryKey.setOnConflict (primaryKeyAnnotation.onConflict()); + + return primaryKey; + } + return null; + } + + private static List assembleIndexes (Element element, List columns) + { + com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); + com.memtrip.sqlking.common.Index[] indexesAnnotation = tableAnnotation.indexes(); + + String tableName = element.getSimpleName().toString(); + + List indexes = new ArrayList<>(); + + for (com.memtrip.sqlking.common.Index indexAnnotation : indexesAnnotation) + { + Index index = new Index(); + + index.setTableName(tableName); + index.setIndexName(indexAnnotation.indexName()); + index.setUnique(indexAnnotation.unique()); + + com.memtrip.sqlking.common.IndexColumn[] indexColumnsAnnotation = indexAnnotation.columns(); + + List idxColumns = new ArrayList<>(); + + for (com.memtrip.sqlking.common.IndexColumn columnAnnotation : indexColumnsAnnotation) + { + IndexColumn indexColumn = new IndexColumn(); + + indexColumn.setColumn(columnAnnotation.column()); + indexColumn.setSortOrder(columnAnnotation.sortOrder()); + + idxColumns.add(indexColumn); + } + + index.setColumns(idxColumns); + + indexes.add(index); + } + + for (Column column : columns) + { + if (column.isIndex()) + { + Index index = new Index(); + + index.setTableName(tableName); + index.setIndexName(column.getName()); + index.setUnique(false); + + List idxColumns = new ArrayList<>(); + + IndexColumn columnIndex = new IndexColumn(); + + columnIndex.setColumn(column.getName()); + columnIndex.setSortOrder(SortOrder.ASC); + + idxColumns.add(columnIndex); + index.setColumns(idxColumns); + + indexes.add(index); + } + } + + return indexes; + } + + private static List assembleForeignKeys(Element element) + { com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); com.memtrip.sqlking.common.ForeignKey[] foreignKeysAnnotation = tableAnnotation.foreignKeys(); List foreignKeys = new ArrayList<>(); - for (com.memtrip.sqlking.common.ForeignKey annotation : foreignKeysAnnotation) { + for (com.memtrip.sqlking.common.ForeignKey fkAnnotation : foreignKeysAnnotation) + { ForeignKey foreignKey = new ForeignKey(); - foreignKey.setTable(annotation.targetTable()); - foreignKey.setTargetColumn(annotation.targetColumn()); - foreignKey.setLocalColumn(annotation.localColumn()); + foreignKey.setForeignTableName(fkAnnotation.foreignTableName()); + foreignKey.setForeignTableAliasName (fkAnnotation.foreignTableAlias()); + + List foreignColumnNames = new ArrayList<>(); + for (String columnName : fkAnnotation.foreignColumnNames()) + { + foreignColumnNames.add(columnName); + } + foreignKey.setForeignColumnNames(foreignColumnNames); + + List localColumnNames = new ArrayList<>(); + for (String columnName : fkAnnotation.localColumnNames()) + { + localColumnNames.add(columnName); + } + + foreignKey.setLocalColumnNames(localColumnNames); foreignKeys.add(foreignKey); - } + } return foreignKeys; - } -} \ No newline at end of file + } + + private static List assembleConstraints(Element element) + { + com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); + com.memtrip.sqlking.common.Constraint[] constraintsAnnotation = tableAnnotation.constraints(); + + List constraints = new ArrayList<>(); + + for (com.memtrip.sqlking.common.Constraint constraintAnnotation : constraintsAnnotation) + { + Constraint constraint = new Constraint(); + + constraint.setConstraintName(constraintAnnotation.constraintName()); + constraint.setConstraintExpression(constraintAnnotation.expression()); + constraint.setOnConflict(constraintAnnotation.onConflict()); + + constraints.add(constraint); + } + + return constraints; + } + + private static List assembleTriggers(Element element) + { + com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); + com.memtrip.sqlking.common.Trigger[] triggersAnnotation = tableAnnotation.triggers(); + + List triggers = new ArrayList<>(); + + if (triggersAnnotation != null && triggersAnnotation.length > 0) + { + for (com.memtrip.sqlking.common.Trigger triggerAnnotation : triggersAnnotation) + { + Trigger trigger = new Trigger(); + + trigger.setTriggerName(triggerAnnotation.triggerName()); + trigger.setTriggerTime(triggerAnnotation.triggerTime()); + trigger.setTriggerType(triggerAnnotation.triggerType()); + + List onUpdateColumns = new ArrayList<>(); + + for (String columnName : triggerAnnotation.updateOfColumnNames()) + { + onUpdateColumns.add(columnName); + } + + trigger.setOnUpdateOfColumnNames(onUpdateColumns); + + trigger.setForEachRow(triggerAnnotation.forEachRow()); + trigger.setWhenExpression(triggerAnnotation.whenExpression()); + trigger.setStatement(triggerAnnotation.statement()); + + triggers.add(trigger); + } + } + + return triggers; + } + + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/PrimaryKeyMustBeUnique.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/PrimaryKeyMustBeUnique.java index 7aaa482..82138aa 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/PrimaryKeyMustBeUnique.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/PrimaryKeyMustBeUnique.java @@ -5,6 +5,7 @@ import com.memtrip.sqlking.preprocessor.processor.data.Column; import com.memtrip.sqlking.preprocessor.processor.data.Data; import com.memtrip.sqlking.preprocessor.processor.data.Table; +import com.memtrip.sqlking.preprocessor.processor.data.PrimaryKey; import java.util.List; @@ -16,12 +17,22 @@ public PrimaryKeyMustBeUnique(Data data) { this.data = data; } - private boolean primaryKeyIsUniqueInColumns(List columns) { + private boolean primaryKeyIsUniqueInColumns(Table table) { int occurrences = 0; - if (columns != null) { - for (Column column : columns) { - if (column.hasPrimaryKey()) { + PrimaryKey primaryKey = table.getPrimaryKey(); + + if (primaryKey != null && primaryKey.getColumns().length > 0) + { + occurrences++; + } + + if (table.getColumns() != null) { + for (Column column : table.getColumns()) { + + primaryKey = column.getPrimaryKey(); + + if (primaryKey != null && primaryKey.getColumns().length > 0 ) { occurrences++; } } @@ -33,7 +44,7 @@ private boolean primaryKeyIsUniqueInColumns(List columns) { @Override public void validate() throws ValidatorException { for (Table table : data.getTables()) { - if (primaryKeyIsUniqueInColumns(table.getColumns())) { + if (primaryKeyIsUniqueInColumns(table)) { throw new ValidatorException( table.getElement(), "[Duplicate primary_key's found in @Table: `" + table.getName() diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/TableNamesMustBeUniqueValidator.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/TableNamesMustBeUniqueValidator.java index d3c97b7..f686c2b 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/TableNamesMustBeUniqueValidator.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/validator/TableNamesMustBeUniqueValidator.java @@ -14,7 +14,7 @@ public TableNamesMustBeUniqueValidator(Data data) { mData = data; } - private Table findDuplicateTable(List
tables) { + private Table findDuplicateTable(List
tables) { for (Table table : tables) { Table duplicateTable = getDuplicateTable(table, tables); if (duplicateTable != null) { @@ -25,7 +25,7 @@ private Table findDuplicateTable(List
tables) { return null; } - private Table getDuplicateTable(Table check, List
tables) { + private Table getDuplicateTable(Table check, List
tables) { int occurrences = 0; for (Table table : tables) { diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/DataModel.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/DataModel.java index 4d3545d..80dbd16 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/DataModel.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/DataModel.java @@ -9,14 +9,29 @@ public class DataModel { private static final String TABLES = "tables"; + private static final String INDEXES = "indexes"; + private static final String PRIMARY_KEY = "primaryKey"; + private static final String FOREIGN_KEYS = "foreignKeys"; + private static final String CONSTRAINTS = "constraints"; + private static final String TRIGGERS = "triggers"; public static Map create(Data data) { Map map = new HashMap<>(); map.put(TABLES, data.getTables()); + map.put(INDEXES, data.getIndexes()); +// map.put(PRIMARY_KEY, data.getPrimaryKey()); +// map.put(FOREIGN_KEYS, data.getForeignKeys()); +// map.put(CONSTRAINTS, data.getConstraints()); + map.put(TRIGGERS, data.getTriggers()); + + map.putAll(AssembleCreateTableMethod.getMethodMap()); + map.putAll(AssembleCreateIndexesMethod.getMethodMap()); +// map.putAll(AssembleCreateForeignKeysMethod.getMethodMap()); +// map.putAll(AssembleCreateConstraintsMethod.getMethodMap()); + map.putAll(AssembleCreateTriggersMethod.getMethodMap()); map.putAll(GetCursorGetterMethod.getMethodMap()); map.putAll(GetInsertValueMethod.getMethodMap()); - map.putAll(AssembleCreateTableMethod.getMethodMap()); map.putAll(FormatConstantMethod.getMethodMap()); map.putAll(JoinSettersMethod.getMethodMap()); map.putAll(JoinReferencesMethod.getMethodMap()); diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateConstraintsMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateConstraintsMethod.java new file mode 100644 index 0000000..4c565ff --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateConstraintsMethod.java @@ -0,0 +1,78 @@ +package com.memtrip.sqlking.preprocessor.processor.freemarker.method; + +import com.memtrip.sqlking.common.ConflictAction; + +import com.memtrip.sqlking.preprocessor.processor.data.Constraint; +import com.memtrip.sqlking.preprocessor.processor.data.Table; + +import freemarker.ext.beans.StringModel; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModelException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AssembleCreateConstraintsMethod implements TemplateMethodModelEx + { + private static final String ASSEMBLE_CREATE_CONSTRAINTS = "assembleCreateConstraints"; + + public static Map getMethodMap () + { + Map map = new HashMap<>(); + map.put(ASSEMBLE_CREATE_CONSTRAINTS, new AssembleCreateConstraintsMethod()); + return map; + } + + /** + * Build a list of create Constraint statement baseds on the provided table + * + * @param table + * @param constraints The list of Constraints that will have create statements created for them + * @return A SQL statement that will create the constraints during CREATE TABLE + */ + private String buildCreateConstraintStatements (Table table) + { + StringBuilder sb = new StringBuilder(); + StringBuilder sbDebug = new StringBuilder(); + + List constraintList = table.getConstraints(); + + for (Constraint constraint : constraintList) + { + sb.append(" CONSTRAINT ") + .append(constraint.getConstraintName()) + .append(" ") + .append(constraint.getConstraintExpression()) + .append(" ON CONFLICT ") + .append(constraint.getOnConflict().toString()) + .append(","); + } + + if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } + + return "\"" + sb.toString() + "\""; + } + + + @Override + public Object exec (List arguments) throws TemplateModelException + { + Object tableValue = arguments.get(0); + + Table table; + + if (tableValue instanceof StringModel) + { + StringModel stringModel = (StringModel)tableValue; + table = (Table)stringModel.getAdaptedObject(Table.class); + } + else + { + throw new IllegalStateException("The assembleCreateConstraintStatements Table argument must be type of " + + "com.memtrip.sqlking.preprocessor.processor.data.Table"); + } + + return buildCreateConstraintStatements(table); + } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateForeignKeysMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateForeignKeysMethod.java new file mode 100644 index 0000000..727cb0c --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateForeignKeysMethod.java @@ -0,0 +1,88 @@ +package com.memtrip.sqlking.preprocessor.processor.freemarker.method; + +import com.memtrip.sqlking.preprocessor.processor.data.IndexColumn; +import com.memtrip.sqlking.preprocessor.processor.data.Index; +import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; +import com.memtrip.sqlking.preprocessor.processor.data.Table; +import freemarker.ext.beans.StringModel; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModelException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AssembleCreateForeignKeysMethod implements TemplateMethodModelEx + { + private static final String ASSEMBLE_CREATE_FOREIGN_KEYS = "assembleCreateCreateForeignKeys"; + + public static Map getMethodMap () + { + Map map = new HashMap<>(); + map.put(ASSEMBLE_CREATE_FOREIGN_KEYS, new AssembleCreateForeignKeysMethod()); + return map; + } + + /** + * Build a list of create ForeignKey statement baseds on the provided tableName + * + * @param tableName + * @param foreignKeys The list of Foreign Keys that will have create statements created for them + * @return A SQL statement that will create a table + */ + private String buildCreateForeignKeyStatements (Table table) + { + StringBuilder sb = new StringBuilder(); + StringBuilder sbDebug = new StringBuilder(); + + List foreignKeyList = table.getForeignKeys(); + + for (ForeignKey foreignKey : foreignKeyList) + { + sbDebug.append("On " + table.getName() + ", Foreign Key references table ") + .append(foreignKey.getForeignTableName()) + .append(" local columns (") + .append(foreignKey.getLocalColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append(") foreign columns (") + .append(foreignKey.getForeignColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append(");"); + + System.out.println("\"" + sbDebug.toString() + "\";"); + } + + for (ForeignKey foreignKey : foreignKeyList) + { + sb.append("CONSTRAINT FOREIGN KEY(") + .append(foreignKey.getLocalColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append(") REFERENCES ") + .append(foreignKey.getForeignTableName()) + .append("(") + .append(foreignKey.getForeignColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append(") "); + } + + return "\"" + sb.toString() + "\""; + } + + + @Override + public Object exec (List arguments) throws TemplateModelException + { + Object tableValue = arguments.get(0); + + Table table; + + if (tableValue instanceof StringModel) + { + StringModel stringModel = (StringModel)tableValue; + table = (Table)stringModel.getAdaptedObject(Table.class); + } + else + { + throw new IllegalStateException("The assembleCreateForeignKeyStatements Table argument must be type of " + + "com.memtrip.sqlking.preprocessor.processor.data.Table"); + } + + return buildCreateForeignKeyStatements(table); + } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java new file mode 100644 index 0000000..8a40edf --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java @@ -0,0 +1,82 @@ +package com.memtrip.sqlking.preprocessor.processor.freemarker.method; + +import com.memtrip.sqlking.preprocessor.processor.data.IndexColumn; +import com.memtrip.sqlking.preprocessor.processor.data.Index; +import com.memtrip.sqlking.preprocessor.processor.data.Table; +import freemarker.ext.beans.StringModel; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModelException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AssembleCreateIndexesMethod implements TemplateMethodModelEx { + + private static final String ASSEMBLE_CREATE_INDEXES = "assembleCreateIndexes"; + + public static Map getMethodMap() { + Map map = new HashMap<>(); + map.put(ASSEMBLE_CREATE_INDEXES, new AssembleCreateIndexesMethod()); + return map; + } + + private AssembleCreateIndexesMethod() { + } + + private String buildIndexName(Index index) + { + return index.getTableName().toLowerCase() + "_" + index.getIndexName().toLowerCase() + "_index"; // note: must match the syntax in resources/Q.Java + } + /** + * Build a list of create Index statement baseds on the provided tableName + * @param indexes The list of indexes that will have create statements created for them + * @return A SQL statement that will create a table + */ + private String buildCreateIndexStatements(Table table) + { + StringBuilder sb = new StringBuilder(); + + List indexes = table.getIndexes(); + + for (Index index : indexes) + { + sb.append("CREATE INDEX " + buildIndexName(index) + " ON " + index.getTableName() + " ("); + + for (IndexColumn indexColumn : index.getColumns()) + { + sb.append(indexColumn.getColumn()) + .append(" ") + .append(indexColumn.getSortOrder()) + .append(","); + } + + sb.deleteCharAt(sb.length() - 1); + + sb.append(");"); + + } + + System.out.println("++ " + sb.toString()); + + return "\"" + sb.toString() + "\""; + } + + @Override + public Object exec(List arguments) throws TemplateModelException { + Object tableValue = arguments.get(0); + + Table table; + if (tableValue instanceof StringModel) + { + StringModel stringModel = (StringModel) tableValue; + table = (Table)stringModel.getAdaptedObject(Table.class); + } + else + { + throw new IllegalStateException("The assembleCreateIndexStatements argument must be type of com.memtrip.sqlking.preprocessor.model.Table"); + } + + return buildCreateIndexStatements(table); + } +} \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTableMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTableMethod.java index d378a17..b42f911 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTableMethod.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTableMethod.java @@ -1,8 +1,16 @@ package com.memtrip.sqlking.preprocessor.processor.freemarker.method; +import com.memtrip.sqlking.common.ConflictAction; + import com.memtrip.sqlking.preprocessor.processor.data.Column; import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; +import com.memtrip.sqlking.preprocessor.processor.data.PrimaryKey; +import com.memtrip.sqlking.preprocessor.processor.data.IndexColumn; +import com.memtrip.sqlking.preprocessor.processor.data.Index; import com.memtrip.sqlking.preprocessor.processor.data.Table; +import com.memtrip.sqlking.preprocessor.processor.data.Constraint; +import com.memtrip.sqlking.preprocessor.processor.data.Trigger; + import freemarker.ext.beans.StringModel; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModelException; @@ -24,59 +32,152 @@ public class AssembleCreateTableMethod implements TemplateMethodModelEx { public static Map getMethodMap() { Map map = new HashMap<>(); map.put(ASSEMBLE_CREATE_TABLE, new AssembleCreateTableMethod()); + return map; } private AssembleCreateTableMethod() { - } /** * Build a create table statement based on the provided tableName and members * @param table The table that the statement will create - * @return A SQL statement that will create a table + * @return A SQL statement that will create a table, and any defined Indexes and Foreign Keys */ - private String buildCreateTableStatement(Table table, List
tables) { - StringBuilder statementBuilder = new StringBuilder(); + private String buildCreateTableStatement(Table table, List
tables) + { + StringBuilder sb = new StringBuilder(); + int tableConstraintCount = 0; - statementBuilder.append("CREATE TABLE "); - statementBuilder.append(table.getName()); - statementBuilder.append(" ("); + sb.append("CREATE TABLE "); + sb.append(table.getName()); + sb.append(" ("); - for (int i = 0; i < table.getColumns().size(); i++) { +//......Columns and column contraints + + for (int i = 0; i < table.getColumns().size(); i++) + { Column column = table.getColumns().get(i); - if (!column.isJoinable(tables)) { - statementBuilder.append(column.getName()); - statementBuilder.append(" "); - statementBuilder.append(getSQLDataTypeFromClassRef(column.getType())); + if (!column.isJoinable(tables)) + { + sb.append(column.getName()) + .append(" ") + .append(getSQLDataTypeFromClassRef(column.getType())); + + if (column.getPrimaryKey() != null && column.getPrimaryKey().isActive() == true) + { + sb.append(" PRIMARY KEY"); + + if (column.getPrimaryKey().isAutoNumber()) + { + sb.append(" AUTOINCREMENT"); + } + + if (column.getPrimaryKey().getOnConflict() != ConflictAction.NONE) + { + sb.append(" ON CONFLICT ") + .append (column.getPrimaryKey().getOnConflict().toString()); + } + } + + if (column.getNotNull() != null) + { + if (column.getNotNull().getOnConflict() != ConflictAction.NONE ) + { + sb.append(" NOT NULL "); + sb.append(" ON CONFLICT "); + sb.append(column.getNotNull().getOnConflict().toString()); + } + } + else if (column.getDefaultValue().length() > 0 ) + { + sb.append(" DEFAULT ") + .append(column.getDefaultValue()); + } + else if (column.getForeignKey().getForeignTableName().length() > 0) + { + ForeignKey foreignKey = column.getForeignKey(); + + sb.append(" FOREIGN KEY /* column */") + .append("(") + .append(foreignKey.getLocalColumnNames().get(0).replaceAll("\\[|\\]", "")) + .append(") REFERENCES ") + .append(column.getForeignKey().getForeignTableName()) + .append("(") + .append(column.getForeignKey().getForeignColumnNames().get(0).replaceAll("\\[|\\]", "")) + .append(")"); + } - if (column.hasPrimaryKey()) { - statementBuilder.append(" PRIMARY KEY"); - if (column.hasAutoIncrement()) { - statementBuilder.append(" AUTOINCREMENT"); + if (column.getConstraints().size() > 0) + { + for (Constraint constraint : column.getConstraints()) + { + if (constraint.getOnConflict() != ConflictAction.NONE) + { + sb.append(constraint.getConstraintExpression()); + + sb.append(" ON CONFLICT ") + .append(constraint.getOnConflict().toString()); + sb.append(","); + } + } + sb.deleteCharAt(sb.length() - 1); } + sb.append(","); } + } + + sb.deleteCharAt(sb.length() - 1); + +//......Table constraints and triggers + + PrimaryKey primaryKey = table.getPrimaryKey(); - statementBuilder.append(","); + if (primaryKey != null && primaryKey.isActive() == true) + { + tableConstraintCount++; + + sb.append (" PRIMARY KEY") + .append("(") + .append(primaryKey.getColumns()) + .append(")"); + + if (primaryKey.getOnConflict() != ConflictAction.NONE) + { + sb.append(" ON CONFLICT ") + .append(primaryKey.getOnConflict().toString()); + } } - } - for (ForeignKey foreignKey : table.getForeignKeys()) { - statementBuilder.append("FOREIGN KEY(") - .append(foreignKey.getThisColumn()).append(") REFERENCES ") - .append(foreignKey.getTable()) + int fkCount = 1; + + for (ForeignKey foreignKey : table.getForeignKeys()) + { +// if (tableConstraintCount > 0) +// { +// sb.append(", "); +// } + + tableConstraintCount++; + + sb.append(", FOREIGN KEY /* table */") .append("(") - .append(foreignKey.getForeignColumn()) - .append("),"); - } + .append(foreignKey.getLocalColumnNames().toString().replaceAll("\\[|\\]", "")) + .append(") REFERENCES ") + .append(foreignKey.getForeignTableName()) + .append("(") + .append(foreignKey.getForeignColumnNames().toString().replaceAll("\\[|\\]", "")) + .append(")"); + fkCount++; + } - statementBuilder.deleteCharAt(statementBuilder.length()-1); + sb.append(");"); - statementBuilder.append(");"); + System.out.println("++ " + sb.toString()); - return "\"" + statementBuilder.toString() + "\";"; - } + return "\"" + sb.toString() + "\""; + } /** * Determine the data type of the provided class reference and return diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTriggersMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTriggersMethod.java new file mode 100644 index 0000000..91e6f17 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTriggersMethod.java @@ -0,0 +1,100 @@ +package com.memtrip.sqlking.preprocessor.processor.freemarker.method; + +import com.memtrip.sqlking.common.TriggerType; +import com.memtrip.sqlking.common.TriggerTime; + +import com.memtrip.sqlking.preprocessor.processor.data.Trigger; +import com.memtrip.sqlking.preprocessor.processor.data.Table; + +import freemarker.ext.beans.StringModel; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModelException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AssembleCreateTriggersMethod implements TemplateMethodModelEx + { + private static final String ASSEMBLE_CREATE_TRIGGERS = "assembleCreateTriggers"; + + public static Map getMethodMap () + { + Map map = new HashMap<>(); + map.put(ASSEMBLE_CREATE_TRIGGERS, new AssembleCreateTriggersMethod()); + return map; + } + + /** + * Build a list of create Trigger statements based on the provided table + * + * @param table + * @param triggers The list of triggers that will have create statements created for them + * @return A SQL statement that will create the triggers (after CREATE TABLE) + */ + private String buildCreateTriggerStatements (Table table) + { + StringBuilder sb = new StringBuilder(); + + List triggerList = table.getTriggers(); + + for (Trigger trigger : triggerList) + { +// sb.append(" CREATE TRIGGER ") +// .append(table.getName()) +// .append("_") +// .append(trigger.getTriggerName()) +// .append(" ") +// .append(trigger.getTriggerTime().toString()) +// .append(" "); +// +// if (trigger.getOnUpdateOfColumnNames().size() > 0) +// { +// sb.append("OF "); +// +// for (String columnName : trigger.getOnUpdateOfColumnNames()) +// { +// sb.append(columnName); +// sb.append(","); +// } +// sb.deleteCharAt(sb.length() -1); +// } +// +// sb.append(" ON ") +// .append(table.getName()); +// +// if (trigger.isForEachRow()) +// { +// sb.append(" FOR EACH ROW "); +// } +// +// sb.append(trigger.getStatement()); + } + + if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } + + return "\"" + sb.toString() + "\""; + } + + + @Override + public Object exec (List arguments) throws TemplateModelException + { + Object tableValue = arguments.get(0); + + Table table; + + if (tableValue instanceof StringModel) + { + StringModel stringModel = (StringModel)tableValue; + table = (Table)stringModel.getAdaptedObject(Table.class); + } + else + { + throw new IllegalStateException("The assembleCreateTriggerstatements Table argument must be type of " + + "com.memtrip.sqlking.preprocessor.processor.data.Table"); + } + + return buildCreateTriggerStatements(table); + } + } \ No newline at end of file diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/GetInsertValueMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/GetInsertValueMethod.java index 2f09862..e40a1d1 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/GetInsertValueMethod.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/GetInsertValueMethod.java @@ -26,11 +26,16 @@ private GetInsertValueMethod() { } - private String assembleInsertValue(Column column, String getter) { - if (column.hasPrimaryKey() && column.hasAutoIncrement()) { + private String assembleInsertValue(Column column, String getter) + { + if (column.getPrimaryKey() != null && column.getPrimaryKey().isAutoNumber()) + { return "NULL"; - } else { - switch (column.getType()) { + } + else + { + switch (column.getType()) + { case "java.lang.String": case "long": case "int": @@ -42,9 +47,9 @@ private String assembleInsertValue(Column column, String getter) { return "\" + assembleBlob(" + getter + ") + \""; default: return ""; + } } } - } @Override public Object exec(List arguments) throws TemplateModelException { diff --git a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/JoinReferencesMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/JoinReferencesMethod.java index 9192231..f6b7fac 100644 --- a/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/JoinReferencesMethod.java +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/JoinReferencesMethod.java @@ -20,9 +20,7 @@ public static Map getMethodMap() { return map; } - private JoinReferencesMethod() { - - } + private JoinReferencesMethod() {} private String build(String joinTableName, List
tables) { StringBuilder sb = new StringBuilder(); @@ -33,6 +31,7 @@ private String build(String joinTableName, List
tables) { List columns = joinTable.getColumns(); for (Column column : columns) { if (column.isJoinable(tables)) { + System.out.println(joinTableName + ": ++ " + column.getName()); Table columnTable = column.getRootTable(tables); sb.append(buildJoinTable(joinTableName, columnTable)); sb.append(build(column.getClassName(), tables)); diff --git a/preprocessor/src/main/resources/Q.java b/preprocessor/src/main/resources/Q.java index c3fceb1..4497eef 100644 --- a/preprocessor/src/main/resources/Q.java +++ b/preprocessor/src/main/resources/Q.java @@ -54,8 +54,8 @@ public String getTableName() { } @Override - public String getTableInsertQuery() { - return ${assembleCreateTable(table, tables)} + public String getTableCreateQuery() { + return ${assembleCreateTable(table, tables)}; } @Override @@ -66,20 +66,29 @@ public String[] getIndexNames() { "${table.getName()}_${column.getName()}_index", + <#list table.getIndexes() as index> + "${table.getName()?lower_case}_${index.getIndexName()?lower_case}_index", + }; } @Override - public String getCreateIndexQuery() { - StringBuilder sb = new StringBuilder(); - - <#list table.getMutableColumns(tables) as column> - <#if column.isIndex()> - sb.append("CREATE INDEX ${table.getName()}_${column.getName()}_index ON ${table.getName()} (${column.getName()});"); - + public String[] getTriggerNames() { + return new String[] { + <#list table.getTriggers() as triggers> + "${table.getName()}_${triggers.getTriggerName()}", + }; + } + + @Override + public String getCreateIndexesQuery() { + return ${assembleCreateIndexes(table)}; + } - return (sb.length() > 0) ? sb.toString() : null; + @Override + public String getCreateTriggersQuery() { + return ${assembleCreateTriggers(table)}; } @Override diff --git a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java index 639de87..11c8302 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java @@ -2,16 +2,29 @@ import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.Table; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; +import com.memtrip.sqlking.common.PrimaryKey; -@Table +@Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, + auto_increment = true + ), + indexes = { + @Index(indexName = "name", + columns = {@IndexColumn(column = "name")} + ) + } +) public class Data { - @Column(primary_key = true, auto_increment = true) int id; + @Column int id; @Column String name; public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +32,6 @@ public void setId(int id) { public String getName() { return name; } - public void setName(String name) { this.name = name; } diff --git a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java index af28983..e34b737 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java @@ -2,24 +2,32 @@ import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.Table; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; +import com.memtrip.sqlking.common.PrimaryKey; -@Table +@Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, + auto_increment = true + ), + indexes = { + @Index(indexName = "timestamp", + columns = {@IndexColumn(column = "timestamp")} + ) + } +) public class Log { - @Column(primary_key = true) int id; + @Column int id; @Column long timestamp; - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } + public int getId() { return id; } + public void setId(int id) { this.id = id; } public long getTimestamp() { return timestamp; } - public void setTimestamp(long timestamp) { this.timestamp = timestamp; } diff --git a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java index c8de2ca..1c54a18 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java @@ -2,28 +2,42 @@ import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.Table; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; +import com.memtrip.sqlking.common.PrimaryKey; -@Table +@Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, + auto_increment = true + ), + indexes = { + @Index(indexName = "timestamp", + columns = { + @IndexColumn(column = "timestamp") + } + ) + } +) public class Post { - @Column(primary_key = true) String id; + @Column int id; @Column String title; @Column byte[] blob; @Column long timestamp; @Column User user; @Column Data data; - public String getId() { + public int getId() { return id; } - - public void setId(String newVal) { + public void setId(int newVal) { id = newVal; } public String getTitle() { return title; } - public void setTitle(String newVal) { title = newVal; } @@ -31,7 +45,6 @@ public void setTitle(String newVal) { public byte[] getBlob() { return blob; } - public void setBlob(byte[] newVal) { blob = newVal; } @@ -39,7 +52,6 @@ public void setBlob(byte[] newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -47,7 +59,6 @@ public void setTimestamp(long newVal) { public User getUser() { return user; } - public void setUser(User user) { this.user = user; } @@ -55,7 +66,6 @@ public void setUser(User user) { public Data getData() { return data; } - public void setData(Data data) { this.data = data; } diff --git a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java index 07464c5..5925f5f 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java @@ -1,20 +1,41 @@ package com.memtrip.sqlking.preprocessor; +//import com.memtrip.sqlking.common.*; import com.memtrip.sqlking.common.Column; +import com.memtrip.sqlking.common.PrimaryKey; import com.memtrip.sqlking.common.ForeignKey; import com.memtrip.sqlking.common.Table; +import com.memtrip.sqlking.common.Index; +import com.memtrip.sqlking.common.IndexColumn; +import com.memtrip.sqlking.common.Constraint; +import com.memtrip.sqlking.common.NotNull; +import com.memtrip.sqlking.common.ConflictAction; @Table( + indexes = { + @Index( + indexName = "username", + columns = {@IndexColumn(column = "username")} + ) + }, foreignKeys = { - @ForeignKey( - targetTable = "Log", - targetColumn = "id", - localColumn = "logId" - ) + @ForeignKey( + foreignTableName = "Log", + localColumnNames = {"logId"}, + foreignColumnNames = {"id"} + ) + }, + constraints = { + @Constraint( + constraintName = "check_username", + expression = "length(username) > 5") } ) + public class User { - @Column String username; + @Column(primaryKey = @PrimaryKey(active = true, auto_increment = false), + notNull = @NotNull(onConflict = ConflictAction.ROLLBACK)) + String username; @Column long timestamp; @Column boolean isRegistered; @Column byte[] profilePicture; @@ -26,7 +47,6 @@ public class User { public String getUsername() { return username; } - public void setUsername(String newVal) { username = newVal; } @@ -34,7 +54,6 @@ public void setUsername(String newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -42,7 +61,6 @@ public void setTimestamp(long newVal) { public boolean getIsRegistered() { return isRegistered; } - public void setIsRegistered(boolean newVal) { isRegistered = newVal; } @@ -50,7 +68,6 @@ public void setIsRegistered(boolean newVal) { public byte[] getProfilePicture() { return profilePicture; } - public void setProfilePicture(byte[] newVal) { profilePicture = newVal; } @@ -58,7 +75,6 @@ public void setProfilePicture(byte[] newVal) { public double getRating() { return rating; } - public void setRating(double rating) { this.rating = rating; } @@ -66,7 +82,6 @@ public void setRating(double rating) { public int getCount() { return count; } - public void setCount(int count) { this.count = count; } @@ -74,7 +89,6 @@ public void setCount(int count) { public int getLogId() { return logId; } - public void setLogId(int logId) { this.logId = logId; } @@ -82,7 +96,6 @@ public void setLogId(int logId) { public Log getLog() { return log; } - public void setLog(Log log) { this.log = log; } diff --git a/sample/app/src/main/java/com/memtrip/sqlking/sample/model/Comment.java b/sample/app/src/main/java/com/memtrip/sqlking/sample/model/Comment.java index 9dc1a31..fcbc8e6 100644 --- a/sample/app/src/main/java/com/memtrip/sqlking/sample/model/Comment.java +++ b/sample/app/src/main/java/com/memtrip/sqlking/sample/model/Comment.java @@ -3,7 +3,23 @@ import com.memtrip.sqlking.common.Column; import com.memtrip.sqlking.common.Table; -@Table +@Table(foreignKeys = { + foreignKey (foreignTableName = "User", + localColumnNames = {"userId"}, + foreignColumnNames = {"id"} + ) + + }, + indexes = { + @Index( + indexName = "user", + columns = { + @IndexColumn(column = "userId"), + @IndexColumn(column = "timestamp", sortOrder = SortOrder.DESC) + } + ) + } +) public class Comment { @Column(index = true) int id; @Column String body; @@ -14,7 +30,6 @@ public class Comment { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -22,7 +37,6 @@ public void setId(int id) { public String getBody() { return body; } - public void setBody(String body) { this.body = body; } @@ -30,7 +44,6 @@ public void setBody(String body) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long timestamp) { this.timestamp = timestamp; } @@ -38,7 +51,6 @@ public void setTimestamp(long timestamp) { public int getUserId() { return userId; } - public void setUserId(int userId) { this.userId = userId; } @@ -46,7 +58,6 @@ public void setUserId(int userId) { public User getUser() { return user; } - public void setUser(User user) { this.user = user; } diff --git a/sample/app/src/main/java/com/memtrip/sqlking/sample/model/User.java b/sample/app/src/main/java/com/memtrip/sqlking/sample/model/User.java index a1d48a6..220ed26 100644 --- a/sample/app/src/main/java/com/memtrip/sqlking/sample/model/User.java +++ b/sample/app/src/main/java/com/memtrip/sqlking/sample/model/User.java @@ -11,7 +11,6 @@ public class User { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +18,6 @@ public void setId(int id) { public String getUsername() { return username; } - public void setUsername(String username) { this.username = username; }