From b952cbaf211554b242cd45cc5bf14a7793c33aa6 Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Thu, 22 Sep 2016 09:56:46 +0200 Subject: [PATCH 1/8] Added initial support for Composite Foreign Keys and Indexes --- .gitignore | 2 + README.md | 4 +- client/build.gradle | 8 +- common/pom.xml | 2 +- .../com/memtrip/sqlking/common/Column.java | 3 +- .../memtrip/sqlking/common/ForeignKey.java | 11 ++- .../memtrip/sqlking/common/ForeignKeys.java | 24 ++++++ .../com/memtrip/sqlking/common/Index.java | 28 +++++++ .../memtrip/sqlking/common/IndexColumn.java | 28 +++++++ .../com/memtrip/sqlking/common/RIRule.java | 24 ++++++ .../com/memtrip/sqlking/common/SortOrder.java | 16 ++++ .../com/memtrip/sqlking/common/Table.java | 1 + preprocessor/pom.xml | 4 +- .../preprocessor/processor/Processor.java | 8 +- .../preprocessor/processor/data/Column.java | 9 +++ .../preprocessor/processor/data/Data.java | 12 +++ .../processor/data/ForeignKey.java | 48 ++++++++---- .../preprocessor/processor/data/Index.java | 39 ++++++++++ .../processor/data/IndexColumn.java | 28 +++++++ .../preprocessor/processor/data/Indexes.java | 29 +++++++ .../preprocessor/processor/data/Table.java | 7 ++ .../data/parse/ParseColumnAnnotation.java | 6 ++ .../data/parse/ParseTableAnnotation.java | 51 +++++++++++-- .../processor/freemarker/DataModel.java | 2 + .../method/AssembleCreateIndexesMethod.java | 75 +++++++++++++++++++ .../method/AssembleCreateTableMethod.java | 66 ++++++++++------ .../method/GetInsertValueMethod.java | 1 - .../method/JoinReferencesMethod.java | 1 + preprocessor/src/main/resources/Q.java | 13 +++- .../memtrip/sqlking/preprocessor/User.java | 6 +- 30 files changed, 491 insertions(+), 65 deletions(-) create mode 100644 common/src/main/java/com/memtrip/sqlking/common/ForeignKeys.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/Index.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/IndexColumn.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/RIRule.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/SortOrder.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Indexes.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java 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..1ac8f27 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' } ``` diff --git a/client/build.gradle b/client/build.gradle index c3c4e8f..1cf1442 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.6' developerId = 'samkirton' developerName = 'Samuel Kirton' @@ -44,7 +44,7 @@ android { minSdkVersion 11 targetSdkVersion 24 versionCode 7 - versionName "1.1.1" + versionName "1.1.6" 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.6' 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.6' androidTestCompile( 'com.android.support.test:runner:0.3', diff --git a/common/pom.xml b/common/pom.xml index 1a663c9..6459227 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.6 SQLKing common 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..9422248 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Column.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Column.java @@ -19,7 +19,8 @@ * @author Samuel Kirton [sam@memtrip.com] */ public @interface Column { + boolean index() default false; boolean primary_key() default false; boolean auto_increment() default false; - boolean index() default false; + boolean not_null() default false; } \ 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..f280a17 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java +++ b/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java @@ -19,8 +19,11 @@ * @author Samuel Kirton [sam@memtrip.com] */ @SuppressWarnings("WeakerAccess") -public @interface ForeignKey { - String targetTable() default ""; - String targetColumn() default ""; - String localColumn() default ""; +public @interface ForeignKey + { + String foreignTableName (); + String[] foreignColumnNames (); + String[] localColumnNames (); + RIRule updateRule () default RIRule.Restrict; + RIRule deleteRule () default RIRule.Restrict; } \ 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..1473275 --- /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] - 2016-09-16 - Added Composite and Unique Index support + */ + +import com.memtrip.sqlking.common.IndexColumn; + +public @interface Index { + String indexName(); + boolean unique() default false; + IndexColumn[] columns() default {}; +} \ 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..6e2433f --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/IndexColumn.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; + +import java.lang.annotation.Repeatable; + +/** + * @author Adrian Velcich [adrian@higration.co.za] - 2016-09-16 - Added Composite and Unique Index support + */ + +@SuppressWarnings("WeakerAccess") +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/RIRule.java b/common/src/main/java/com/memtrip/sqlking/common/RIRule.java new file mode 100644 index 0000000..06adf78 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/RIRule.java @@ -0,0 +1,24 @@ +package com.memtrip.sqlking.common; + +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/SortOrder.java b/common/src/main/java/com/memtrip/sqlking/common/SortOrder.java new file mode 100644 index 0000000..9c2b435 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/SortOrder.java @@ -0,0 +1,16 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.common; + +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..a49c427 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Table.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Table.java @@ -20,4 +20,5 @@ */ public @interface Table { ForeignKey[] foreignKeys() default {}; + Index[] indexes() default {}; } \ No newline at end of file diff --git a/preprocessor/pom.xml b/preprocessor/pom.xml index ee38e1a..33c5726 100644 --- a/preprocessor/pom.xml +++ b/preprocessor/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking preprocessor - 1.1.5 + 1.1.6 SQLKing preprocessor @@ -56,7 +56,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.6 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..8c92776 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,9 @@ import com.google.googlejavaformat.java.FormatterException; 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.ForeignKey; 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; @@ -36,7 +39,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) { @@ -82,6 +85,9 @@ 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(ForeignKey.class.getCanonicalName()); return set; } 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..f4f6e94 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 @@ -7,6 +7,7 @@ public class Column { private String mClassName; private String mType; private boolean mIsIndex; + private boolean mIsNotNull; private boolean mPrimaryKey; private boolean mHasAutoIncrement; @@ -45,6 +46,14 @@ public void setIsIndex(boolean newVal) { mIsIndex = newVal; } + public boolean isNotNull () + { + return mIsNotNull; + } + public void setNotNull (boolean newVal) + { + this.mIsNotNull = newVal; + } public boolean hasPrimaryKey() { return mPrimaryKey; } 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..fdbe3c1 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,6 +4,8 @@ public class Data { private List mTables; + private List mIndexes; + private List mForeignKeys; public List
getTables() { return mTables; @@ -12,4 +14,14 @@ public List
getTables() { public void setTables(List
newVal) { mTables = newVal; } + public List getIndexes() { return mIndexes; } + public void setIndexes(List newVal) { mIndexes = newVal; } + public List getForeignKeys () + { + return mForeignKeys; + } + public void setForeignKeys (List newVal) + { + this.mForeignKeys = 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..ccc48cd 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,47 @@ package com.memtrip.sqlking.preprocessor.processor.data; -public class ForeignKey { - private String mTable; - private String mThisColumn; - private String mForeignColumn; +import java.util.List; +import com.memtrip.sqlking.common.RIRule; +import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; +public class ForeignKey + { + private String mForeignTableName; + private List mLocalColumnNames; + private List mForeignColumnNames; + private RIRule mRIUpdateRule; + private RIRule mRIDeleteRule; - public String getTable() { - return mTable; + public String getForeignTableName() { + return mForeignTableName; } - public void setTable(String newVal) { - mTable = newVal; + public void setForeignTableName(String newVal) { + mForeignTableName = newVal; } - public String getThisColumn() { - return mThisColumn; + 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 void setLocalColumn(String newVal) { - mThisColumn = newVal; + public RIRule getRIUpdateRule () + { + return mRIUpdateRule; + } + public void setRIUpdateRule (RIRule newVal) + { + this.mRIUpdateRule = newVal; } - public String getForeignColumn() { - return mForeignColumn; + public RIRule getRIDeleteRule () + { + return mRIDeleteRule; } - public void setTargetColumn(String newVal) { - mForeignColumn = newVal; + 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..a20cacf --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java @@ -0,0 +1,39 @@ +package com.memtrip.sqlking.preprocessor.processor.data; + +import java.util.List; + +public class Index { + private String mIndexName; + private boolean mIsUnique; + private List mColumns; + + 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..ca4558b --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java @@ -0,0 +1,28 @@ +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/Table.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java index 9c26d87..cd56a24 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 @@ -11,6 +11,7 @@ public class Table { private String mType; private List mColumns; private List mForeignKeys; + private List mIndexes; public Element getElement() { return mElement; @@ -63,6 +64,12 @@ public void setForeignKeys(List 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 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..2dd0186 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 @@ -14,6 +14,7 @@ static Column parseColumn(Element element) { boolean isIndex = assembleIsIndex(element); boolean hasPrimaryKey = assemblePrimaryKey(element); boolean hasAutoIncrement = assembleAutoIncrement(element); + boolean isNotNotNull = assembleNotNull(element); String type = assembleType(element); String className = assembleClassName(type); @@ -22,6 +23,7 @@ static Column parseColumn(Element element) { column.setIsIndex(isIndex); column.setHasPrimaryKey(hasPrimaryKey); column.setHasAutoIncrement(hasAutoIncrement); + column.setNotNull(isNotNotNull); column.setType(type); column.setClassName(className); @@ -57,4 +59,8 @@ private static boolean assembleAutoIncrement(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); return column.auto_increment(); } + private static boolean assembleNotNull(Element element) { + com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + return column.not_null(); + } } 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..98f0bf2 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 @@ -3,6 +3,8 @@ import com.memtrip.sqlking.preprocessor.processor.Context; import com.memtrip.sqlking.preprocessor.processor.data.Column; 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 javax.lang.model.element.Element; @@ -10,6 +12,7 @@ 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; @@ -21,6 +24,8 @@ static Table parseTable(Element element) { String tablePackage = assemblePackage(element); String type = tablePackage + "." + name; List columns = assembleColumns(element); + List foreignKeys = assembleForeignKeys(element); + List indexes = assembleIndexes(element); Table table = new Table(); table.setElement(element); @@ -28,7 +33,8 @@ static Table parseTable(Element element) { table.setPackage(tablePackage); table.setType(type); table.setColumns(columns); - table.setForeignKeys(assembleForeignKeys(element)); + table.setForeignKeys(foreignKeys); + table.setIndexes(indexes); return table; } @@ -58,18 +64,53 @@ private static List assembleColumns(Element element) { return columns; } + private static List assembleIndexes (Element element) + { + com.memtrip.sqlking.common.Table tableAnnotation = element.getAnnotation(com.memtrip.sqlking.common.Table.class); + com.memtrip.sqlking.common.Index[] indexesAnnotation = tableAnnotation.indexes(); + List indexes = new ArrayList<>(); + for (com.memtrip.sqlking.common.Index indexAnnotation : indexesAnnotation) + { + Index index = new Index(); + com.memtrip.sqlking.common.IndexColumn[] indexColumnsAnnotation = indexAnnotation.columns(); + List indexColumns = new ArrayList<>(); + for (com.memtrip.sqlking.common.IndexColumn columnAnnotation : indexColumnsAnnotation) + { + IndexColumn indexColumn = new IndexColumn(); + indexColumn.setColumn(columnAnnotation.column()); + indexColumn.setSortOrder(columnAnnotation.sortOrder()); + indexColumns.add(indexColumn); + } + index.setIndexName(indexAnnotation.indexName()); + index.setColumns(indexColumns); + index.setUnique(indexAnnotation.unique()); + 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()); + 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); } 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..da9c0cc 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,11 +9,13 @@ public class DataModel { private static final String TABLES = "tables"; + private static final String INDEXES = "indexes"; public static Map create(Data data) { Map map = new HashMap<>(); map.put(TABLES, data.getTables()); + map.put(INDEXES, data.getIndexes()); map.putAll(GetCursorGetterMethod.getMethodMap()); map.putAll(GetInsertValueMethod.getMethodMap()); map.putAll(AssembleCreateTableMethod.getMethodMap()); 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..f7ba5f2 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java @@ -0,0 +1,75 @@ +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.Indexes; +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() { + } + + /** + * 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(String tableName, Index[] indexes) + { + StringBuilder sb = new StringBuilder(); + + for (Index index : indexes) + { + sb.append("CREATE INDEX " + index.getIndexName() + "ON " + tableName + "("); + + for (IndexColumn indexColumn : index.getColumns()) + { + sb.append(indexColumn.getColumn()) + .append(indexColumn.getSortOrder()) + .append(","); + } + + sb.deleteCharAt(sb.length() - 1); + + sb.append(");"); + + } + return "\"" + sb.toString() + "\";"; + } + + @Override + public Object exec(List arguments) throws TemplateModelException { + Object tableNameValue = arguments.get(0); + Object indexListValue = arguments.get(1); + + Index[] indexes; + + if (indexListValue instanceof StringModel) + { + StringModel stringModel = (StringModel) indexListValue; + indexes = (Index[])stringModel.getAdaptedObject(Indexes.class); + } + else + { + throw new IllegalStateException("The assembleCreateIndexStatements argument must be type of com.memtrip.sqlking.preprocessor.model.Indexes"); + } + + return buildCreateIndexStatements((String)tableNameValue, indexes); + } +} \ 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..cdea8fe 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 @@ -2,6 +2,8 @@ import com.memtrip.sqlking.preprocessor.processor.data.Column; import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; +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; @@ -36,46 +38,62 @@ private AssembleCreateTableMethod() { * @param table The table that the statement will create * @return A SQL statement that will create a table */ - private String buildCreateTableStatement(Table table, List
tables) { - StringBuilder statementBuilder = new StringBuilder(); + private String buildCreateTableStatement(Table table, List
tables) + { + StringBuilder sb = new StringBuilder(); - 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++) { + 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.hasPrimaryKey()) { - statementBuilder.append(" PRIMARY KEY"); - if (column.hasAutoIncrement()) { - statementBuilder.append(" AUTOINCREMENT"); + if (!column.isJoinable(tables)) + { + sb.append(column.getName()) + .append(" ") + .append(getSQLDataTypeFromClassRef(column.getType())); + + if (column.hasPrimaryKey()) + { + sb.append(" PRIMARY KEY"); + if (column.hasAutoIncrement()) + { + sb.append(" AUTOINCREMENT"); } } - statementBuilder.append(","); + sb.append(","); } } - for (ForeignKey foreignKey : table.getForeignKeys()) { - statementBuilder.append("FOREIGN KEY(") - .append(foreignKey.getThisColumn()).append(") REFERENCES ") - .append(foreignKey.getTable()) + List foreignKeyList = table.getForeignKeys(); + for (ForeignKey foreignKey : foreignKeyList) + { + StringBuilder sb_FK = new StringBuilder(); + sb_FK.append(table.getName() + " - Foreign Key: ") + .append( foreignKey.getForeignTableName()) + .append(" ") + .append( foreignKey.getLocalColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append( " References ") + .append( foreignKey.getForeignColumnNames().toString().replaceAll("[\\[\\]]", "")); + System.out.println("\"" + sb_FK.toString() + "\""); + sb.append(" FOREIGN KEY(") + .append(foreignKey.getLocalColumnNames().toString().replaceAll("[\\[\\]]", "")) + .append(") REFERENCES ") + .append(foreignKey.getForeignTableName()) .append("(") - .append(foreignKey.getForeignColumn()) + .append(foreignKey.getForeignColumnNames().toString().replaceAll("[\\[\\]]", "")) .append("),"); } - statementBuilder.deleteCharAt(statementBuilder.length()-1); + sb.deleteCharAt(sb.length() - 1); - statementBuilder.append(");"); + sb.append(");"); - return "\"" + statementBuilder.toString() + "\";"; + return "\"" + sb.toString() + "\""; } /** 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..b079e6a 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 @@ -44,7 +44,6 @@ private String assembleInsertValue(Column column, String getter) { 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..ef9016f 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 @@ -33,6 +33,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..d22337e 100644 --- a/preprocessor/src/main/resources/Q.java +++ b/preprocessor/src/main/resources/Q.java @@ -66,6 +66,9 @@ public String[] getIndexNames() { "${table.getName()}_${column.getName()}_index", + <#list table.getIndexes() as index> + "${table.getName()}_${index.getIndexName()}_index", + }; } @@ -78,7 +81,15 @@ public String getCreateIndexQuery() { sb.append("CREATE INDEX ${table.getName()}_${column.getName()}_index ON ${table.getName()} (${column.getName()});"); - + <#list table.getIndexes() as index> + sb.append("CREATE INDEX ${table.getName()}_${index.getIndexName()}_idx ON ${table.getName()} ("); + <#list index.getColumns() as indexColumn> + sb.append("${indexColumn.getColumn()} ${indexColumn.getSortOrder()}"); + sb.append(", "); + + sb.deleteCharAt(sb.length() - 1); + sb.append(");"); + return (sb.length() > 0) ? sb.toString() : null; } 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..0fb34e4 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java @@ -7,9 +7,9 @@ @Table( foreignKeys = { @ForeignKey( - targetTable = "Log", - targetColumn = "id", - localColumn = "logId" + foreignTableName = "Log", + localColumnNames = {"logId"}, + foreignColumnNames = {"id"} ) } ) From 0bfb2713e1155ad0dd358ca3cc15fcf022c512d1 Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Thu, 22 Sep 2016 09:56:46 +0200 Subject: [PATCH 2/8] Added initial support for Composite Foreign Keys and Indexes, Table Constraints and Triggers --- .gitignore | 2 + README.md | 61 ++++++- build.gradle | 4 +- client/build.gradle | 8 +- .../com/memtrip/sqlking/database/SQLInit.java | 17 +- .../com/memtrip/sqlking/database/SQLOpen.java | 37 ++-- .../sqlking/integration/CreateTest.java | 4 +- .../sqlking/integration/ForeignKeyTest.java | 80 +++++++++ .../sqlking/integration/IndexTest.java | 2 +- .../sqlking/integration/models/Post.java | 6 +- .../sqlking/integration/models/User.java | 18 +- .../sqlking/integration/utils/SetupData.java | 2 +- .../sqlking/integration/utils/SetupLog.java | 2 +- .../sqlking/integration/utils/SetupPost.java | 2 +- .../sqlking/integration/utils/SetupUser.java | 2 +- common/pom.xml | 2 +- .../com/memtrip/sqlking/common/Column.java | 8 +- .../sqlking/common/ConflictAction.java | 36 ++++ .../memtrip/sqlking/common/Constraint.java | 26 +++ .../memtrip/sqlking/common/ForeignKey.java | 15 +- .../com/memtrip/sqlking/common/Index.java | 28 +++ .../memtrip/sqlking/common/IndexColumn.java | 25 +++ .../memtrip/sqlking/common/PrimaryKey.java | 28 +++ .../com/memtrip/sqlking/common/RIRule.java | 43 +++++ .../com/memtrip/sqlking/common/SQLQuery.java | 16 +- .../com/memtrip/sqlking/common/SortOrder.java | 31 ++++ .../com/memtrip/sqlking/common/Table.java | 3 + .../com/memtrip/sqlking/common/Trigger.java | 30 ++++ .../memtrip/sqlking/common/TriggerTime.java | 22 +++ .../memtrip/sqlking/common/TriggerType.java | 22 +++ preprocessor/pom.xml | 4 +- .../preprocessor/processor/Processor.java | 14 +- .../preprocessor/processor/data/Column.java | 48 ++++-- .../processor/data/Constraint.java | 33 ++++ .../preprocessor/processor/data/Data.java | 23 ++- .../processor/data/ForeignKey.java | 55 ++++-- .../preprocessor/processor/data/Index.java | 40 +++++ .../processor/data/IndexColumn.java | 26 +++ .../preprocessor/processor/data/Table.java | 32 +++- .../preprocessor/processor/data/Trigger.java | 54 ++++++ .../data/parse/ParseColumnAnnotation.java | 80 ++++++++- .../data/parse/ParseTableAnnotation.java | 162 ++++++++++++++++-- .../TableNamesMustBeUniqueValidator.java | 4 +- .../processor/freemarker/DataModel.java | 13 ++ .../AssembleCreateConstraintsMethod.java | 78 +++++++++ .../AssembleCreateForeignKeysMethod.java | 88 ++++++++++ .../method/AssembleCreateIndexesMethod.java | 74 ++++++++ .../method/AssembleCreateTableMethod.java | 96 +++++++---- .../method/AssembleCreateTriggersMethod.java | 101 +++++++++++ .../method/GetInsertValueMethod.java | 15 +- .../method/JoinReferencesMethod.java | 5 +- preprocessor/src/main/resources/Q.java | 29 ++-- .../memtrip/sqlking/preprocessor/Data.java | 5 +- .../com/memtrip/sqlking/preprocessor/Log.java | 15 +- .../memtrip/sqlking/preprocessor/Post.java | 25 +-- .../memtrip/sqlking/preprocessor/User.java | 33 ++-- .../memtrip/sqlking/sample/model/Comment.java | 23 ++- .../memtrip/sqlking/sample/model/User.java | 2 - 58 files changed, 1558 insertions(+), 201 deletions(-) create mode 100644 client/src/tests/java/com/memtrip/sqlking/integration/ForeignKeyTest.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/Constraint.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/Index.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/IndexColumn.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/RIRule.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/SortOrder.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/Trigger.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/TriggerType.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Constraint.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Index.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/IndexColumn.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Trigger.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateConstraintsMethod.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateForeignKeysMethod.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTriggersMethod.java 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..7485598 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,8 +297,9 @@ 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: +An auto incrementing primary key can be defined on an `int` or `long` column using: ```java @Table @@ -300,6 +316,36 @@ public class Data { } ``` +####Table Constraints, Composite Indexes and Foreign Keys#### +Multiple Composite Indexes and Foreign Keys can be defined for the table, and will be created automatically when the table is created: + +```java +@Table ( + foreignkeys = {@ForeignKey ( // (not required for joins, but will be enforced by SQLite DBMS) + 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 + } + )[, ...] // 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` + [,@onConflict (ConflictAction.ROLLBACK|ABORT|FAIL|etc)] // as appropriate, if required + )[, ...] // optional additional @Constraint 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 +353,7 @@ 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 \ No newline at end of file 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..dcf8d61 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.7' developerId = 'samkirton' developerName = 'Samuel Kirton' @@ -44,7 +44,7 @@ android { minSdkVersion 11 targetSdkVersion 24 versionCode 7 - versionName "1.1.1" + versionName "1.1.7" 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.7' 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.7' androidTestCompile( 'com.android.support.test:runner:0.3', 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..599ca76 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) { + db.execSQL(createIndex); + } + } + + for (String createTrigger : mCreateTriggerStatements) { + if (createTrigger != null) { + db.execSQL(createTrigger); + } + } } @Override 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/models/Post.java b/client/src/tests/java/com/memtrip/sqlking/integration/models/Post.java index cb2e811..961d97d 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"} ) } ) 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..e503f99 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,23 @@ 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", + indexColumns = { + @IndexColumn(column = "username")} + ) } ) public class User { 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..af6bc67 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.7 SQLKing common 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..87c29fd 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,15 @@ /** * @author Samuel Kirton [sam@memtrip.com] + * @author Adrian Velcich [adrian@higration.co.za] */ + public @interface Column { + boolean index() default false; boolean primary_key() default false; boolean auto_increment() default false; - boolean index() default false; + boolean not_null() default false; + String defaultValue() default ""; + ForeignKey foreignKey() default @ForeignKey (); + 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..b295a23 --- /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 + { + NA ("NA"), + 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..9e148fc --- /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(); + String expression(); + ConflictAction onConflict() default ConflictAction.NA; +} \ 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..4549674 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 + { + 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/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/PrimaryKey.java b/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java new file mode 100644 index 0000000..f7e8ab9 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.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] + */ + +public @interface PrimaryKey // Table Level Primary key + { + Column[] columns(); + SortOrder sortOrder() default SortOrder.ASC; + ConflictAction onConflict() default ConflictAction.ROLLBACK; + boolean autoIncrement() default false; + } \ 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..a4dc5db 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,8 @@ * @author Samuel Kirton [sam@memtrip.com] */ public @interface Table { + Index[] indexes() default {}; 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..3e4b197 --- /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(); + TriggerType triggerType(); + 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..c993b70 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java @@ -0,0 +1,22 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum TriggerTime + { + BEFORE ("BEFORE"), + AFTER ("AFTER"), + INSTEAD_OF ("INSTEAD OF"); + + 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..f3e15e1 --- /dev/null +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java @@ -0,0 +1,22 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.common; + +/** + * Author: A.Velcich + */ + +public enum TriggerType + { + DELETE ("DELETE"), + INSERT ("INSERT"), + UPDATE ("UPDATE"); + + 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/pom.xml b/preprocessor/pom.xml index ee38e1a..b3b3c00 100644 --- a/preprocessor/pom.xml +++ b/preprocessor/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking preprocessor - 1.1.5 + 1.1.7 SQLKing preprocessor @@ -56,7 +56,7 @@ com.memtrip.sqlking common - 1.1.5 + 1.1.7 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..5859a38 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,12 @@ import com.google.googlejavaformat.java.FormatterException; 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.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; @@ -36,7 +42,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) { @@ -82,6 +88,12 @@ 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(ForeignKey.class.getCanonicalName()); + set.add(Constraint.class.getCanonicalName()); + set.add(Trigger.class.getCanonicalName()); + return set; } 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..9704422 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 @@ -3,17 +3,20 @@ 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 boolean mIsIndex; + private boolean mIsNotNull; private boolean mPrimaryKey; private boolean mHasAutoIncrement; + private String mDefaultValue; + private ForeignKey mForeignKey; + private List mConstraints; public String getName() { return mName; } - public void setName(String newVal) { mName = newVal; } @@ -21,7 +24,6 @@ public void setName(String newVal) { public String getClassName() { return mClassName; } - public void setClassName(String newVal) { mClassName = newVal; } @@ -29,7 +31,6 @@ public void setClassName(String newVal) { public String getType() { return mType; } - public void setType(String newVal) { mType = newVal; } @@ -40,15 +41,22 @@ public void setType(String newVal) { public boolean isIndex() { return mIsIndex; } - public void setIsIndex(boolean newVal) { mIsIndex = newVal; } + public boolean isNotNull () + { + return mIsNotNull; + } + public void setNotNull (boolean newVal) + { + this.mIsNotNull = newVal; + } + public boolean hasPrimaryKey() { return mPrimaryKey; } - public void setHasPrimaryKey(boolean newVal) { mPrimaryKey = newVal; } @@ -56,12 +64,32 @@ public void setHasPrimaryKey(boolean newVal) { public boolean hasAutoIncrement() { return mHasAutoIncrement; } - public void setHasAutoIncrement(boolean newVal) { mHasAutoIncrement = newVal; } - public Table getRootTable(List
tables) { + public String getDefaultValue () + { + return mDefaultValue; + } + public void setDefaultValue (String newVal) + { + this.mDefaultValue = 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) { 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..e141e77 --- /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.NA; + + 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..61989e2 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,33 @@ public class Data { private List
mTables; + private List mIndexes; + 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 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..d37959d 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,50 @@ package com.memtrip.sqlking.preprocessor.processor.data; -public class ForeignKey { - private String mTable; - private String mThisColumn; - private String mForeignColumn; +import java.util.List; +import com.memtrip.sqlking.common.RIRule; +import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; +public class ForeignKey + { + private String mForeignTableName; + private String mForeignTableAliasName; + private List mLocalColumnNames; + private List mForeignColumnNames; + private RIRule mRIUpdateRule; + private RIRule mRIDeleteRule; - public String getTable() { - return mTable; + public String getForeignTableName() { + return mForeignTableName; } - - public void setTable(String newVal) { - mTable = newVal; + public void setForeignTableName(String newVal) { + mForeignTableName = newVal; } - public String getThisColumn() { - return mThisColumn; - } + public String getForeignTableAliasName () { return mForeignTableAliasName; } + public void setForeignTableAliasName (String newVal) { this.mForeignTableAliasName = newVal; } - public void setLocalColumn(String newVal) { - mThisColumn = 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/Table.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Table.java index 9c26d87..8e7dea7 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 @@ -7,31 +7,35 @@ public class Table { private Element mElement; private String mName; + private String mAliasName = ""; private String mPackage; private String mType; private List mColumns; private List mForeignKeys; + private List mIndexes; + private List mConstraints; + private List mTriggers; public Element getElement() { return mElement; } - public void setElement(Element newVal) { mElement = newVal; } public String getName() { - return mName; + return mAliasName.length() > 0 ? mAliasName : mName; } - public void setName(String newVal) { mName = newVal; } - public String getPackage() { + public String getAliasName () { return mAliasName; } + public void setAliasName (String newVal) { this.mAliasName = mAliasName; }; + + public String getPackage () { return mPackage; } - public void setPackage(String newVal) { mPackage = newVal; } @@ -42,7 +46,6 @@ public void setPackage(String newVal) { public String getType() { return mType; } - public void setType(String newVal) { mType = newVal; } @@ -50,7 +53,6 @@ public void setType(String newVal) { public List getColumns() { return mColumns; } - public void setColumns(List newVal) { mColumns = newVal; } @@ -58,12 +60,24 @@ public void setColumns(List newVal) { public List getForeignKeys() { return mForeignKeys; } - public void setForeignKeys(List newVal) { mForeignKeys = newVal; } - /** + public List getIndexes() { + return mIndexes; + } + public void setIndexes(List newVal) { + mIndexes = newVal; + } + + 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; } + +/** * (Used in Q.java freemarker template) * @return all columns ignoring any object mappings */ 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..4263281 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/Trigger.java @@ -0,0 +1,54 @@ +/** + * Author: A.Velcich + */ + +package com.memtrip.sqlking.preprocessor.processor.data; + +/** + * Author: A.Velcich + */ + +import java.util.List; +import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; +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..af60bea 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,43 @@ package com.memtrip.sqlking.preprocessor.processor.data.parse; import com.memtrip.sqlking.preprocessor.processor.data.Column; +import com.memtrip.sqlking.preprocessor.processor.data.Constraint; +import com.memtrip.sqlking.preprocessor.processor.data.ForeignKey; 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); + String type = assembleType(element); + String className = assembleClassName(type); + boolean isIndex = assembleIsIndex(element); boolean hasPrimaryKey = assemblePrimaryKey(element); boolean hasAutoIncrement = assembleAutoIncrement(element); - String type = assembleType(element); - String className = assembleClassName(type); + boolean isNotNotNull = assembleNotNull(element); + String defaultValue = assembleDefaultValue(element); + ForeignKey foreignKey = assembleForeignKey(element); + List constraints = assembleConstraints(element); Column column = new Column(); column.setName(name); + column.setType(type); + column.setClassName(className); column.setIsIndex(isIndex); column.setHasPrimaryKey(hasPrimaryKey); column.setHasAutoIncrement(hasAutoIncrement); - column.setType(type); - column.setClassName(className); + column.setNotNull(isNotNotNull); + column.setDefaultValue(defaultValue); + column.setConstraints(constraints); + column.setForeignKey(foreignKey); + column.setConstraints(constraints); return column; } @@ -57,4 +71,62 @@ private static boolean assembleAutoIncrement(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); return column.auto_increment(); } + + private static boolean assembleNotNull(Element element) { + com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + return column.not_null(); + } + + private static String assembleDefaultValue(Element element) { + com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); + 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(constraintAnnotation.constraintName()); + 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..dda512c 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,26 +1,40 @@ 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.preprocessor.processor.Context; import com.memtrip.sqlking.preprocessor.processor.data.Column; 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 { - - static Table parseTable(Element element) { - - String name = assembleName(element); - String tablePackage = assemblePackage(element); - String type = tablePackage + "." + name; - List columns = assembleColumns(element); +class ParseTableAnnotation + { + static Table parseTable(Element element) + { + String name = assembleName(element); + String tablePackage = assemblePackage(element); + String type = tablePackage + "." + name; + List columns = assembleColumns(element); + List foreignKeys = assembleForeignKeys(element); + List indexes = assembleIndexes(element); + List constraints = assembleConstraints(element); + List triggers = assembleTriggers(element); Table table = new Table(); table.setElement(element); @@ -28,7 +42,10 @@ static Table parseTable(Element element) { table.setPackage(tablePackage); table.setType(type); table.setColumns(columns); - table.setForeignKeys(assembleForeignKeys(element)); + table.setForeignKeys(foreignKeys); + table.setIndexes(indexes); + table.setConstraints (constraints); + table.setTriggers (triggers); return table; } @@ -54,25 +71,134 @@ private static List assembleColumns(Element element) { } } } - return columns; } - private static List assembleForeignKeys(Element element) { + private static List assembleIndexes (Element element) + { + 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); + } + 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<>(); + + 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/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..0412d66 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,27 @@ public class DataModel { private static final String TABLES = "tables"; + private static final String INDEXES = "indexes"; + 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(FOREIGN_KEYS, data.getForeignKeys()); + map.put(CONSTRAINTS, data.getConstraints()); + map.put(TRIGGERS, data.getTriggers()); + map.putAll(GetCursorGetterMethod.getMethodMap()); map.putAll(GetInsertValueMethod.getMethodMap()); map.putAll(AssembleCreateTableMethod.getMethodMap()); + map.putAll(AssembleCreateIndexesMethod.getMethodMap()); + map.putAll(AssembleCreateForeignKeysMethod.getMethodMap()); + map.putAll(AssembleCreateConstraintsMethod.getMethodMap()); + map.putAll(AssembleCreateTriggersMethod.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..b28dae2 --- /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("CREATE 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..c14ed05 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateIndexesMethod.java @@ -0,0 +1,74 @@ +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() { + } + + /** + * 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 " + index.getIndexName() + " ON " + index.getTableName() + " ("); + + for (IndexColumn indexColumn : index.getColumns()) + { + sb.append(indexColumn.getColumn()) + .append(indexColumn.getSortOrder()) + .append(","); + } + + sb.deleteCharAt(sb.length() - 1); + + sb.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 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..4b6cb6d 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,15 @@ 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.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,58 +31,83 @@ 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(); - 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++) { + 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.hasPrimaryKey()) { - statementBuilder.append(" PRIMARY KEY"); - if (column.hasAutoIncrement()) { - statementBuilder.append(" AUTOINCREMENT"); + if (!column.isJoinable(tables)) + { + sb.append(column.getName()) + .append(" ") + .append(getSQLDataTypeFromClassRef(column.getType())); + + if (column.hasPrimaryKey()) + { + sb.append(" PRIMARY KEY"); + if (column.hasAutoIncrement()) + { + sb.append(" AUTOINCREMENT"); + } + else if (column.isNotNull()) + { + sb.append(" NOT NULL"); + } + else if (column.getDefaultValue().length() > 0 ) + { + sb.append(" DEFAULT ") + .append(column.getDefaultValue()); + } + else if (column.getForeignKey().getForeignTableName().length() > 0) + { + sb.append(" FOREIGN KEY REFERENCES ") + .append(column.getForeignKey().getForeignTableName()) + .append(" (") + .append(column.getForeignKey().getForeignColumnNames().get(0)) + .append(")"); + } + + for (Constraint constraint : column.getConstraints()) + { + if (constraint.getOnConflict() != ConflictAction.NA) + { + sb.append(" CONSTRAINT ") + .append(constraint.getConstraintName()) + .append(" ") + .append(constraint.getConstraintExpression()); + + sb.append(" ON CONFLICT ") + .append(constraint.getOnConflict().toString()); + } } } - - statementBuilder.append(","); + sb.append(","); } } + sb.deleteCharAt(sb.length() - 1); - for (ForeignKey foreignKey : table.getForeignKeys()) { - statementBuilder.append("FOREIGN KEY(") - .append(foreignKey.getThisColumn()).append(") REFERENCES ") - .append(foreignKey.getTable()) - .append("(") - .append(foreignKey.getForeignColumn()) - .append("),"); - } - - statementBuilder.deleteCharAt(statementBuilder.length()-1); - - statementBuilder.append(");"); + sb.append(");"); - return "\"" + statementBuilder.toString() + "\";"; + return "\"" + sb.toString() + "\";"; } /** 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..969a483 --- /dev/null +++ b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateTriggersMethod.java @@ -0,0 +1,101 @@ +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(); + StringBuilder sbDebug = 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..e2ccdd1 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.hasPrimaryKey() && column.hasAutoIncrement()) + { 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..bfbe1e1 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()}_${index.getIndexName()}_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)}; + } + + @Override + public String getCreateTriggersQuery() { + return ${assembleCreateTriggers(table)}; - return (sb.length() > 0) ? sb.toString() : null; } @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..5179958 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java @@ -2,6 +2,9 @@ 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.ForeignKey; @Table public class Data { @@ -11,7 +14,6 @@ public class Data { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +21,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..abebf58 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java @@ -2,8 +2,19 @@ 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.ForeignKey; -@Table +@Table( + indexes = { + @Index(indexName = "timestamp", + columns = { + @IndexColumn(column = "timestamp") + } + ) + } +) public class Log { @Column(primary_key = true) int id; @Column long timestamp; @@ -11,7 +22,6 @@ public class Log { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -19,7 +29,6 @@ public void setId(int 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..cc56e2c 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,37 @@ 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.ForeignKey; -@Table +@Table( + indexes = { + @Index(indexName = "timestamp", + columns = { + @IndexColumn(column = "timestamp") + } + ) + } +) public class Post { - @Column(primary_key = true) String id; + @Column(primary_key = true, auto_increment = true) 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 +40,6 @@ public void setTitle(String newVal) { public byte[] getBlob() { return blob; } - public void setBlob(byte[] newVal) { blob = newVal; } @@ -39,7 +47,6 @@ public void setBlob(byte[] newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -47,7 +54,6 @@ public void setTimestamp(long newVal) { public User getUser() { return user; } - public void setUser(User user) { this.user = user; } @@ -55,7 +61,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..d95e198 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/User.java @@ -3,16 +3,31 @@ import com.memtrip.sqlking.common.Column; 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; @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 long timestamp; @@ -26,7 +41,6 @@ public class User { public String getUsername() { return username; } - public void setUsername(String newVal) { username = newVal; } @@ -34,7 +48,6 @@ public void setUsername(String newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -42,7 +55,6 @@ public void setTimestamp(long newVal) { public boolean getIsRegistered() { return isRegistered; } - public void setIsRegistered(boolean newVal) { isRegistered = newVal; } @@ -50,7 +62,6 @@ public void setIsRegistered(boolean newVal) { public byte[] getProfilePicture() { return profilePicture; } - public void setProfilePicture(byte[] newVal) { profilePicture = newVal; } @@ -58,7 +69,6 @@ public void setProfilePicture(byte[] newVal) { public double getRating() { return rating; } - public void setRating(double rating) { this.rating = rating; } @@ -66,7 +76,6 @@ public void setRating(double rating) { public int getCount() { return count; } - public void setCount(int count) { this.count = count; } @@ -74,7 +83,6 @@ public void setCount(int count) { public int getLogId() { return logId; } - public void setLogId(int logId) { this.logId = logId; } @@ -82,7 +90,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; } From c614d7b134ce6626ed2ea8dbbd9a0f00dbb56490 Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Mon, 26 Sep 2016 14:18:48 +0200 Subject: [PATCH 3/8] Fixed whitespace error on creation of indexes; Added a windows-based build-allw.cmd file --- build-allw.cmd | 6 ++++++ .../freemarker/method/AssembleCreateIndexesMethod.java | 1 + 2 files changed, 7 insertions(+) create mode 100644 build-allw.cmd 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/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 index c14ed05..1cff67d 100644 --- 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 @@ -42,6 +42,7 @@ private String buildCreateIndexStatements(Table table) for (IndexColumn indexColumn : index.getColumns()) { sb.append(indexColumn.getColumn()) + .append(" ") .append(indexColumn.getSortOrder()) .append(","); } From a5370cd19ac224d245d4f66987eb78750b5f38ae Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Wed, 5 Oct 2016 10:16:13 +0200 Subject: [PATCH 4/8] Added better, clearer support for Table-level and Column-level annotations for Primary Keys, Foreign Keys, Indexes, Triggers and Constraints --- .../sqlking/database/ClauseHelper.java | 62 ++++++---- .../com/memtrip/sqlking/database/Query.java | 1 + .../com/memtrip/sqlking/database/SQLOpen.java | 4 +- .../memtrip/sqlking/database/SQLProvider.java | 3 +- .../sqlking/operation/function/Select.java | 57 ++++++--- .../operation/join/CrossInnerJoin.java | 12 +- .../sqlking/operation/join/InnerJoin.java | 24 +++- .../memtrip/sqlking/operation/join/Join.java | 21 ++++ .../sqlking/operation/join/LeftOuterJoin.java | 12 +- .../operation/join/NaturalInnerJoin.java | 12 +- .../operation/join/NaturalLeftOuterJoin.java | 12 +- .../memtrip/sqlking/integration/JoinTest.java | 27 +++-- .../sqlking/integration/models/Data.java | 2 - .../sqlking/integration/models/Log.java | 6 +- .../sqlking/integration/models/Post.java | 7 -- .../sqlking/integration/models/User.java | 12 +- .../com/memtrip/sqlking/common/Check.java | 25 ++++ .../com/memtrip/sqlking/common/Column.java | 16 ++- .../sqlking/common/ConflictAction.java | 2 +- .../memtrip/sqlking/common/Constraint.java | 4 +- .../memtrip/sqlking/common/ForeignKey.java | 2 +- .../com/memtrip/sqlking/common/NotNull.java | 24 ++++ .../memtrip/sqlking/common/PrimaryKey.java | 7 +- .../com/memtrip/sqlking/common/Table.java | 1 + preprocessor/buildw.cmd | 4 + .../preprocessor/processor/FreeMarker.java | 56 ++++++--- .../preprocessor/processor/Processor.java | 8 +- .../preprocessor/processor/data/Column.java | 48 +++----- .../processor/data/Constraint.java | 2 +- .../preprocessor/processor/data/Data.java | 14 +-- .../processor/data/ForeignKey.java | 6 +- .../preprocessor/processor/data/NotNull.java | 15 +++ .../processor/data/PrimaryKey.java | 23 ++++ .../preprocessor/processor/data/Table.java | 27 ++--- .../preprocessor/processor/data/Trigger.java | 5 - .../data/parse/ParseColumnAnnotation.java | 65 +++++++---- .../data/parse/ParseTableAnnotation.java | 87 +++++++++++--- .../validator/PrimaryKeyMustBeUnique.java | 30 +++-- .../processor/freemarker/DataModel.java | 14 ++- .../AssembleCreateForeignKeysMethod.java | 6 +- .../method/AssembleCreateIndexesMethod.java | 9 +- .../method/AssembleCreateTableMethod.java | 109 ++++++++++++++---- .../method/AssembleCreateTriggersMethod.java | 59 +++++----- .../method/GetInsertValueMethod.java | 2 +- preprocessor/src/main/resources/Q.java | 6 +- .../memtrip/sqlking/preprocessor/Data.java | 17 ++- .../com/memtrip/sqlking/preprocessor/Log.java | 21 ++-- .../memtrip/sqlking/preprocessor/Post.java | 9 +- .../memtrip/sqlking/preprocessor/User.java | 8 +- 49 files changed, 684 insertions(+), 321 deletions(-) create mode 100644 common/src/main/java/com/memtrip/sqlking/common/Check.java create mode 100644 common/src/main/java/com/memtrip/sqlking/common/NotNull.java create mode 100644 preprocessor/buildw.cmd create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/NotNull.java create mode 100644 preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/data/PrimaryKey.java 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..0dca5c7 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java +++ b/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java @@ -49,7 +49,7 @@ 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(); @@ -59,7 +59,6 @@ public String getClause(Clause[] clause) { clauseBuilder.append(getClause(item)); } } - return clauseBuilder.toString(); } @@ -74,7 +73,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 +86,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 +135,6 @@ private String buildInCondition(In in) { stringBuilder.append(VALUE); stringBuilder.append(COMMA); } - stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length()); } @@ -241,52 +242,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.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 +312,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.length() > 0) + { + sb.append(" AS ") + .append(tableAlias); + } + sb.append(" ") .append(getJoinStatement(joins, resolver)) .append(" ") .append(clauseString) @@ -314,7 +328,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/SQLOpen.java b/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java index 599ca76..b9b1aa4 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java +++ b/client/src/main/java/com/memtrip/sqlking/database/SQLOpen.java @@ -67,13 +67,13 @@ public void onCreate(SQLiteDatabase db) { } for (String createIndex : mCreateIndexStatements) { - if (createIndex != null) { + if (createIndex != null && createIndex.length() > 0) { db.execSQL(createIndex); } } for (String createTrigger : mCreateTriggerStatements) { - if (createTrigger != null) { + if (createTrigger != null && createTrigger.length() > 0) { db.execSQL(createTrigger); } } 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..f51701f 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,15 @@ @SuppressWarnings("unchecked") public class LeftOuterJoin extends Join { - public LeftOuterJoin(Class table, Join join, Clause... clauses) { - super(table, join, 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); + public static LeftOuterJoin leftOuterJoin(Class table, String tableAlias, Clause... clauses) { + return new LeftOuterJoin(table, tableAlias, null, clauses); } - public static LeftOuterJoin leftOuterJoin(Class table, Join join, Clause... clauses) { - return new LeftOuterJoin(table, join, 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/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 961d97d..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 @@ -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 e503f99..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 @@ -16,8 +16,7 @@ }, indexes = { @Index(indexName = "username", - indexColumns = { - @IndexColumn(column = "username")} + columns = { @IndexColumn(column = "username") } ) } ) @@ -35,7 +34,6 @@ public class User { public int getId() { return id; } - public void setId(int id) { this.id = id; } @@ -43,7 +41,6 @@ public void setId(int id) { public String getUsername() { return username; } - public void setUsername(String newVal) { username = newVal; } @@ -51,7 +48,6 @@ public void setUsername(String newVal) { public long getTimestamp() { return timestamp; } - public void setTimestamp(long newVal) { timestamp = newVal; } @@ -59,7 +55,6 @@ public void setTimestamp(long newVal) { public boolean getIsRegistered() { return isRegistered; } - public void setIsRegistered(boolean newVal) { isRegistered = newVal; } @@ -67,7 +62,6 @@ public void setIsRegistered(boolean newVal) { public byte[] getProfilePicture() { return profilePicture; } - public void setProfilePicture(byte[] newVal) { profilePicture = newVal; } @@ -75,7 +69,6 @@ public void setProfilePicture(byte[] newVal) { public double getRating() { return rating; } - public void setRating(double rating) { this.rating = rating; } @@ -83,7 +76,6 @@ public void setRating(double rating) { public int getCount() { return count; } - public void setCount(int count) { this.count = count; } @@ -91,7 +83,6 @@ public void setCount(int count) { public int getLogId() { return logId; } - public void setLogId(int logId) { this.logId = logId; } @@ -99,7 +90,6 @@ public void setLogId(int logId) { public Log getLog() { return log; } - public void setLog(Log log) { this.log = log; } 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 87c29fd..e507965 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Column.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Column.java @@ -21,11 +21,15 @@ */ public @interface Column { - boolean index() default false; - boolean primary_key() default false; - boolean auto_increment() default false; - boolean not_null() default false; - String defaultValue() default ""; - ForeignKey foreignKey() default @ForeignKey (); + 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 index b295a23..203d6a0 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java +++ b/common/src/main/java/com/memtrip/sqlking/common/ConflictAction.java @@ -21,7 +21,7 @@ public enum ConflictAction { - NA ("NA"), + NONE ("NONE"), ROLLBACK ("ROLLBACK"), ABORT ("ABORT"), FAIL ("FAIL"), diff --git a/common/src/main/java/com/memtrip/sqlking/common/Constraint.java b/common/src/main/java/com/memtrip/sqlking/common/Constraint.java index 9e148fc..a0e8c76 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Constraint.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Constraint.java @@ -20,7 +20,7 @@ */ public @interface Constraint { - String constraintName(); + String constraintName() default ""; String expression(); - ConflictAction onConflict() default ConflictAction.NA; + 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 4549674..1251bbc 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java +++ b/common/src/main/java/com/memtrip/sqlking/common/ForeignKey.java @@ -21,7 +21,7 @@ */ @SuppressWarnings("WeakerAccess") -public @interface ForeignKey +public @interface ForeignKey // table level Foreign Key - allows for a composite key (multiple columns) { String foreignTableName () default ""; String foreignTableAlias () default ""; 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 index f7e8ab9..9a82cba 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java +++ b/common/src/main/java/com/memtrip/sqlking/common/PrimaryKey.java @@ -21,8 +21,9 @@ public @interface PrimaryKey // Table Level Primary key { - Column[] columns(); + 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.ROLLBACK; - boolean autoIncrement() default false; + ConflictAction onConflict() default ConflictAction.NONE; } \ 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 a4dc5db..cc13d59 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Table.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Table.java @@ -20,6 +20,7 @@ */ public @interface Table { Index[] indexes() default {}; + PrimaryKey primaryKey() default @PrimaryKey(); ForeignKey[] foreignKeys() default {}; Constraint[] constraints() default {}; Trigger[] triggers() default {}; 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/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 5859a38..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,7 @@ 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; @@ -18,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; @@ -67,7 +70,7 @@ public boolean process(Set annotations, RoundEnvironment 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() @@ -90,6 +93,7 @@ public Set getSupportedAnnotationTypes() { 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()); @@ -113,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 9704422..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,16 +2,17 @@ import java.util.List; + public class Column { private String mName; private String mClassName; private String mType; + private PrimaryKey mPrimaryKey; + private ForeignKey mForeignKey; private boolean mIsIndex; - private boolean mIsNotNull; - private boolean mPrimaryKey; - private boolean mHasAutoIncrement; + private NotNull mNotNull; + private boolean mUnique; private String mDefaultValue; - private ForeignKey mForeignKey; private List mConstraints; public String getName() { @@ -35,9 +36,9 @@ 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; } @@ -45,28 +46,17 @@ public void setIsIndex(boolean newVal) { mIsIndex = newVal; } - public boolean isNotNull () + public NotNull getNotNull () { - return mIsNotNull; + return mNotNull; } - public void setNotNull (boolean newVal) + public void setNotNull (NotNull newVal) { - this.mIsNotNull = newVal; + this.mNotNull = newVal; } - public boolean hasPrimaryKey() { - return mPrimaryKey; - } - public void setHasPrimaryKey(boolean newVal) { - mPrimaryKey = newVal; - } - - public boolean hasAutoIncrement() { - return mHasAutoIncrement; - } - public void setHasAutoIncrement(boolean newVal) { - mHasAutoIncrement = newVal; - } + public boolean isUnique () { return mUnique; } + public void setUnique (boolean mUnique) { this.mUnique = mUnique; } public String getDefaultValue () { @@ -80,14 +70,8 @@ public void setDefaultValue (String 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 List getConstraints () { return mConstraints; } + public void setConstraints (List newVal) { this.mConstraints = newVal; } public Table getRootTable (List
tables) { if (isJoinable(tables)) { 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 index e141e77..50a139c 100644 --- 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 @@ -8,7 +8,7 @@ public class Constraint { private String mConstraintName; private String mConstraintExpression; - private ConflictAction mOnConflict = ConflictAction.NA; + private ConflictAction mOnConflict = ConflictAction.NONE; public String getConstraintName () { 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 61989e2..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 @@ -5,6 +5,7 @@ public class Data { private List
mTables; private List mIndexes; + private PrimaryKey mPrimaryKey; private List mForeignKeys; private List mConstraints; private List mTriggers; @@ -19,14 +20,11 @@ public void setTables(List
newVal) { public List getIndexes() { return mIndexes; } public void setIndexes(List newVal) { mIndexes = newVal; } - public List getForeignKeys () - { - return mForeignKeys; - } - public void setForeignKeys (List newVal) - { - this.mForeignKeys = 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; } 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 d37959d..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,8 +1,12 @@ package com.memtrip.sqlking.preprocessor.processor.data; +/** + * Author: A.Velcich + */ + import java.util.List; import com.memtrip.sqlking.common.RIRule; -import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; + public class ForeignKey { private String mForeignTableName; 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 8e7dea7..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 @@ -7,10 +7,10 @@ public class Table { private Element mElement; private String mName; - private String mAliasName = ""; private String mPackage; private String mType; private List mColumns; + private PrimaryKey mPrimaryKey; private List mForeignKeys; private List mIndexes; private List mConstraints; @@ -24,15 +24,12 @@ public void setElement(Element newVal) { } public String getName() { - return mAliasName.length() > 0 ? mAliasName : mName; + return mName; } public void setName(String newVal) { mName = newVal; } - public String getAliasName () { return mAliasName; } - public void setAliasName (String newVal) { this.mAliasName = mAliasName; }; - public String getPackage () { return mPackage; } @@ -40,9 +37,6 @@ public void setPackage(String newVal) { mPackage = newVal; } - /** - * (Used in Q.java freemarker template) - */ public String getType() { return mType; } @@ -57,16 +51,19 @@ 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; - } + return mIndexes; + } public void setIndexes(List newVal) { mIndexes = newVal; } @@ -77,10 +74,6 @@ public void setIndexes(List newVal) { public List getTriggers () { return mTriggers; } public void setTriggers (List newVal) { this.mTriggers = newVal; } -/** - * (Used in Q.java freemarker template) - * @return all columns ignoring any object mappings - */ 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 index 4263281..9a7e780 100644 --- 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 @@ -1,7 +1,3 @@ -/** - * Author: A.Velcich - */ - package com.memtrip.sqlking.preprocessor.processor.data; /** @@ -9,7 +5,6 @@ */ import java.util.List; -import com.memtrip.sqlking.preprocessor.processor.utils.StringUtils; import com.memtrip.sqlking.common.TriggerTime; import com.memtrip.sqlking.common.TriggerType; 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 af60bea..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,8 +1,11 @@ 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; @@ -19,25 +22,24 @@ static Column parseColumn(Element element) { String className = assembleClassName(type); boolean isIndex = assembleIsIndex(element); - boolean hasPrimaryKey = assemblePrimaryKey(element); - boolean hasAutoIncrement = assembleAutoIncrement(element); - boolean isNotNotNull = assembleNotNull(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.setType(type); column.setClassName(className); column.setIsIndex(isIndex); - column.setHasPrimaryKey(hasPrimaryKey); - column.setHasAutoIncrement(hasAutoIncrement); - column.setNotNull(isNotNotNull); + column.setPrimaryKey(primaryKey); + column.setNotNull(notNull); column.setDefaultValue(defaultValue); column.setConstraints(constraints); column.setForeignKey(foreignKey); - column.setConstraints(constraints); return column; } @@ -59,22 +61,43 @@ 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 boolean assemblePrimaryKey(Element element) { - com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column.primary_key(); - } + 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(); - private static boolean assembleAutoIncrement(Element element) { - com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column.auto_increment(); + 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 assembleNotNull(Element element) { + private static NotNull assembleNotNull(Element element) { com.memtrip.sqlking.common.Column column = element.getAnnotation(com.memtrip.sqlking.common.Column.class); - return column.not_null(); + 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 String assembleDefaultValue(Element element) { @@ -85,13 +108,13 @@ private static String assembleDefaultValue(Element element) { 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); @@ -120,7 +143,7 @@ private static List assembleConstraints(Element element) { { Constraint constraint = new Constraint(); - constraint.setConstraintName(constraintAnnotation.constraintName()); + constraint.setConstraintName(""); constraint.setConstraintExpression(constraintAnnotation.expression()); constraint.setOnConflict(constraintAnnotation.onConflict()); 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 dda512c..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 @@ -4,9 +4,11 @@ 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; @@ -30,18 +32,24 @@ static Table parseTable(Element element) String name = assembleName(element); String tablePackage = assemblePackage(element); String type = tablePackage + "." + name; + + System.out.println("++ Preprocessing table: " + type); + List columns = assembleColumns(element); + PrimaryKey primaryKey = assemblePrimaryKey(element); List foreignKeys = assembleForeignKeys(element); - List indexes = assembleIndexes(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.setPrimaryKey(primaryKey); table.setForeignKeys(foreignKeys); table.setIndexes(indexes); table.setConstraints (constraints); @@ -74,7 +82,24 @@ private static List assembleColumns(Element element) { return columns; } - private static List assembleIndexes (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(); @@ -109,6 +134,31 @@ private static List assembleIndexes (Element element) 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; } @@ -174,28 +224,31 @@ private static List assembleTriggers(Element element) List triggers = new ArrayList<>(); - for (com.memtrip.sqlking.common.Trigger triggerAnnotation : triggersAnnotation) + if (triggersAnnotation != null && triggersAnnotation.length > 0) { - Trigger trigger = new Trigger(); + for (com.memtrip.sqlking.common.Trigger triggerAnnotation : triggersAnnotation) + { + Trigger trigger = new Trigger(); - trigger.setTriggerName(triggerAnnotation.triggerName()); - trigger.setTriggerTime(triggerAnnotation.triggerTime()); - trigger.setTriggerType(triggerAnnotation.triggerType()); + trigger.setTriggerName(triggerAnnotation.triggerName()); + trigger.setTriggerTime(triggerAnnotation.triggerTime()); + trigger.setTriggerType(triggerAnnotation.triggerType()); - List onUpdateColumns = new ArrayList<>(); + List onUpdateColumns = new ArrayList<>(); - for (String columnName : triggerAnnotation.updateOfColumnNames()) - { - onUpdateColumns.add(columnName); - } + for (String columnName : triggerAnnotation.updateOfColumnNames()) + { + onUpdateColumns.add(columnName); + } - trigger.setOnUpdateOfColumnNames(onUpdateColumns); + trigger.setOnUpdateOfColumnNames(onUpdateColumns); - trigger.setForEachRow(triggerAnnotation.forEachRow()); - trigger.setWhenExpression(triggerAnnotation.whenExpression()); - trigger.setStatement(triggerAnnotation.statement()); + trigger.setForEachRow(triggerAnnotation.forEachRow()); + trigger.setWhenExpression(triggerAnnotation.whenExpression()); + trigger.setStatement(triggerAnnotation.statement()); - triggers.add(trigger); + triggers.add(trigger); + } } return triggers; 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..a895412 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,16 +17,27 @@ 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()) { - occurrences++; - } - } - } +// PrimaryKey primaryKey = table.getPrimaryKey(); +// +// if (primaryKey != null && primaryKey.getColumns().length > 0) +// { +// occurrences++; +// } + +// if (table.getColumns() != null) { +// for (Column column : table.getColumns()) { +// +// PrimaryKey primaryKey = column.getPrimaryKey(); +// +// if (primaryKey != null) { +//// if (primaryKey.getColumns().length > 0) { +// occurrences++; +// } +// } +// } return occurrences > 1; } @@ -33,7 +45,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/freemarker/DataModel.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/DataModel.java index 0412d66..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 @@ -10,6 +10,7 @@ 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"; @@ -19,17 +20,18 @@ public static Map create(Data data) { map.put(TABLES, data.getTables()); map.put(INDEXES, data.getIndexes()); - map.put(FOREIGN_KEYS, data.getForeignKeys()); - map.put(CONSTRAINTS, data.getConstraints()); +// map.put(PRIMARY_KEY, data.getPrimaryKey()); +// map.put(FOREIGN_KEYS, data.getForeignKeys()); +// map.put(CONSTRAINTS, data.getConstraints()); map.put(TRIGGERS, data.getTriggers()); - map.putAll(GetCursorGetterMethod.getMethodMap()); - map.putAll(GetInsertValueMethod.getMethodMap()); map.putAll(AssembleCreateTableMethod.getMethodMap()); map.putAll(AssembleCreateIndexesMethod.getMethodMap()); - map.putAll(AssembleCreateForeignKeysMethod.getMethodMap()); - map.putAll(AssembleCreateConstraintsMethod.getMethodMap()); +// map.putAll(AssembleCreateForeignKeysMethod.getMethodMap()); +// map.putAll(AssembleCreateConstraintsMethod.getMethodMap()); map.putAll(AssembleCreateTriggersMethod.getMethodMap()); + map.putAll(GetCursorGetterMethod.getMethodMap()); + map.putAll(GetInsertValueMethod.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/AssembleCreateForeignKeysMethod.java b/preprocessor/src/main/java/com/memtrip/sqlking/preprocessor/processor/freemarker/method/AssembleCreateForeignKeysMethod.java index b28dae2..727cb0c 100644 --- 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 @@ -52,16 +52,16 @@ private String buildCreateForeignKeyStatements (Table table) for (ForeignKey foreignKey : foreignKeyList) { - sb.append("CREATE FOREIGN KEY(") + sb.append("CONSTRAINT FOREIGN KEY(") .append(foreignKey.getLocalColumnNames().toString().replaceAll("[\\[\\]]", "")) .append(") REFERENCES ") .append(foreignKey.getForeignTableName()) .append("(") .append(foreignKey.getForeignColumnNames().toString().replaceAll("[\\[\\]]", "")) - .append(");"); + .append(") "); } - return "\"" + sb.toString() + "\";"; + return "\"" + sb.toString() + "\""; } 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 index 1cff67d..8a40edf 100644 --- 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 @@ -24,6 +24,10 @@ public static Map getMethodMap() { 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 @@ -37,7 +41,7 @@ private String buildCreateIndexStatements(Table table) for (Index index : indexes) { - sb.append("CREATE INDEX " + index.getIndexName() + " ON " + index.getTableName() + " ("); + sb.append("CREATE INDEX " + buildIndexName(index) + " ON " + index.getTableName() + " ("); for (IndexColumn indexColumn : index.getColumns()) { @@ -52,6 +56,9 @@ private String buildCreateIndexStatements(Table table) sb.append(");"); } + + System.out.println("++ " + sb.toString()); + return "\"" + sb.toString() + "\""; } 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 4b6cb6d..41cf9b8 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 @@ -4,6 +4,7 @@ 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; @@ -46,11 +47,14 @@ private AssembleCreateTableMethod() { private String buildCreateTableStatement(Table table, List
tables) { StringBuilder sb = new StringBuilder(); + int tableConstraintCount = 0; sb.append("CREATE TABLE "); sb.append(table.getName()); sb.append(" ("); +//......Columns and column contraints + for (int i = 0; i < table.getColumns().size(); i++) { Column column = table.getColumns().get(i); @@ -61,34 +65,55 @@ private String buildCreateTableStatement(Table table, List
tables) .append(" ") .append(getSQLDataTypeFromClassRef(column.getType())); - if (column.hasPrimaryKey()) + if (column.getPrimaryKey() != null && column.getPrimaryKey().isActive() == true) { sb.append(" PRIMARY KEY"); - if (column.hasAutoIncrement()) + + if (column.getPrimaryKey().isAutoNumber()) { sb.append(" AUTOINCREMENT"); } - else if (column.isNotNull()) - { - sb.append(" NOT NULL"); - } - else if (column.getDefaultValue().length() > 0 ) + + if (column.getPrimaryKey().getOnConflict() != ConflictAction.NONE) { - sb.append(" DEFAULT ") - .append(column.getDefaultValue()); + sb.append(" ON CONFLICT ") + .append (column.getPrimaryKey().getOnConflict().toString()); } - else if (column.getForeignKey().getForeignTableName().length() > 0) + + } + + if (column.getNotNull() != null) + { + if (column.getNotNull().getOnConflict() != ConflictAction.NONE ) { - sb.append(" FOREIGN KEY REFERENCES ") - .append(column.getForeignKey().getForeignTableName()) - .append(" (") - .append(column.getForeignKey().getForeignColumnNames().get(0)) - .append(")"); + 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 ") + .append(table.getName().toLowerCase() + "_" + foreignKey.getForeignTableName().toLowerCase() + "_" + column.getName().toLowerCase() + "_fk") + .append("(") + .append(foreignKey.getLocalColumnNames().get(0).replaceAll("\\[|\\]", "")) + .append(") REFERENCES ") + .append(column.getForeignKey().getForeignTableName()) + .append(" (") + .append(column.getForeignKey().getForeignColumnNames().get(0).replaceAll("\\[|\\]", "")) + .append(")"); + } for (Constraint constraint : column.getConstraints()) { - if (constraint.getOnConflict() != ConflictAction.NA) + if (constraint.getOnConflict() != ConflictAction.NONE) { sb.append(" CONSTRAINT ") .append(constraint.getConstraintName()) @@ -99,16 +124,60 @@ else if (column.getForeignKey().getForeignTableName().length() > 0) .append(constraint.getOnConflict().toString()); } } + sb.append(","); } - sb.append(","); } - } + sb.deleteCharAt(sb.length() - 1); +//......Table constraints and triggers + + PrimaryKey primaryKey = table.getPrimaryKey(); + + 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()); + } + } + + int fkCount = 1; + + for (ForeignKey foreignKey : table.getForeignKeys()) + { + if (tableConstraintCount > 0) + { + sb.append(", "); + } + + tableConstraintCount++; + + sb.append(" FOREIGN KEY ") + .append(table.getName().toLowerCase() + "_" + foreignKey.getForeignTableName().toLowerCase() + "_" + fkCount + "_fk") + .append(" (") + .append(foreignKey.getLocalColumnNames().toString().replaceAll("\\[|\\]", "")) + .append(") REFERENCES ") + .append(foreignKey.getForeignTableName()) + .append(" (") + .append(foreignKey.getForeignColumnNames().toString().replaceAll("\\[|\\]", "")) + .append(")"); + fkCount++; + } sb.append(");"); - return "\"" + sb.toString() + "\";"; - } + System.out.println("++ " + sb.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 index 969a483..91e6f17 100644 --- 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 @@ -35,41 +35,40 @@ public static Map getMethodMap () private String buildCreateTriggerStatements (Table table) { StringBuilder sb = new StringBuilder(); - StringBuilder sbDebug = 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()); +// 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); } 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 e2ccdd1..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 @@ -28,7 +28,7 @@ private GetInsertValueMethod() { private String assembleInsertValue(Column column, String getter) { - if (column.hasPrimaryKey() && column.hasAutoIncrement()) + if (column.getPrimaryKey() != null && column.getPrimaryKey().isAutoNumber()) { return "NULL"; } diff --git a/preprocessor/src/main/resources/Q.java b/preprocessor/src/main/resources/Q.java index bfbe1e1..4497eef 100644 --- a/preprocessor/src/main/resources/Q.java +++ b/preprocessor/src/main/resources/Q.java @@ -55,7 +55,7 @@ public String getTableName() { @Override public String getTableCreateQuery() { - return ${assembleCreateTable(table, tables)} + return ${assembleCreateTable(table, tables)}; } @Override @@ -67,7 +67,7 @@ public String[] getIndexNames() { <#list table.getIndexes() as index> - "${table.getName()}_${index.getIndexName()}_index", + "${table.getName()?lower_case}_${index.getIndexName()?lower_case}_index", }; } @@ -80,6 +80,7 @@ public String[] getTriggerNames() { }; } + @Override public String getCreateIndexesQuery() { return ${assembleCreateIndexes(table)}; @@ -88,7 +89,6 @@ public String getCreateIndexesQuery() { @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 5179958..11c8302 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Data.java @@ -4,11 +4,22 @@ import com.memtrip.sqlking.common.Table; import com.memtrip.sqlking.common.Index; import com.memtrip.sqlking.common.IndexColumn; -import com.memtrip.sqlking.common.ForeignKey; +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() { 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 abebf58..e34b737 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Log.java @@ -4,27 +4,26 @@ import com.memtrip.sqlking.common.Table; import com.memtrip.sqlking.common.Index; import com.memtrip.sqlking.common.IndexColumn; -import com.memtrip.sqlking.common.ForeignKey; +import com.memtrip.sqlking.common.PrimaryKey; @Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, + auto_increment = true + ), indexes = { @Index(indexName = "timestamp", - columns = { - @IndexColumn(column = "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; 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 cc56e2c..1c54a18 100644 --- a/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java +++ b/preprocessor/src/test/java/com/memtrip/sqlking/preprocessor/Post.java @@ -4,9 +4,14 @@ import com.memtrip.sqlking.common.Table; import com.memtrip.sqlking.common.Index; import com.memtrip.sqlking.common.IndexColumn; -import com.memtrip.sqlking.common.ForeignKey; +import com.memtrip.sqlking.common.PrimaryKey; @Table( + primaryKey = @PrimaryKey( + active = true, + columns = {"id"}, + auto_increment = true + ), indexes = { @Index(indexName = "timestamp", columns = { @@ -16,7 +21,7 @@ } ) public class Post { - @Column(primary_key = true, auto_increment = true) int id; + @Column int id; @Column String title; @Column byte[] blob; @Column long timestamp; 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 d95e198..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,11 +1,15 @@ 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 = { @@ -29,7 +33,9 @@ ) 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; From 36034d1f16383b9da3c4439964d01ba4a64f3df3 Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Wed, 5 Oct 2016 11:02:44 +0200 Subject: [PATCH 5/8] Updated README documentation for Table-level and Column level Annotations --- README.md | 77 ++++++++++++++++--- .../memtrip/sqlking/common/TriggerType.java | 3 +- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7485598..21dd42a 100644 --- a/README.md +++ b/README.md @@ -298,13 +298,17 @@ Comment[] comments = Select.getBuilder() User user = comments[0].getUser(); // The nested User object is populated by the join ``` -####Primary Key#### +####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; @@ -316,16 +320,49 @@ 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 Composite Indexes and Foreign Keys can be defined for the table, and will be created automatically when the table is created: +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, but will be enforced by SQLite DBMS) - 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 + 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 + foreignColumnNames = {"foreignColumn"[, ...]// Multiple columns possible + [,updateRule = ] + [,deleteRule = ] + } )[, ...] // optional additional @ForeignKey statements }, @@ -339,13 +376,32 @@ Multiple Composite Indexes and Foreign Keys can be defined for the table, and wi }, 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` - [,@onConflict (ConflictAction.ROLLBACK|ABORT|FAIL|etc)] // as appropriate, if required + 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 = ] // only one trigger time is allowed, but it is not required (default is TriggerTime.NONE) + [,triggerType = ] // only one trigger type is allowed, but is not required (default is triggerType.NONE) + [,updateOfColumns = { column[,...] }] // one or more columns + [,forEachRow = true|false] // not required, defaults to false. SQLite does not currently support FOR_EACH_STATEMENT + [,whenExpression = "my_when_expression"] // 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. @@ -356,4 +412,5 @@ tests can be used as a good reference on how to structure queries. - @NotNull annotation and handle this validation in the software layer - 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 \ No newline at end of file +- 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/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java b/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java index f3e15e1..1deb572 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerType.java @@ -12,7 +12,8 @@ public enum TriggerType { DELETE ("DELETE"), INSERT ("INSERT"), - UPDATE ("UPDATE"); + UPDATE ("UPDATE"), + NONE ("NONE"); private final String text; From 959d404ca25b13384a6e4066d563e0313c512eaf Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Wed, 5 Oct 2016 11:17:07 +0200 Subject: [PATCH 6/8] More amendments to README, and small changes to Trigger Annotations --- README.md | 35 +++++++++++-------- .../com/memtrip/sqlking/common/Trigger.java | 4 +-- .../memtrip/sqlking/common/TriggerTime.java | 3 +- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 21dd42a..45ee8cc 100644 --- a/README.md +++ b/README.md @@ -364,21 +364,22 @@ Multiple table Constraints, Composite Indexes and Composite Foreign Keys can be |RIRule.NoAction>] } - )[, ...] // optional additional @ForeignKey statements + )[, ...] // 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 + 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 + )[, ...] // 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 + )[, ...] // optional additional @Constraint statements } ) ``` @@ -389,13 +390,19 @@ Triggers can be defined at the Table Level with the following syntax: ```java @Table ( triggers = {@Trigger(triggerName = "my_trigger_name", - [,triggerTime = ] // only one trigger time is allowed, but it is not required (default is TriggerTime.NONE) - [,triggerType = ] // only one trigger type is allowed, but is not required (default is triggerType.NONE) - [,updateOfColumns = { column[,...] }] // one or more columns - [,forEachRow = true|false] // not required, defaults to false. SQLite does not currently support FOR_EACH_STATEMENT - [,whenExpression = "my_when_expression"] // 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 + [,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 } ) diff --git a/common/src/main/java/com/memtrip/sqlking/common/Trigger.java b/common/src/main/java/com/memtrip/sqlking/common/Trigger.java index 3e4b197..c7e8954 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/Trigger.java +++ b/common/src/main/java/com/memtrip/sqlking/common/Trigger.java @@ -21,8 +21,8 @@ public @interface Trigger { String triggerName() default ""; - TriggerTime triggerTime(); - TriggerType triggerType(); + TriggerTime triggerTime() default TriggerTime.NONE; + TriggerType triggerType() default TriggerType.NONE; String[] updateOfColumnNames() default {}; boolean forEachRow() default false; String whenExpression() default ""; diff --git a/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java b/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java index c993b70..28b2f6a 100644 --- a/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java +++ b/common/src/main/java/com/memtrip/sqlking/common/TriggerTime.java @@ -12,7 +12,8 @@ public enum TriggerTime { BEFORE ("BEFORE"), AFTER ("AFTER"), - INSTEAD_OF ("INSTEAD OF"); + INSTEAD_OF ("INSTEAD OF"), + NONE ("NONE"); private final String text; From 991e4d35bbb86e6b83973f6b80aee3344893b879 Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Wed, 5 Oct 2016 11:26:58 +0200 Subject: [PATCH 7/8] Re-enabled the PrimaryKey validation code. ps. I also added some debug statements to the preprocessor project --- .../validator/PrimaryKeyMustBeUnique.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) 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 a895412..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 @@ -20,24 +20,23 @@ public PrimaryKeyMustBeUnique(Data data) { private boolean primaryKeyIsUniqueInColumns(Table table) { int occurrences = 0; -// PrimaryKey primaryKey = table.getPrimaryKey(); -// -// if (primaryKey != null && primaryKey.getColumns().length > 0) -// { -// occurrences++; -// } - -// if (table.getColumns() != null) { -// for (Column column : table.getColumns()) { -// -// PrimaryKey primaryKey = column.getPrimaryKey(); -// -// if (primaryKey != null) { -//// if (primaryKey.getColumns().length > 0) { -// occurrences++; -// } -// } -// } + 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++; + } + } + } return occurrences > 1; } From d9186480c5f86042eebf8fde54be089c1df2e4ff Mon Sep 17 00:00:00 2001 From: Adrian Velcich Date: Wed, 26 Oct 2016 18:04:40 +0200 Subject: [PATCH 8/8] Relaxed support for table alias names not yet fully implemented, Foreign key syntax was not being generated properly --- client/build.gradle | 8 ++-- .../sqlking/database/ClauseHelper.java | 8 ++-- .../sqlking/operation/join/LeftOuterJoin.java | 30 ++++++++++--- common/pom.xml | 2 +- preprocessor/pom.xml | 4 +- .../method/AssembleCreateTableMethod.java | 44 +++++++++---------- 6 files changed, 59 insertions(+), 37 deletions(-) diff --git a/client/build.gradle b/client/build.gradle index dcf8d61..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.7' + libraryVersion = '1.1.8' developerId = 'samkirton' developerName = 'Samuel Kirton' @@ -44,7 +44,7 @@ android { minSdkVersion 11 targetSdkVersion 24 versionCode 7 - versionName "1.1.7" + versionName "1.1.8" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -137,11 +137,11 @@ install { } dependencies { - compile 'com.memtrip.sqlking:common:1.1.7' + 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.7' + 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 0dca5c7..70d4977 100644 --- a/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java +++ b/client/src/main/java/com/memtrip/sqlking/database/ClauseHelper.java @@ -56,7 +56,9 @@ public String getClause(Clause[] clause) { 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(); @@ -255,7 +257,7 @@ public String getJoinStatement(Join[] joins, Resolver resolver) { .append(" ") .append(tableName); - if (tableAliasName.length() > 0) + if (tableAliasName != null && tableAliasName.length() > 0) { sb.append(" AS ") .append(tableAliasName); @@ -314,7 +316,7 @@ public String buildJoinQuery(String[] tableColumns, Join[] joins, String tableNa sb.append(" FROM ") .append(tableName); - if (tableAlias.length() > 0) + if (tableAlias != null && tableAlias.length() > 0) { sb.append(" AS ") .append(tableAlias); 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 f51701f..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); + } + + 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); + super(table, tableAlias, join, clauses); } - + + public static LeftOuterJoin leftOuterJoin(Class table, Clause... clauses) { + return new LeftOuterJoin(table, clauses); + } + + public static LeftOuterJoin leftOuterJoin(Class table, Join join, Clause... clauses) { + return new LeftOuterJoin(table, clauses); + } + public static LeftOuterJoin leftOuterJoin(Class table, String tableAlias, Clause... clauses) { - return new LeftOuterJoin(table, tableAlias, null, 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); + return new LeftOuterJoin(table, tableAlias, join, clauses); } } \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml index af6bc67..c06861d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking common - 1.1.7 + 1.1.8 SQLKing common diff --git a/preprocessor/pom.xml b/preprocessor/pom.xml index b3b3c00..5a95d56 100644 --- a/preprocessor/pom.xml +++ b/preprocessor/pom.xml @@ -6,7 +6,7 @@ com.memtrip.sqlking preprocessor - 1.1.7 + 1.1.8 SQLKing preprocessor @@ -56,7 +56,7 @@ com.memtrip.sqlking common - 1.1.7 + 1.1.8 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 41cf9b8..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 @@ -79,14 +79,13 @@ private String buildCreateTableStatement(Table table, List
tables) 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(" NOT NULL "); sb.append(" ON CONFLICT "); sb.append(column.getNotNull().getOnConflict().toString()); } @@ -100,29 +99,30 @@ else if (column.getForeignKey().getForeignTableName().length() > 0) { ForeignKey foreignKey = column.getForeignKey(); - sb.append(" FOREIGN KEY ") - .append(table.getName().toLowerCase() + "_" + foreignKey.getForeignTableName().toLowerCase() + "_" + column.getName().toLowerCase() + "_fk") + sb.append(" FOREIGN KEY /* column */") .append("(") .append(foreignKey.getLocalColumnNames().get(0).replaceAll("\\[|\\]", "")) .append(") REFERENCES ") .append(column.getForeignKey().getForeignTableName()) - .append(" (") + .append("(") .append(column.getForeignKey().getForeignColumnNames().get(0).replaceAll("\\[|\\]", "")) .append(")"); } - for (Constraint constraint : column.getConstraints()) + if (column.getConstraints().size() > 0) { - if (constraint.getOnConflict() != ConflictAction.NONE) + for (Constraint constraint : column.getConstraints()) { - sb.append(" CONSTRAINT ") - .append(constraint.getConstraintName()) - .append(" ") - .append(constraint.getConstraintExpression()); - - sb.append(" ON CONFLICT ") - .append(constraint.getOnConflict().toString()); + 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(","); } @@ -154,24 +154,24 @@ else if (column.getForeignKey().getForeignTableName().length() > 0) for (ForeignKey foreignKey : table.getForeignKeys()) { - if (tableConstraintCount > 0) - { - sb.append(", "); - } +// if (tableConstraintCount > 0) +// { +// sb.append(", "); +// } tableConstraintCount++; - sb.append(" FOREIGN KEY ") - .append(table.getName().toLowerCase() + "_" + foreignKey.getForeignTableName().toLowerCase() + "_" + fkCount + "_fk") - .append(" (") + sb.append(", FOREIGN KEY /* table */") + .append("(") .append(foreignKey.getLocalColumnNames().toString().replaceAll("\\[|\\]", "")) .append(") REFERENCES ") .append(foreignKey.getForeignTableName()) - .append(" (") + .append("(") .append(foreignKey.getForeignColumnNames().toString().replaceAll("\\[|\\]", "")) .append(")"); fkCount++; } + sb.append(");"); System.out.println("++ " + sb.toString());