]> source.dussan.org Git - iciql.git/commitdiff
update Maven submodule reference
authorJames Moger <james.moger@gmail.com>
Thu, 14 Mar 2013 17:17:22 +0000 (13:17 -0400)
committerJames Moger <james.moger@gmail.com>
Thu, 14 Mar 2013 17:17:22 +0000 (13:17 -0400)
30 files changed:
build.xml
maven
releases.moxie [new file with mode: 0644]
src/site/00_index.mkd [deleted file]
src/site/01_model_classes.mkd [deleted file]
src/site/02_table_versioning.mkd [deleted file]
src/site/02_usage.mkd [deleted file]
src/site/03_performance.mkd [deleted file]
src/site/04_examples.mkd [deleted file]
src/site/04_tools.mkd [deleted file]
src/site/05_building.mkd [deleted file]
src/site/05_javadoc.mkd [deleted file]
src/site/05_releases.mkd [deleted file]
src/site/06_jaqu_comparison.mkd [deleted file]
src/site/building.mkd [new file with mode: 0644]
src/site/custom.less
src/site/examples.mkd [new file with mode: 0644]
src/site/index.mkd [new file with mode: 0644]
src/site/jaqu_comparison.mkd [new file with mode: 0644]
src/site/javadoc.mkd [new file with mode: 0644]
src/site/model_classes.mkd [new file with mode: 0644]
src/site/performance.mkd [new file with mode: 0644]
src/site/table_versioning.mkd [new file with mode: 0644]
src/site/templates/atom.ftl [new file with mode: 0644]
src/site/templates/macros.ftl [new file with mode: 0644]
src/site/templates/releasecurrent.ftl [new file with mode: 0644]
src/site/templates/releasehistory.ftl [new file with mode: 0644]
src/site/templates/rss.ftl [new file with mode: 0644]
src/site/tools.mkd [new file with mode: 0644]
src/site/usage.mkd [new file with mode: 0644]

index d7dbdded3bc4a5310f7a23b32ef3121ef2d42ff1..0832bf101a6e5d81167d730316dbd9cad1274221 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -10,7 +10,7 @@
                Retrieve Moxie Toolkit\r
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
        -->\r
-       <property name="moxie.version" value="0.6.2" />\r
+       <property name="moxie.version" value="0.7.0-SNAPSHOT" />\r
        <property name="moxie.url" value="http://gitblit.github.com/moxie/maven" />\r
        <property name="moxie.jar" value="moxie-toolkit-${moxie.version}.jar" />\r
        <property name="moxie.dir" value="${user.home}/.moxie" />\r
                                        \r
                <!-- Download links -->\r
                <property name="gc.url" value="http://code.google.com/p/iciql/downloads/detail?name=" />\r
-\r
-               <mx:doc googleplusone="true" injectprettify="true" prettifyTheme="hemisu-dark"\r
-                       minify="true" customless="custom.less">\r
+               <property name="releaselog" value="${basedir}/releases.moxie" />\r
+                       \r
+               <mx:doc googleplusone="true" injectprettify="true" prettifyTheme="hemisu-dark" minify="true" \r
+                       templateDir="${project.siteSourceDirectory}/templates"\r
+                       customless="custom.less" rssFeed="rss.xml" atomFeed="atom.xml">\r
 \r
                        <logo file="iciql_white.png" />\r
                        <favicon file="iciql-favicon.png" />\r
                        <structure>\r
        \r
                                <menu name="about" pager="true" pagerPlacement="bottom" pagerLayout="justified">\r
-                                       <page name="overview" src="00_index.mkd" out="index.html" />\r
-                                       <page name="performance" src="03_performance.mkd" out="performance.html" />\r
-                                       <page name="jaqu comparison" src="06_jaqu_comparison.mkd" out="jaqu_comparison.html" />\r
+                                       <page name="overview" src="index.mkd" out="index.html" />\r
+                                       <page name="performance" src="performance.mkd" out="performance.html" />\r
+                                       <page name="jaqu comparison" src="jaqu_comparison.mkd" out="jaqu_comparison.html" />\r
                                </menu>\r
        \r
                                <menu name="getting started" pager="true" pagerPlacement="bottom" pagerLayout="justified">\r
-                                       <page name="models" src="01_model_classes.mkd" out="model_classes.html" headerLinks="true" />\r
-                                       <page name="versioning" src="02_table_versioning.mkd" out="table_versioning.html" headerLinks="true" />\r
-                                       <page name="usage" src="02_usage.mkd" out="usage.html" headerLinks="true" />\r
-                                       <page name="examples" src="04_examples.mkd" out="examples.html" headerLinks="true" />\r
-                                       <page name="tools" src="04_tools.mkd" out="tools.html" headerLinks="true" />\r
+                                       <page name="models" src="model_classes.mkd" out="model_classes.html" headerLinks="true" />\r
+                                       <page name="versioning" src="table_versioning.mkd" out="table_versioning.html" headerLinks="true" />\r
+                                       <page name="usage" src="usage.mkd" out="usage.html" headerLinks="true" />\r
+                                       <page name="examples" src="examples.mkd" out="examples.html" headerLinks="true" />\r
+                                       <page name="tools" src="tools.mkd" out="tools.html" headerLinks="true" />\r
                                </menu>\r
        \r
-                               <page name="building" src="05_building.mkd" out="building.html" />\r
-                               <page name="javadoc" src="05_javadoc.mkd" out="javadoc.html" />\r
-                               <page name="releases" src="05_releases.mkd" out="releases.html" />\r
+                               <page name="building" src="building.mkd" out="building.html" />\r
+                               <page name="javadoc" src="javadoc.mkd" out="javadoc.html" />\r
 \r
-                               <!--<page name="release notes" out="releasenotes.html">\r
-                                       <template src="releasecurrent.ftl" data="${basedir}/releases.moxie" />\r
+                               <page name="release notes" out="releasenotes.html">\r
+                                       <template src="releasecurrent.ftl" data="${releaselog}" />\r
                                </page>\r
                                <page out="releases.html" navbarlink="false">\r
-                                       <template src="releasehistory.ftl" data="${basedir}/releases.moxie" />\r
-                               </page>-->\r
+                                       <template src="releasehistory.ftl" data="${releaselog}" />\r
+                               </page>\r
                                        \r
                                <menu name="downloads">\r
                                        <link name="${project.artifactId}-${project.releaseVersion}"\r
                        </structure>\r
                                                \r
                        <!-- Generate RSS and Atom feeds from the release history -->\r
-                       <!--<page as="atom.xml">\r
-                               <template src="atom.ftl" data="${basedir}/releases.moxie" />\r
+                       <page as="atom.xml">\r
+                               <template src="atom.ftl" data="${releaselog}" />\r
                        </page>\r
                        <page as="rss.xml">\r
-                               <template src="rss.ftl" data="${basedir}/releases.moxie" />\r
-                       </page>-->\r
+                               <template src="rss.ftl" data="${releaselog}" />\r
+                       </page>\r
                                                \r
                </mx:doc>\r
                                                \r
diff --git a/maven b/maven
index fad8023ebba18365237912c58bca86eb691f2369..1f40ae4f2766e4a32dc1e11e7f610bd75da0e986 160000 (submodule)
--- a/maven
+++ b/maven
@@ -1 +1 @@
-Subproject commit fad8023ebba18365237912c58bca86eb691f2369
+Subproject commit 1f40ae4f2766e4a32dc1e11e7f610bd75da0e986
diff --git a/releases.moxie b/releases.moxie
new file mode 100644 (file)
index 0000000..abe9b95
--- /dev/null
@@ -0,0 +1,414 @@
+#
+# ${project.version} release
+#
+r20: {
+    title: ${project.name} ${project.version} released
+    id: ${project.version}
+    date: ${project.buildDate}
+
+       html: '''
+<span class="alert alert-success">
+Iciql artifacts may now be retrieved by your favorite Maven 2-compatible build tool from <a href="http://gitblit.github.com/iciql/maven">here</a>.
+</span>
+       '''
+       
+    fixes:
+     - Fixed case-sensitivity bug on setting a compound primary key from an annotation (issue 12)
+     - Fixed order of DEFAULT value in create table statement (issue 11)
+     - Fixed password bug in model generator (issue 7)
+
+    changes:
+     - ''
+       Support inheriting columns from super.super class, if super.super is annotated.
+       This allows for an inheritance hierarchy like:
+       @IQTable class MyTable -> @IQView abstract class MyBaseView -> @IQView class MyConstrainedView
+       ''
+
+    additions:
+     - ''
+       Implemented readonly view support. (issue 8)
+       View models may be specified using the IQView annotation or Iciql.define().  Views can either be created automatically as part of a query of the view OR views may be constructed from a fluent statement.
+       ''
+     - Support inheritance of IQVersion for DbUpgrader implementations (issue 10)
+}
+
+#
+# 1.1.0 release
+#
+r19: {
+    title: Iciql 1.1.0 released
+    id: 1.1.0
+    date: 2012-08-20
+
+    changes:
+     - All bulk operations (insert all, update all, delete all) now use JDBC savepoints to ensure atomicity of the transaction
+}
+
+#
+# 1.0.0 release
+#
+r18: {
+    title: Iciql 1.0.0 released
+    id: 1.0.0
+    date: 2012-07-14
+
+    fixes:
+     - Fixed bug in using 0L primitive values in where clauses.  These were confused with the COUNT(*) function. (Github/kc5nra,issue 5)
+
+    changes:
+     - Issue CREATE TABLE and CREATE INDEX statements once per-db instance/table-mapping
+
+    additions:
+     - ''
+       Added support for single column subquery
+       select name, address from user_table where user_id in (select user_id from invoice table where paid = false)
+       ''
+     - Added support for left outer join (Github/backpaper0)
+}
+
+#
+# 0.7.10 release
+#
+r17: {
+    title: Iciql 0.7.10 released
+    id: 0.7.10
+    date: 2012-01-27
+
+    fixes:
+     - Fixed default String value bug where a default empty string threw an IndexOutOfBounds exception
+}
+
+#
+# 0.7.9 release
+#
+r16: {
+    title: Iciql 0.7.9 released
+    id: 0.7.9
+    date: 2012-01-24
+
+    additions:
+     - ''
+       Added toParameter() option for SET commands and allow generating parameterized UPDATE statements
+
+       String q = db.from(t).set(t.timestamp).toParameter().where(t.id).is(5).toSQL();
+       db.executeUpdate(q, new Date());
+       ''
+}
+
+#
+# 0.7.8 release
+#
+r15: {
+    title: Iciql 0.7.8 released
+    id: 0.7.8
+    date: 2012-01-11
+    fixes:
+     - Replaced non-threadsafe counter used for assigning AS identifiers in JOIN statements with an AtomicInteger
+     - Prevent negative rollover of the AS counter
+     - Fixed bug in Query.select(Z z) which assumed that Z must always be an anonymous inner class which may not always be true.  This allows for specifying an existing alias to force table or identifier usage in the generated select list.  This is very useful for DISTINCT JOIN statements where only the columns of the primary table are of interest.
+
+    additions:
+     - Added optional alias parameter to Query.toSQL and QueryWhere.toSQL to force generated statement to prefix an AS identifier or, alternatively, the tablename.  
+     - Query.toSQL(boolean distinct, K alias)
+     - QueryWhere.toSQL(boolean distinct, K alias)
+}
+
+#
+# 0.7.7 release
+#
+r14: {
+    title: Iciql 0.7.7 released
+    id: 0.7.7
+    date: 2012-01-05
+    changes:
+     - ''
+       Disallow declaring and explicitly referencing multiple instances of an enum type within a single model.
+
+       A runtime exception will be thrown if an attempt to use where/set/on/and/or/groupBy/orderBy(enum) and your model has multiple fields of a single enum type.
+       ''
+
+    additions:
+     - added Query.toSQL() and QueryWhere.toSQL() methods which, when combined with the following new methods, allows for generation of a parameterized, static sql string to be reused with a dynamic query or a PreparedStatement.
+     - QueryCondition.isParameter()
+     - QueryCondition.atLeastParameter()
+     - QueryCondition.atMostParameter()
+     - QueryCondition.exceedsParameter()
+     - QueryCondition.lessThanParameter()
+     - QueryCondition.likeParameter()
+     - QueryCondition.isNotParameter()
+}
+
+#
+# 0.7.6 release
+#
+r13: {
+    title: Iciql 0.7.6 released
+    id: 0.7.6
+    date: 2011-12-21
+    changes:
+     - Iciql now tries to instantiate a default value from an annotated default value IFF the field object is null, it is specified nullable = false, and a defaultValue exists.  This only applies to db.insert or db.update.
+}
+
+#
+# 0.7.5 release
+#
+r12: {
+    title: Iciql 0.7.5 released
+    id: 0.7.5
+    date: 2011-12-12
+    fixes:
+     - Iciql now identifies wildcard queries and builds a dynamic column lookup.  Otherwise, the original field-position-based approach is used.  This corrects the performance regression released in 0.7.4 while still fixing the wildcard statement column mapping problem.
+}
+
+#
+# 0.7.4 release
+#
+r11: {
+    title: Iciql 0.7.4 released
+    id: 0.7.4
+    date: 2011-12-06
+
+    fixes:
+     - Fixed JOIN ON primitives
+     - Fixed GROUP BY primitives
+     - Fixed primitive references when selecting into a custom type with primitives
+     - ''
+       Fixed inherited JaQu bug related to model classes and wildcard queries (select *).
+
+       Iciql maps resultset columns by the index of the model class field from a list.  This assumes that all columns in the resultset have a corresponding model field definition.  This works fine for most queries because iciql explicitly selects columns from the table (select alpha, beta...) when you execute select().
+       The problem is when iciql issues a dynamic wildcard query and your model does not represent all columns in the resultset: columns and fields may fail to correctly line-up.
+
+       Iciql now maps all fields by their column name, not by their position.
+       ''
+
+    changes:
+     - Disallow declaring and explicitly referencing multiple primitive booleans in a single model.  A runtime exception will be thrown if an attempt to use where/set/on/and/or/groupBy/orderBy(boolean) and your model has multiple mapped primitive boolean fields.
+
+    additions:
+     - Added list alternatives to the varargs methods because it was too easy to forget list.toArray()
+     - Db.executeQuery(Class<? extends T> modelClass, String sql, List<?> args)
+     - Db.executeQuery(String sql, List<?> args)
+     - Query.where(String fragment, List<?> args)
+}
+
+#
+# 0.7.3 release
+#
+r10: {
+    title: Iciql 0.7.3 released
+    id: 0.7.3
+    date: 2011-12-06
+    fixes:
+     - Fixed JOIN ON primitives
+     - Fixed GROUP BY primitives
+     - Fixed primitive references when selecting into a custom type with primitives
+    changes:
+     - Improved fluent/type-safety of joins
+}
+
+#
+# 0.7.2 release
+#
+r9: {
+    title: Iciql 0.7.2 released
+    id: 0.7.2
+    date: 2011-11-30
+    changes:
+     - generated models are now serializable with a default serial version id of 1
+    dependencyChanges:
+    - H2 1.3.162
+    - HSQLDB 2.2.6 (100% of unit tests pass)
+}
+
+#
+# 0.7.1 release
+#
+r8: {
+    title: Iciql 0.7.1 released
+    id: 0.7.1
+    date: 2011-08-31
+    fixes:
+     - Fix to PostgreSQL dialect when creating autoincrement columns
+     - Fix to default dialect when creating autoincrement columns
+    changes:
+     - Undeprecated interface configuration
+     - Interface configuration now maps ALL fields, not just public fields
+     - Overhauled test suite and included more database configurations
+     - Documented POJO configuration option (limited subset of interface configuration)
+    additions:
+    - Added @IQIgnore annotation to explicitly skip fields for interface configuration
+    - Created additional Define static methods to bring interface configuration to near-parity with annotation configuration
+    - Added Db.open(url) method
+}
+
+#
+# 0.7.0 release
+#
+r7: {
+    title: Iciql 0.7.0 released
+    id: 0.7.0
+    date: 2011-08-17
+    changes:
+     - Finished MySQL dialect implementation.  MySQL 5.0.51b passes 100% of tests.
+     - Renamed StatementLogger to IciqlLogger
+     - Overhauled test suite and included more database configurations
+    additions:
+    - Added PostgreSQL dialect.  PostgreSQL 9.0 passes all but the boolean-as-int tests.
+    - Added Db.dropTable(T) method
+    - Added IciqlLogger.warn method
+    - Added IciqlLogger.drop method
+}
+
+#
+# 0.6.6 release
+#
+r6: {
+    title: Iciql 0.6.6 released
+    id: 0.6.6
+    date: 2011-08-15
+    changes:
+     - Disabled two concurrency unit tests since I believe they are flawed and do not yield reproducible results
+    additions:
+    - Implemented HSQLDB MERGE syntax.  HSQL 2.2.4 fails 1 test which is bug-3390047 in HSQLDB.
+    - Added Derby database dialect.  Derby 10.7.1.1 and 10.8.1.2 pass 100% of tests.
+
+    dependencyChanges:
+    - H2 1.3.159
+}
+
+#
+# 0.6.5 release
+#
+r5: {
+    title: Iciql 0.6.5 released
+    id: 0.6.5
+    date: 2011-08-12
+    fixes:
+     - fixed failure of db.delete(PrimitiveModel) and db.update(PrimitiveModel)
+}
+
+#
+# 0.6.4 release
+#
+r4: {
+    title: Iciql 0.6.4 released
+    id: 0.6.4
+    date: 2011-08-12
+    fixes:
+     - do not INSERT primitive autoIncrement fields, let database assign value
+    changes:
+     - @IQTable.createIfRequired -> @IQTable.create
+     - unspecified length String fields are now CLOB instead of TEXT.  dialects can intercept this and convert to another type. e.g. MySQL dialect can change CLOB to TEXT.
+    - java.lang.Boolean now maps to BOOLEAN instead of BIT
+    - expressions on unmapped fields will throw an IciqlException
+    - expressions on unsupported types will throw an IciqlException
+    - moved dialects back to main package
+    - moved create table and create index statement generation into dialects
+    - renamed _iq_versions table to iq_versions since leading _ character is troublesome for some databases
+    - @IQColumn(allowNull=true) -> @IQColumn(nullable=true)
+    - All Object columns are assumed NULLABLE unless explicitly set @IQColumn(nullable = false)
+    - All Primitive columns are assumed NOT NULLABLE unless explicitly set @IQColumn(nullable = true)
+    - changed @IQTable.primaryKey definition to use array of column names (@IQTable( primaryKey = {"name", "nickname"}) )
+
+    additions:
+     - full support for primitives in all clauses
+     - DECIMAL(length, scale) support
+     - improved exception reporting by including generated statement, if available 
+     - improved automatic dialect determination on pooled connections
+     - added HSQL dialect.  HSQL fails 4 out of 50 unit tests. (2 failures are unimplemented merge, 1 is a bug-3390047 in HSQLDB, 1 is a concurreny issue)
+     - added untested MySQL dialect
+     - allow defining table create DEFAULT values from default object values (Date myDate = new Date(100, 1, 1); => CREATE TABLE ... myDate DATETIME DEFAULT '2000-02-01 00:00:00')
+}
+
+#
+# 0.6.3 release
+#
+r3: {
+    title: Iciql 0.6.3 Released
+    id: 0.6.3
+    date: 2011-08-08
+
+    changes:
+     - Moved dialects into separate package
+     - finished enum support (issue 4)
+
+    additions:
+     - added UUID type support (H2 databases only)
+     - added partial primitives support (primitives may not be used for compile-time condition clauses)
+     - added between(A y).and(A z) condition syntax
+}
+
+#
+# 0.6.2 release
+#
+r2: {
+    title: Iciql 0.6.2 Released
+    id: 0.6.2
+    date: 2011-08-05
+
+    fixes:
+     - fix to versioning to support H2 1.3.158+
+    changes:
+     - @IQSchema(name="public") => @IQSchema("public")
+     - @IQDatabase(version=2) => @IQVersion(2)
+     - @IQTable(version=2) => @IQVersion(2)
+     - @IQIndex annotation simplified to be used for one index definition and expanded to specify index name
+     - @IQColumn(maxLength=20) => @IQColumn(length=20)
+     - @IQColumn(trimString=true) => @IQColumn(trim=true)}
+
+    additions:
+     - added BLOB support (issue 1)
+     - added java.lang.Enum support (issue 2)
+     - allow runtime flexible mapping of BOOL columns to Integer fields
+     - allow runtime flexible mapping of INT columns to Boolean fields
+     - added @IQIndexes annotation to specify multiple IQIndex annotations
+}
+
+#
+# 0.5.0 release
+#
+r1: {
+    title: Iciql 0.5.0 Released
+    id: 0.5.0
+    date: 2011-08-03
+    note: ~
+    text: Initial release of blessed JaQu fork
+    changes:
+     - deprecated model class interface configuration
+     - added Db.open(Connection conn) method, changed constructor to default scope
+     - added Db.registerDialect static methods to register custom dialects
+     - added Query.where(String fragment, Object... args) method to build a runtime query fragment when compile-time queries are too strict
+     - added Db.executeQuery(String query, Object... args) to execute a complete sql query with optional arguments
+     - added Db.executeQuery(Class modelClass, String query, Object... args) to execute a complete sql query, with optional arguments, and build objects from the result
+     - added Db.buildObjects(Class modelClass, ResultSet rs) method to build objects from the ResultSet of a plain sql query
+     - added ThreadLocal<T> com.iciql.Utils.newThreadLocal(final Class<? extends T> clazz) method
+     - added optional console statement logger and SLF4J statement logger
+     - refactored dialect support
+     - throw IciqlException (which is a RuntimeException) instead of RuntimeException
+     - synchronized Db.classMap for concurrent sharing of a Db instance
+     - Database/table versioning uses the _iq_versions table, the _ jq_versions table, if present, is ignored
+     - ''
+       Changed the following class names:
+       org.h2.jaqu.Table => com.iciql.Iciql
+       org.h2.jaqu.JQSchema => com.iciql.IQSchema
+       org.h2.jaqu.JQDatabase => com.iciql.IQDatabase
+       org.h2.jaqu.JQIndex => com.iciql.IQIndex
+       org.h2.jaqu.JQTable => com.iciql.IQTable
+       org.h2.jaqu.JQColumn => com.iciql.IQColumn
+       ''
+     - ''
+       Changed the following method names:
+       org.h2.jaqu.Table.define() => com.iciql.Iciql.defineIQ()
+       QueryConditon.bigger => QueryCondition.exceeds
+       QueryConditon.biggerEqual => QueryCondition.atLeast
+       QueryConditon.smaller => QueryCondition.lessThan
+       QueryConditon.smallEqual => QueryCondition.atMost
+       ''
+}
+
+#
+# Release log data
+#
+release: &r19
+snapshot: &r20
+releases: &r[1..19]
diff --git a/src/site/00_index.mkd b/src/site/00_index.mkd
deleted file mode 100644 (file)
index 1c2bbd3..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-## Overview\r
-\r
-iciql **is**...\r
-\r
-- a model-based, database access wrapper for JDBC\r
-- for modest database schemas and basic statement generation\r
-- for those who want to write code, instead of SQL, using IDE completion and compile-time type-safety\r
-- small (200KB) with debug symbols and no runtime dependencies\r
-- pronounced *icicle* (although it could be French: *ici ql* - here query language)\r
-- a friendly fork of the H2 [JaQu][jaqu] project\r
-\r
-iciql **is not**...\r
-\r
-- a complete alternative to JDBC\r
-- designed to compete with more powerful database query tools like [jOOQ][jooq] or [Querydsl][querydsl]\r
-- designed to compete with enterprise [ORM][orm] tools like [Hibernate][hibernate] or [mybatis][mybatis]\r
-\r
-### Example Usage\r
-<table class="table">\r
-<tr>\r
-<th>iciql</th><th>sql</th>\r
-</tr>\r
-<tr>\r
-<td>\r
-%BEGINCODE%\r
-Product p = new Product();\r
-List<Product> restock = db.from(p).where(p.unitsInStock).is(0).select();\r
-List<Product> all = db.executeQuery(Product.class, "select * from products");\r
-%ENDCODE%\r
-\r
-</td><td>\r
-<br/>\r
-select * from products p where p.unitsInStock = 0<br/>\r
-select * from products\r
-</td>\r
-</tr>\r
-</table>\r
-\r
-### Supported Databases (Unit-Tested)\r
-- [H2](http://h2database.com) ${h2.version}\r
-- [HSQLDB](http://hsqldb.org) ${hsqldb.version}\r
-- [Derby](http://db.apache.org/derby) ${derby.version}\r
-- [MySQL](http://mysql.com) ${mysql.version}\r
-- [PostgreSQL](http://postgresql.org) ${postgresql.version}\r
-\r
-Support for others is possible and may only require creating a simple "dialect" class.\r
-\r
-### Java Runtime Requirement\r
-\r
-iciql requires a Java 6 Runtime Environment (JRE) or a Java 6 Development Kit (JDK).\r
\r
-### License\r
-iciql is distributed under the terms of the [Apache Software Foundation license, version 2.0][apachelicense]\r
-\r
-[jaqu]: http://h2database.com/html/jaqu.html "H2 JaQu project"\r
-[orm]: http://en.wikipedia.org/wiki/Object-relational_mapping "Object Relational Mapping"\r
-[jooq]: http://jooq.sourceforge.net "jOOQ"\r
-[querydsl]: http://source.mysema.com/display/querydsl/Querydsl "Querydsl"\r
-[hibernate]: http://www.hibernate.org "Hibernate"\r
-[mybatis]: http://www.mybatis.org "mybatis"\r
-[github]: http://github.com/gitblit/iciql "iciql git repository"\r
-[googlecode]: http://code.google.com/p/iciql "iciql project management"\r
-[apachelicense]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0"
\ No newline at end of file
diff --git a/src/site/01_model_classes.mkd b/src/site/01_model_classes.mkd
deleted file mode 100644 (file)
index 8fedf18..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-## Model Classes\r
-A model class represents a single table within your database.  Fields within your model class represent columns in the table.  The object types of your fields are reflectively mapped to SQL types by iciql at runtime.\r
-\r
-Models can be manually written using one of three approaches: *annotation configuration*, *interface configuration*, or *POJO configuration*.  All approaches can be used within a project and all can be used within a single model class, although that is discouraged.\r
-\r
-Alternatively, model classes can be automatically generated by iciql using the model generation tool.  Please see the [tools](tools.html) page for details.\r
-\r
-### Configuration Requirements and Limitations\r
-\r
-1. Your model class **must** provide a public default constructor.\r
-2. All **Object** fields are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)* or *Define.nullable(field, false)*.\r
-3. All **Primitive** fields are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)* or *Define.nullable(field, true)*.\r
-4. Only the specified types are supported.  Any other types are not supported.\r
-5. Triggers, views, and other advanced database features are not supported.\r
-\r
-### Supported Data Types\r
-\r
----NOMARKDOWN---\r
-<table class="table">\r
-<tr><td colspan="3"><b>Fully Supported Types</b><br/>\r
-can be used for all iciql expressions\r
-</tr>\r
-<tr><th>Object</th><th>Primitive</th><th>SQL Type</th></tr>\r
-<tr><td>java.lang.String</td><td></td>\r
-<td>VARCHAR <em>(length > 0)</em> or CLOB <em>(length == 0)</em></td></tr>\r
-       \r
-<tr><td>java.lang.Boolean</td><td>boolean</td>\r
-<td>BOOLEAN<br/><i>can only <b>declare and explicitly reference</b> one <u>primitive boolean</u> per model<br/>multiple primitives are allowed if not using where/set/on/and/or/groupBy/orderBy(boolean)</i></td></tr>\r
-       \r
-<tr><td>java.lang.Byte</td><td>byte</td>\r
-<td>TINYINT</td></tr>\r
-       \r
-<tr><td>java.lang.Short</td><td>short</td>\r
-<td>SMALLINT</td></tr>\r
-       \r
-<tr><td>java.lang.Integer</td><td>int</td>\r
-<td>INT</td></tr>\r
-       \r
-<tr><td>java.lang.Long</td><td>long</td>\r
-<td>BIGINT</td></tr>\r
-       \r
-<tr><td>java.lang.Float</td><td>float</td>\r
-<td>REAL</td></tr>\r
-       \r
-<tr><td>java.lang.Double</td><td>double</td>\r
-<td>DOUBLE</td></tr>\r
-       \r
-<tr><td>java.math.BigDecimal</td><td> </td>\r
-<td>DECIMAL <em>(length == 0)</em> or DECIMAL(length,scale) <em>(length > 0)</em></td></tr>\r
-       \r
-<tr><td>java.sql.Date</td><td> </td>\r
-<td>DATE</td></tr>\r
-       \r
-<tr><td>java.sql.Time</td><td> </td>\r
-<td>TIME</td></tr>\r
-       \r
-<tr><td>java.sql.Timestamp</td><td> </td>\r
-<td>TIMESTAMP</td></tr>\r
-\r
-<tr><td>java.util.Date</td><td> </td>\r
-<td>TIMESTAMP</td></tr>\r
-\r
-<tr><td>java.lang.Enum.name()<br/><em>default type</em></td><td></td>\r
-<td>VARCHAR <em>(length > 0)</em> or CLOB <em>(length == 0)</em><br/><em>EnumType.NAME</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
-\r
-<tr><td>java.lang.Enum.ordinal()</td><td> </td>\r
-<td>INT<br/><em>EnumType.ORDINAL</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
-\r
-<tr><td>java.lang.Enum implements<br/><em>com.iciql.Iciql.EnumId.enumId()</em></td><td> </td>\r
-<td>INT<br/><em>EnumType.ENUMID</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
-\r
-<tr><td colspan="3"><b>Partially Supported Types</b><br/>\r
-can not be directly referenced in an expression</td></tr>\r
-<tr><td>byte []</td> <td></td>\r
-<td>BLOB</td><tr/>\r
-\r
-<tr><td colspan="3"><b>H2 Database Types</b><br/>\r
-fully supported when paired with an H2 database \r
-</td></tr>\r
-<tr><td>java.util.UUID</td><td> </td>\r
-<td>UUID</td></tr>\r
-\r
-</table>\r
----NOMARKDOWN---\r
-**NOTE:**<br/>\r
-The reverse lookup used for model generation, SQL type -> Java type, contains more mappings.<br/>\r
-Please consult the `com.iciql.ModelUtils` class for details. \r
-\r
-## Annotation Configuration\r
-The recommended approach to setup a model class is to annotate the class and field declarations.\r
-\r
-### advantages\r
-\r
-- annotated models support annotated field inheritance making it possible to design a single base class that defines the fields and then create table subclasses that specify the table mappings.\r
-- model runtime dependency is limited to the small, portable `com.iciql.Iciql` class file which contains the annotation definitions\r
-\r
-### disadvantages\r
-\r
-- more verbose model classes\r
-- indexes are defined using "fragile" string column names\r
-- compound primary keys are defined using "fragile" string column names\r
-\r
-### field mapping\r
-\r
-- By default, **ONLY** fields annotated with *@IQColumn* are mapped.\r
-- scope is irrelevant.\r
-- transient is irrelevant.\r
-\r
-### default values\r
-\r
-You may specify default values for an *@IQColumn* by either:\r
-\r
-1. specifying the default value string within your annotation<br/>\r
-**NOTE:**<br/>\r
-The annotated default value always takes priority over a field default value.\r
-%BEGINCODE%\r
-// notice the single ticks!\r
-@IQColumn(defaultValue="'2000-01-01 00:00:00'")\r
-Date myDate;\r
-%ENDCODE%\r
-\r
-2. setting a default value on the field<br/>\r
-**NOTE:**<br/>\r
-Primitive types have an implicit default value of *0* or *false*.\r
-%BEGINCODE%\r
-@IQColumn\r
-Date myDate = new Date(100, 0, 1);\r
-\r
-@IQColumn\r
-int myId;\r
-%ENDCODE%\r
-\r
-If you want to specify a database-specific variable or function as your default value (e.g. CURRENT_TIMESTAMP) you must do that within the annotation.  Also note that the *IQColumn.defaultValue* must be a well-formatted SQL DEFAULT expression whereas object defaults will be automatically converted to an SQL DEFAULT expression.\r
-\r
-### Special Case: primitive autoincrement fields and 0\r
-%BEGINCODE%\r
-@IQColumn(autoIncrement = true)\r
-int myId;\r
-%ENDCODE%\r
-\r
-Because primitive types have implicit default values, this field will be excluded from an INSERT statement if its value is 0.  Iciql can not differentiate an implicit/uninitialized 0 from a explicitly assigned 0.\r
-\r
-### Example Annotated Model\r
-%BEGINCODE%\r
-import com.iciql.Iciql.EnumType;\r
-import com.iciql.Iciql.IQColumn;\r
-import com.iciql.Iciql.IQEnum;\r
-import com.iciql.Iciql.IQIndex;\r
-import com.iciql.Iciql.IQTable;\r
-\r
-@IQTable\r
-@IQIndexes({\r
-  @IQIndex({"productName", "category"}),\r
-  @IQIndex(name="nameindex", value="productName")\r
-})\r
-public class Product {\r
-\r
-       @IQEnum(EnumType.ORDINAL)\r
-       public enum Availability {\r
-               ACTIVE, DISCONTINUED;\r
-       }\r
-\r
-       @IQColumn(primaryKey = true)\r
-       public Integer productId;\r
-      \r
-       @IQColumn(length = 200, trim = true)\r
-       public String productName;\r
-      \r
-       @IQColumn(length = 50, trim = true)\r
-       public String category;\r
-      \r
-       @IQColumn\r
-       public Double unitPrice;\r
-      \r
-       @IQColumn(name = "units")\r
-       public Integer unitsInStock;\r
-      \r
-       @IQColumn\r
-       private Integer reorderQuantity;\r
-       \r
-       @IQColumn\r
-       private Availability availability;\r
-       \r
-       // ignored because it is not annotated AND the class is @IQTable annotated\r
-       private Integer ignoredField;\r
-      \r
-       public Product() {\r
-               // default constructor\r
-       }\r
-}\r
-%ENDCODE%\r
-\r
-## Interface Configuration\r
-Alternatively, you may map your model classes using the interface approach by implementing the `com.iciql.Iciql` interface.\r
-\r
-This is a less verbose configuration style, but it comes at the expense of introducing a compile-time dependency on the logic of the iciql library.  This might be a deterrent, for example, if you were serializing your model classes to another process that may not have the iciql library.\r
-\r
-The `com.iciql.Iciql` interface specifies a single method, *defineIQ()*.  In your implementation of *defineIQ()* you would use static method calls to set:\r
-\r
-- the schema name\r
-- the table name (if it's not the class name)\r
-- the column name (if it's not the field name)\r
-- the max length and trim of a string field\r
-- the precision and scale of a decimal field\r
-- the autoincrement flag of a long or integer field\r
-- the nullable flag of a field \r
-- the primaryKey (single field or compound)\r
-- any indexes (single field or compound)\r
-\r
-### advantages\r
-\r
-- less verbose model class\r
-- compile-time index definitions\r
-- compile-time compound primary key definitions\r
-\r
-### disadvantages\r
-\r
-- model runtime dependency on entire iciql library\r
-- *defineIQ()* is called from a static synchronized block which may be a bottleneck for highly concurrent systems\r
-\r
-### field mapping\r
-\r
-- **ALL** fields are mapped unless annotated with *@IQIgnore*.\r
-- scope is irrelevant.\r
-- transient is irrelevant.\r
-\r
-### default values\r
-\r
-You may specify default values for an field by either:\r
-\r
-1. specifying the default value string within your *defineIQ()* method<br/>\r
-**NOTE:**<br/>\r
-The defineIQ() value always takes priority over a field default value.\r
-%BEGINCODE%\r
-Date myDate;\r
-\r
-public void defineIQ() {\r
-    // notice the single ticks!\r
-    Define.defaultValue(myDate, "'2000-01-01 00:00:00'");\r
-}\r
-%ENDCODE%\r
-\r
-2. setting a default value on the field<br/>\r
-**NOTE:**<br/>\r
-Primitive types have an implicit default value of *0* or *false*.\r
-%BEGINCODE%\r
-Date myDate = new Date(100, 0, 1);\r
-\r
-int myId;\r
-%ENDCODE%\r
-\r
-### Example Interface Model\r
-%BEGINCODE%\r
-import com.iciql.Iciql;\r
-import com.iciql.Iciql.IQIgnore;\r
-\r
-public class Product implements Iciql {\r
-       public Integer productId;\r
-       public String productName;\r
-       public String category;\r
-       public Double unitPrice;\r
-       public Integer unitsInStock;\r
-       \r
-       @IQIgnore\r
-       Integer reorderQuantity;\r
-      \r
-       public Product() {\r
-       }\r
-      \r
-       @Override\r
-       public void defineIQ() {\r
-               com.iciql.Define.primaryKey(productId);\r
-               com.iciql.Define.columnName(unitsInStock, "units");\r
-               com.iciql.Define.length(productName, 200);\r
-               com.iciql.Define.length(category, 50);\r
-               com.iciql.Define.index(productName, category);\r
-       }\r
-}\r
-%ENDCODE%\r
-\r
-\r
-## POJO (Plain Old Java Object) Configuration\r
-\r
-This approach is very similar to the *interface configuration* approach; it is the least verbose and also the least useful.\r
-\r
-This approach would be suitable for quickly modeling an existing table where only SELECT and INSERT statements will be generated.\r
-\r
-### advantages\r
-\r
-- nearly zero-configuration\r
-\r
-### disadvantages\r
-\r
-- can not execute DELETE, UPDATE, or MERGE statements (they require a primary key specification)\r
-- table name MUST MATCH model class name\r
-- column names MUST MATCH model field names\r
-- can not specify any column attributes\r
-- can not specify indexes\r
-\r
-### field mapping\r
-\r
-- **ALL** fields are mapped unless annotated with *@IQIgnore*.\r
-- scope is irrelevant.\r
-- transient is irrelevant.\r
-\r
-### default values\r
-\r
-You may specify a default value on the field.\r
-\r
-**NOTE:**<br/>\r
-Primitive types have an implicit default value of *0* or *false*.\r
-%BEGINCODE%\r
-Date myDate = new Date(100, 0, 1);\r
-\r
-int myId;\r
-%ENDCODE%\r
-\r
-### Example POJO Model\r
-%BEGINCODE%\r
-import com.iciql.Iciql.IQIgnore;\r
-\r
-public class Product {\r
-       public Integer productId;\r
-       public String productName;\r
-       public String category;\r
-       public Double unitPrice;\r
-       public Integer units;\r
-       \r
-       @IQIgnore\r
-       Integer reorderQuantity;\r
-      \r
-       public Product() {\r
-       }   \r
-}\r
-%ENDCODE%
\ No newline at end of file
diff --git a/src/site/02_table_versioning.mkd b/src/site/02_table_versioning.mkd
deleted file mode 100644 (file)
index 2e95aaa..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-## Database & Table Versioning\r
-\r
-Iciql supports an optional, simple versioning mechanism.  There are two parts to the mechanism.\r
-\r
-1. You must supply an implementation of `com.iciql.DbUpgrader` to your `com.iciql.Db` instance.\r
-2. One or more of your table model classes must specify the `IQVersion(version)` annotation<br/>\r
-AND/OR<br/>\r
-Your `com.iciql.DbUpgrader` implementation must specify the `IQVersion(version)` annotation\r
-\r
-### How does it work?\r
-If you choose to use versioning, iciql will maintain a table within your database named *iq_versions* which is defined as:\r
-\r
-    CREATE TABLE IQ_VERSIONS(SCHEMANAME VARCHAR(255) NOT NULL, TABLENAME VARCHAR(255) NOT NULL, VERSION INT NOT NULL)\r
-    \r
-This database table is automatically created if and only if at least one of your model classes specifies a *version* > 0.\r
-\r
-When you generate a statement, iciql will compare the annotated version field of your model class to its last known value in the *iq_versions* table.  If *iq_versions* lags behind the model annotation, iciql will immediately call the registered `com.iciql.DbUpgrader` implementation before generating and executing the current statement.\r
-\r
-When an upgrade scenario is identified, the current version and the annotated version information is passed to either:\r
-\r
-- `DbUpgrader.upgradeDatabase(db, fromVersion, toVersion)`\r
-- `DbUpgrader.upgradeTable(db, schema, table, fromVersion, toVersion)`\r
-\r
-both of which allow for non-linear upgrades.  If the upgrade method call is successful and returns *true*, iciql will update the *iq_versions* table with the annotated version number.\r
-\r
-The actual upgrade procedure is beyond the scope of iciql and is your responsibility to implement.  This is simply a mechanism to automatically identify when an upgrade is necessary.\r
-\r
-**NOTE:**<br/>\r
-The database entry of the *iq_versions* table is specified as SCHEMANAME='' and TABLENAME=''.
\ No newline at end of file
diff --git a/src/site/02_usage.mkd b/src/site/02_usage.mkd
deleted file mode 100644 (file)
index 7b9d89d..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-## Usage\r
-\r
-Aside from this brief usage guide, please consult the [examples](examples.html), the [javadoc](javadoc.html) and the [source code](${project.scmUrl}).\r
-\r
-### Instantiating a Db\r
-\r
-Use one of the static utility methods to instantiate a Db instance:\r
-\r
-    Db.open(String url, String user, String password);\r
-    Db.open(String url, String user, char[] password);\r
-    Db.open(Connection conn);\r
-    Db.open(DataSource dataSource);\r
\r
-### Compile-Time Statements\r
-\r
-You compose your statements using the builder pattern where each method call returns an object that is used to specify the next part of the statement.  Through clever usage of generics, pioneered by the original JaQu project, compile-time safety flows through the statement.\r
-\r
-%BEGINCODE%\r
-Db db = Db.open("jdbc:h2:mem:", "sa", "sa");\r
-db.insertAll(Product.getList());\r
-db.insertAll(Customer.getList());\r
-\r
-List<Product> restock =\r
-       db.from(p).\r
-       where(p.unitsInStock).\r
-       is(0).orderBy(p.productId).select();\r
-               \r
-for (Product product : restock) {\r
-       db.from(p).\r
-       set(p.unitsInStock).to(25).\r
-       where(p.productId).is(product.productId).update();\r
-}\r
-db.close();\r
-%ENDCODE%\r
\r
-Please see the [examples](examples.html) page for more code samples. \r
\r
-### Dynamic Runtime Queries\r
-\r
-Iciql gives you compile-time type-safety, but it becomes inconvenient if your design requires more dynamic statement generation.  For these scenarios iciql offers some runtime query support through a hybrid approach or a pure JDBC approach.\r
-\r
-#### Where String Fragment Approach\r
-This approach is a mixture of iciql and jdbc.  It uses the traditional prepared statement *field=?* tokens with iciql compile-time model class type checking.  There is no field token type-safety checking.\r
-%BEGINCODE%\r
-List<Product> restock = db.from(p).where("unitsInStock=? and productName like ? order by productId", 0, "Chef%").select();\r
-%ENDCODE%\r
-\r
-#### Db.executeQuery Approaches\r
-There may be times when the hybrid approach is still too restrictive and you'd prefer to write straight SQL.  You can do that too and use iciql to build objects from your ResultSet, but be careful:\r
-\r
-1. Make sure to _select *_ in your query otherwise db.buildObjects() will throw a RuntimeException\r
-2. There is no model class type checking nor field type checking. \r
-\r
-%BEGINCODE%\r
-List<Product> allProducts = db.executeQuery(Product.class, "select * from products");\r
-List<Product> restock = db.executeQuery(Product.class, "select * from products where unitsInStock=?", 0);\r
-\r
-// parameterized query which can be cached and re-used later\r
-String q = db.from(p).where(p.unitsInStock).isParameter().toSQL();\r
-List<Product> restock = db.executeQuery(Product.class, q, 0);\r
-\r
-%ENDCODE% \r
-\r
-Or if you want access to the raw *ResultSet* before building your model object instances...\r
-\r
-%BEGINCODE%\r
-ResultSet rs = db.executeQuery("select * from products");\r
-List<Product> allProducts = db.buildObjects(Product.class, rs);\r
-// This method ensures the creating statement is closed\r
-JdbcUtils.closeSilently(rs, true);\r
-%ENDCODE% \r
-\r
-### Natural Syntax\r
-\r
-<span class="warning">work-in-progress</span>\r
-\r
-The original JaQu source offers partial support for Java expressions in *where* clauses.\r
-\r
-This works by decompiling a Java expression, at runtime, to an SQL condition.  The expression is written as an anonymous inner class implementation of the `com.iciql.Filter` interface.\r
-A proof-of-concept decompiler is included, but is incomplete.\r
-\r
-The proposed syntax is:\r
-%BEGINCODE%\r
-long count = db.from(co).\r
-    where(new Filter() { public boolean where() {\r
-        return co.id == x\r
-            && co.name.equals(name)\r
-            && co.value == new BigDecimal("1")\r
-            && co.amount == 1L\r
-            && co.birthday.before(new java.util.Date())\r
-            && co.created.before(java.sql.Timestamp.valueOf("2005-05-05 05:05:05"))\r
-            && co.time.before(java.sql.Time.valueOf("23:23:23"));\r
-        }\r
-    }).selectCount();\r
-%ENDCODE%\r
-\r
-### JDBC Statements, ResultSets, and Exception Handling\r
-\r
-Iciql opens and closes all JDBC objects automatically.  SQLExceptions thrown during execution of a statement (except for *close()* calls), will be caught, wrapped, and rethrown as an `IciqlException`, which is a RuntimeException.\r
-\r
-Iciql does not throw any [checked exceptions](http://en.wikipedia.org/wiki/Exception_handling#Checked_exceptions).\r
-\r
-### Statement Logging\r
-\r
-Iciql provides a mechanism to log generated statements and warnings to the console, to SLF4J, or to your own logging framework.  Exceptions are not logged using this mechanism; exceptions are wrapped and rethrown as `IciqlException`, which is a RuntimeException.\r
-\r
-#### Console Logging\r
-%BEGINCODE%\r
-IciqlLogger.activeConsoleLogger();\r
-IciqlLogger.deactiveConsoleLogger();\r
-%ENDCODE%\r
-\r
-#### SLF4J Logging\r
-%BEGINCODE%\r
-Slf4jIciqlListener slf4j = new Slf4jIciqlListener();\r
-slf4j.setLevel(StatementType.CREATE, Level.WARN);\r
-slf4j.setLevel(StatementType.DELETE, Level.WARN);\r
-slf4j.setLevel(StatementType.MERGE, Level.OFF);\r
-IciqlLogger.registerListener(slf4j);\r
-IciqlLogger.unregisterListener(slf4j);\r
-%ENDCODE%\r
-\r
-#### Custom Logging\r
-%BEGINCODE%\r
-IciqlListener custom = new IciqlListener() {\r
-    public void logIciql(StatementType type, String statement) {\r
-        // do log\r
-    }\r
-};\r
-IciqlLogger.registerListener(custom);\r
-IciqlLogger.unregisterListener(custom);\r
-%ENDCODE%\r
-\r
-## Understanding Aliases and Model Classes\r
-Consider the following example:\r
-%BEGINCODE%\r
-Product p = new Product();\r
-List<Product> restock = db.from(p).where(p.unitsInStock).is(0).select();\r
-%ENDCODE%\r
-\r
-The Product model class instance named **p** is an *alias* object.  An *alias* is simply an instance of your model class that is only used to build the compile-time/runtime representation of your table.\r
-\r
-1. *Alias* instances are **NOT** thread-safe and must not be used concurrently.\r
-2. *Alias* instances have no other purpose than to provide a compile-time/runtime map of your table.\r
-3. If you inspected an *alias* instance after using one you would find that it's fields have been assigned numeric values.<br/>These values are assigned from a static counter in `com.iciql.Utils.newObject()` during execution of the *db.from()* method.<p/>For *Object* fields, these values are meaningless since objects are mapped by reference.<br/>For *Primitive* fields these values do matter because primitives are mapped by value.  The proper alias is selected as long as the primitive variant methods are used.  e.g. db.from(p).where(int).is(Integer).select()\r
-\r
-If your statement is a query, like in the above example, iciql will generate new instances of your *alias* model class and return them as a list where each entry of the list represents a row from the JDBC `ResultSet`.\r
\r
-### Why are Aliases not thread-safe?\r
-\r
-The _db.from(p)_ call reinstantiates each member field of p.  Those reinstantiated fields are then subsequently used in clauses like _where(p.unitsInStock)_.  If your *alias* instance is shared concurrently then its highly probable that when _queryA_ executes, _queryC_ has reinstantiated all the *alias* fields and broken _queryA's_ runtime field mapping.\r
-\r
-Depending on your design, you might consider using a [ThreadLocal](http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html) variable if you do not want to keep instantiating *alias* instances.  A utility function is included for easily creating ThreadLocal variables.\r
-\r
-%BEGINCODE%\r
-final ThreadLocal<Product> p = Utils.newThreadLocal(Product.class);\r
-db.from(p.get()).select();\r
-%ENDCODE%\r
-\r
-## Best Practices\r
-\r
-1. Close your *Db* instances when you are done with them, this closes the underlying connection or directs the pool to "close" the connection.\r
-2. Aliases instances are not thread-safe so DO NOT SHARE an alias!<br/>Consider using a *ThreadLocal* alias instance with the `com.iciql.Utils.newThreadLocal()` utility method.\r
-\r
-<p/>\r
-<table class="table">\r
-<tr><th>Not Thread-Safe</th><th>Thread-Safe</th></tr>\r
-<tr><td>\r
-%BEGINCODE%\r
-final Product p = new Product();\r
-for (int i = 0; i < 5; i++) {\r
-    Thread thread = new Thread(new Runnable() {\r
-        public void run() {\r
-            // from(p) reinstantiates p's fields\r
-            db.from(p).select();\r
-        }\r
-    }, "Thread-" + i);\r
-    thread.start();\r
-}\r
-%ENDCODE%\r
-\r
-</td><td>\r
-%BEGINCODE%\r
-final ThreadLocal<Product> p = Utils.newThreadLocal(Product.class);\r
-for (int i = 0; i < 5; i++) {\r
-    Thread thread = new Thread(new Runnable() {\r
-        public void run() {\r
-            // a unique p for this thread            \r
-            db.from(p.get()).select();\r
-        }\r
-    }, "Thread-" + i);\r
-    thread.start();\r
-}\r
-%ENDCODE%\r
-\r
-</td></tr>\r
-</table>
\ No newline at end of file
diff --git a/src/site/03_performance.mkd b/src/site/03_performance.mkd
deleted file mode 100644 (file)
index 34e545c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-\r
-## Performance\r
-\r
-The information provided here may be based on flawed test procedures.  You have to be the judge of what is performant and non-performant.\r
-\r
-### iciql statement generation\r
-\r
-Performance of iciql statement generation is not currently benchmarked.\r
-\r
-### iciql+database performance comparison\r
-\r
-The following data was generated by running the *single-threaded* iciql test suite.  All database connections are pooled and re-used within each execution of the test suite using [Apache Commons DBCP](http://commons.apache.org/dbcp).\r
-\r
-Connections are pooled to normalize embedded database performance with out-of-process database performance.  Some of the Java embedded database configurations have a very high startup-time penalty.  Notably, H2 is slow to open a database and its performance is substantially affected if connection pooling is not enabled to keep the embedded database open.\r
-\r
-All tables are created as CACHED when the database distinguishes between CACHED and MEMORY tables.\r
-  \r
-All performance numbers include the combined overhead of iciql statement generation and JUnit 4 test framework execution so they are not bare-metal database metrics.  \r
-\r
-<pre>\r
-%DBPERFORMANCE%\r
-</pre>
\ No newline at end of file
diff --git a/src/site/04_examples.mkd b/src/site/04_examples.mkd
deleted file mode 100644 (file)
index 33cb9c4..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-## Select Statements\r
-\r
-%BEGINCODE%\r
-// select * from products\r
-List<Product> allProducts = db.from(p).select();\r
-\r
-// select * from customers where region='WA'\r
-Customer c = new Customer();\r
-List<Customer> waCustomers = db.from(c). where(c.region).is("WA").select();\r
-\r
-public static class ProductPrice {\r
-       public String productName;\r
-       public String category;\r
-       public Double price;\r
-}\r
-\r
-// select with generation of new anonymous inner class\r
-List<ProductPrice> productPrices =\r
-    db.from(p).\r
-    orderBy(p.productId).\r
-    select(new ProductPrice() {{\r
-        productName = p.productName;\r
-        category = p.category;\r
-        price = p.unitPrice;\r
-    }});\r
-%ENDCODE%\r
-\r
-## Insert Statements\r
-\r
-%BEGINCODE%\r
-// single record insertion\r
-db.insert(singleProduct);\r
-\r
-// single record insertion with primary key retrieval\r
-Long key = db.insertAndGetKey(singleProduct);\r
-\r
-// batch record insertion\r
-db.insertAll(myProducts);\r
-\r
-// batch insertion with primary key retrieval\r
-List<Long> myKeys = db.insertAllAndGetKeys(list);\r
-%ENDCODE%\r
-\r
-## Update Statements\r
-\r
-%BEGINCODE%\r
-// single record update\r
-db.update(singleProduct);\r
-\r
-// batch record updates\r
-db.updateAll(myProducts);\r
-\r
-// update query\r
-db.from(p).set(p.productName).to("updated")\r
-       .increment(p.unitPrice).by(3.14)\r
-       .increment(p.unitsInStock).by(2)\r
-       .where(p.productId).is(1).update();\r
-       \r
-// reusable, parameterized update query\r
-String q = db.from(p).set(p.productName).toParameter().where(p.productId).is(1).toSQL();\r
-db.executeUpdate(q, "Lettuce");\r
-\r
-%ENDCODE%\r
-\r
-## Merge Statements\r
-Merge statements currently generate the [H2 merge syntax](http://h2database.com/html/grammar.html#merge).\r
\r
-%BEGINCODE%\r
-Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();\r
-pChang.unitPrice = 19.5;\r
-pChang.unitsInStock = 16;\r
-db.merge(pChang);\r
-%ENDCODE%\r
-\r
-## Delete Statements\r
-\r
-%BEGINCODE%\r
-// single record deletion\r
-db.delete(singleProduct);  \r
-\r
-// batch record deletion\r
-db.deleteAll(myProducts);\r
-\r
-// delete query\r
-db.from(p).where(p.productId).atLeast(10).delete();\r
-\r
-%ENDCODE%\r
-\r
-## Inner Join Statements\r
-\r
-%BEGINCODE%\r
-final Customer c = new Customer();\r
-final Order o = new Order();\r
-\r
-List<Customer> customersWithLargeOrders =\r
-    db.from(c).\r
-    innerJoin(o).on(c.customerId).is(o.customerId).\r
-    where(o.total).greaterThan(new BigDecimal("500.00")).\r
-    groupBy(c.customerId).select();\r
-\r
-\r
-List<CustOrder> orders =\r
-    db.from(c).\r
-    innerJoin(o).on(c.customerId).is(o.customerId).\r
-    where(o.total).lessThan(new BigDecimal("500.00")).\r
-    orderBy(1).\r
-    select(new CustOrder() {{\r
-        customerId = c.customerId;\r
-        orderId = o.orderId;\r
-        total = o.total;\r
-    }});\r
-%ENDCODE%\r
-\r
-## View Statements\r
-\r
-%BEGINCODE%\r
-// the view named "ProductView" is created from the "Products" table\r
-@IQView(viewTableName = "Products")\r
-public class ProductView {\r
-\r
-    @IQColumn\r
-    @IQConstraint("this >= 200 AND this < 300")\r
-    Long id;\r
-       \r
-    @IQColumn\r
-    String name;\r
-}\r
-\r
-final ProductView v = new ProductView();\r
-List<ProductView> allProducts = db.from(v).select();\r
-\r
-// this version of the view model "ProductView" inherits table metadata\r
-// from the Products class which is annotated with IQTable\r
-@IQView(inheritColumns = true)\r
-public class ProductView extends Products {\r
-\r
-    // inherited BUT replaced to define the constraint\r
-    @IQColumn\r
-    @IQConstraint("this >= 200 AND this < 300")\r
-    Long id;\r
-       \r
-    // inherited from Products\r
-    //@IQColumn\r
-    //String name;\r
-}\r
-\r
-final ProductView v = new ProductView();\r
-List<ProductView> allProducts = db.from(v).select();\r
-\r
-// in this example we are creating a view based on a fluent query\r
-// and using 2 levels of inheritance.  IQConstraints are ignored\r
-// when using this approach because we are fluently defining them.\r
-@IQView(inheritColumns = true)\r
-public class ProductViewInherited extends ProductView {\r
-\r
-}\r
-\r
-final Products p = new Products();\r
-db.from(p).where(p.id).atLeast(200L).and(p.id).lessThan(300L).createView(ProductViewInherited.class);\r
-\r
-// now replace the view with a variation\r
-db.from(p).where(p.id).atLeast(250L).and(p.id).lessThan(350L).replaceView(ProductViewInherited.class);\r
-\r
-// now drop the view from the database\r
-db.dropView(ProductViewInherited.class);\r
-\r
-%ENDCODE%\r
-\r
-## Dynamic Queries\r
-\r
-Dynamic queries skip all field type checking and, depending on which approach you use, may skip model class/table name checking too.\r
-\r
-%BEGINCODE%\r
-// where fragment with object parameters\r
-List<Product> restock = db.from(p).where("unitsInStock=? and productName like ? order by productId", 0, "Chef%").select();\r
-\r
-// parameterized query which can be cached and re-used later\r
-String q = db.from(p).where(p.unitsInStock).isParameter().and(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
-List<Product> allProducts = db.executeQuery(Product.class, q, 0, "Chef%");\r
-\r
-// statement with binding to your model class\r
-List<Product> allProducts = db.executeQuery(Product.class, "select * from products");\r
-\r
-// statement with object parameters and binding to your model class\r
-List<Product> restock = db.executeQuery(Product.class, "select * from products where unitsInStock=?", 0);\r
-\r
-/**\r
- * If you want to process the intermediate ResultSet\r
- * yourself make sure to use the <i>closeSilently()</i> method \r
- * to ensure the parent statement is closed too.\r
- */\r
-ResultSet rs = db.executeQuery("select * from products");\r
-List<Product> allProducts = db.buildObjects(Product.class, rs);\r
-JdbcUtils.closeSilently(rs, true);\r
-\r
-%ENDCODE%
\ No newline at end of file
diff --git a/src/site/04_tools.mkd b/src/site/04_tools.mkd
deleted file mode 100644 (file)
index 6d8c348..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-## Model Generation\r
-If you do not have or do not want to annotate your existing model classes, you can use the included model generation tool to create iciql model classes.\r
-\r
-    java -jar iciql.jar <parameters>\r
-\r
-### Parameters\r
-<table class="table">\r
-<tr><th>-url</th><td>JDBC url for the database</td><td><em>REQUIRED</em></td></tr>\r
-<tr><th>-username</th><td>username for JDBC connection</td><td><em>optional</em></td></tr>\r
-<tr><th>-password</th><td>password for JDBC connection</td><td><em>optional</em></td></tr>\r
-<tr><th>-schema</th><td>the target schema for model generation</td><td><em>default:</em> all schemas</td></tr>\r
-<tr><th>-table</th><td>the target table for model generation</td><td><em>default:</em> all tables</td></tr>\r
-<tr><th>-package</th><td>the destination package name for generated models</td><td><em>default:</em> default package</td></tr>\r
-<tr><th>-folder</th><td>the output folder for .java files</td><td><em>default:</em> current folder</td></tr>\r
-<tr><th>-annotateSchema</th><td>include the schema name in the class annotations</td><td><em>default:</em> true</td></tr>\r
-<tr><th>-trimStrings</th><td>annotate trimStrings=true for any VARCHAR string mappings &nbsp; </td><td><em>default:</em> false</td></tr>\r
-</table>\r
-\r
-## Model Validation\r
-Iciql can validate your model classes against your database to ensure that your models are optimally defined and are consistent with the current table and index definitions.\r
-\r
-Each `com.iciql.ValidationRemark` returned by the validation has an associated level from the following enum:\r
-%BEGINCODE%\r
-public static enum Level {\r
-       CONSIDER, WARN, ERROR;\r
-}\r
-%ENDCODE%\r
-\r
-A typical validation may output recommendations for adjusting a model field annotation such as setting the *maxLength* of a string to match the length of its linked VARCHAR column.\r
-\r
-### Sample Model Validation using JUnit 4\r
-%BEGINCODE%\r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.sql.SQLException;\r
-\r
-import org.junit.After;\r
-import org.junit.Before;\r
-import org.junit.Rule;\r
-import org.junit.Test;\r
-import org.junit.rules.ErrorCollector;\r
-\r
-import com.iciql.Db;\r
-import com.iciql.DbInspector;\r
-import com.iciql.ValidationRemark;\r
-import com.iciql.test.models.Product;\r
-import com.iciql.test.models.ProductAnnotationOnly;\r
-import com.iciql.test.models.ProductMixedAnnotation;\r
-\r
-public class ValidateModels {\r
-\r
-       /*\r
-        * The ErrorCollector Rule allows execution of a test to continue after the\r
-        * first problem is found and report them all at once\r
-        */\r
-       @Rule\r
-       public ErrorCollector errorCollector = new ErrorCollector();\r
-       \r
-       private Db db;\r
-       \r
-       @Before\r
-       public void setUp() {\r
-               db = Db.open("jdbc:h2:mem:", "sa", "sa");\r
-       }\r
-\r
-       @After\r
-       public void tearDown() {\r
-               db.close();\r
-       }\r
-       \r
-       @Test\r
-       public void testValidateModels() {\r
-               DbInspector inspector = new DbInspector(db);\r
-               validateModel(inspector, new Product());\r
-               validateModel(inspector, new ProductAnnotationOnly());\r
-               validateModel(inspector, new ProductMixedAnnotation());\r
-       }\r
-       \r
-       private void validateModel(DbInspector inspector, Object o) {\r
-               List<ValidationRemark> remarks = inspector.validateModel(o, false);\r
-               assertTrue("Validation remarks are null for " + o.getClass().getName(), remarks != null);\r
-               log("Validation remarks for " + o.getClass().getName());\r
-               for (ValidationRemark remark : remarks) {\r
-                       log(remark.toString());\r
-                       if (remark.isError()) {\r
-                               errorCollector.addError(new SQLException(remark.toString()));\r
-                       }\r
-               }\r
-       }\r
-       \r
-       private void log(String message) {\r
-               System.out.println(message);\r
-       }\r
-}\r
-%ENDCODE%
\ No newline at end of file
diff --git a/src/site/05_building.mkd b/src/site/05_building.mkd
deleted file mode 100644 (file)
index b5548bc..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-## Building from Source\r
-\r
-[Eclipse](http://eclipse.org) is recommended for development as the project settings are preconfigured.\r
-\r
-Additionally, [eclipse-cs](http://eclipse-cs.sourceforge.net), [FindBugs](http://findbugs.sourceforge.net), and [EclEmma](http://www.eclemma.org) are recommended development tools.\r
-\r
-### Build Dependencies (bundled in repository)\r
-- [ant-googlecode](http://code.google.com/p/ant-googlecode) (New BSD)\r
-\r
-### Build Dependencies (downloaded during build)\r
-- [Moxie Build Toolkit](http://moxie.gitblit.com) (Apache 2.0)\r
-- [H2 Database](http://h2database.com) (Eclipse Public License 1.0)\r
-- [HSQL Database Engine](http://hsqldb.org) (BSD)\r
-- [Apache Derby Database](http://db.apache.org/derby) (Apache 2.0)\r
-- [MySQL Connector/J](http://dev.mysql.com/downloads/connector/j) (GPL)\r
-- [PostgreSQL JDBC Connector](http://jdbc.postgresql.org) (BSD)\r
-- [JUnit](http://junit.org) (Common Public License)\r
-- [SLF4J](http://www.slf4j.org) (MIT/X11)\r
-- [Apache Commons Pool](http://commons.apache.org/pool) (Apache 2.0)\r
-- [Apache Commons DBCP](http://commons.apache.org/dbcp) (Apache 2.0)\r
-\r
-### Instructions\r
-1. Clone the git repository from [Github](${project.scmUrl}).\r
-2. Import the iciql project into your Eclipse workspace.<br/>\r
-*There will be some build errors.*\r
-3. Using Ant, execute the `build.xml` script in the project root.<br/>\r
-*This will download all necessary build dependencies.*\r
-4. Select your iciql project root and **Refresh** the project, this should correct all build problems.\r
-\r
-## Contributing\r
-Patches welcome in any form.\r
-\r
-Contributions must be your own original work and must licensed under the [Apache License, Version 2.0][apachelicense], the same license used by iciql.\r
-\r
-[apachelicense]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0"
\ No newline at end of file
diff --git a/src/site/05_javadoc.mkd b/src/site/05_javadoc.mkd
deleted file mode 100644 (file)
index 0d0f161..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<div class="javadoc_nav">\r
-<a href="javadoc/overview-summary.html" target="javadoc">packages</a>\r
- | <a href="javadoc/overview-tree.html" target="javadoc">tree</a>\r
- | <a href="javadoc/deprecated-list.html" target="javadoc">deprecated</a>\r
- | <a href="javadoc/index-all.html" target="javadoc">index</a>\r
-</div>\r
-<iframe name="javadoc" src="javadoc/overview-summary.html" width="100%" height="650" frameborder="0"></iframe>\r
diff --git a/src/site/05_releases.mkd b/src/site/05_releases.mkd
deleted file mode 100644 (file)
index 3e66494..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-## Release History\r
-\r
-### Current Release\r
-\r
-**${project.version}**\r
-\r
-- Fixed case-sensitivity bug on setting a compound primary key from an annotation (issue 12)\r
-- Implemented readonly view support. (issue 8)<br/>\r
-View models may be specified using the IQView annotation or Iciql.define().  Views can either be created automatically as part of a query of the view OR views may be constructed from a fluent statement.\r
-- Support inheriting columns from super.super class, if super.super is annotated.<br/>This allows for an inheritance hierarchy like:<br/>\r
-@IQTable class MyTable -> @IQView abstract class MyBaseView -> @IQView class MyConstrainedView\r
-- Fixed order of DEFAULT value in create table statement (issue 11)\r
-- Support inheritance of IQVersion for DbUpgrader implementations (issue 10)\r
-- Fixed password bug in model generator (issue 7)\r
-\r
-### Older Releases\r
-\r
-**1.1.0** &nbsp; *released 2012-08-20*\r
-\r
-- All bulk operations (insert all, update all, delete all) now use JDBC savepoints to ensure atomicity of the transaction\r
-\r
-**1.0.0** &nbsp; *released 2012-07-14*\r
-\r
-- Issue CREATE TABLE and CREATE INDEX statements once per-db instance/table-mapping\r
-- Fixed bug in using 0L primitive values in where clauses.  These were confused with the COUNT(*) function. (Github/kc5nra,issue 5)\r
-- Added support for single column subquery *select name, address from user_table where user_id in (select user_id from invoice table where paid = false)*\r
-- Added support for left outer join (Github/backpaper0)\r
-\r
-**0.7.10** &nbsp; *released 2012-01-27*\r
-\r
-- Fixed default String value bug where a default empty string threw an IndexOutOfBounds exception\r
-\r
-**0.7.9** &nbsp; *released 2012-01-24*\r
-\r
-- Added toParameter() option for SET commands and allow generating parameterized UPDATE statements<br/>\r
-String q = db.from(t).set(t.timestamp).toParameter().where(t.id).is(5).toSQL();<br/>\r
-db.executeUpdate(q, new Date());\r
-\r
-**0.7.8** &nbsp; *released 2012-01-11*\r
-\r
-- Replaced non-threadsafe counter used for assigning AS identifiers in JOIN statements with an AtomicInteger\r
-- Prevent negative rollover of the AS counter\r
-- Added optional alias parameter to *Query.toSQL* and *QueryWhere.toSQL* to force generated statement to prefix an AS identifier or, alternatively, the tablename.  \r
-    - Query.toSQL(boolean distinct, K alias)\r
-    - QueryWhere.toSQL(boolean distinct, K alias)\r
-- Fixed bug in Query.select(Z z) which assumed that Z must always be an anonymous inner class which may not always be true.  This allows for specifying an existing alias to force table or identifier usage in the generated select list.  This is very useful for DISTINCT JOIN statements where only the columns of the primary table are of interest.\r
-\r
-**0.7.7** &nbsp; *released 2012-01-05*\r
-\r
-- added *Query.toSQL()* and *QueryWhere.toSQL()* methods which, when combined with the following new methods, allows for generation of a parameterized, static sql string to be reused with a dynamic query or a PreparedStatement.  \r
-    - QueryCondition.isParameter()\r
-    - QueryCondition.atLeastParameter()\r
-    - QueryCondition.atMostParameter()\r
-    - QueryCondition.exceedsParameter()\r
-    - QueryCondition.lessThanParameter()\r
-    - QueryCondition.likeParameter()\r
-    - QueryCondition.isNotParameter()\r
-- Disallow **declaring and explicitly referencing** multiple instances of an enum type within a single model.<br/>A runtime exception will be thrown if an attempt to use where/set/on/and/or/groupBy/orderBy(enum) and your model has multiple fields of a single enum type.\r
-\r
-**0.7.6** &nbsp; *released 2011-12-21*\r
-\r
-- Iciql now tries to instantiate a default value from an annotated default value IFF the field object is null, it is specified *nullable = false*, and a defaultValue exists.  This only applies to *db.insert* or *db.update*.\r
-\r
-**0.7.5** &nbsp; *released 2011-12-12*\r
-\r
-- Iciql now identifies wildcard queries and builds a dynamic column lookup.  Otherwise, the original field-position-based approach is used.  This corrects the performance regression released in 0.7.4 while still fixing the wildcard statement column mapping problem. \r
-\r
-**0.7.4** &nbsp; *released 2011-12-06*\r
-\r
-- Disallow **declaring and explicitly referencing** multiple primitive booleans in a single model.<br/>A runtime exception will be thrown if an attempt to use where/set/on/and/or/groupBy/orderBy(boolean) and your model has multiple mapped primitive boolean fields.\r
-- Added list alternatives to the varargs methods because it was too easy to forget list.toArray()<br/>\r
-*Db.executeQuery(Class&lt;? extends T&gt; modelClass, String sql, List&lt;?&gt; args)*<br/>\r
-*Db.executeQuery(String sql, List&lt;?&gt; args)*<br/>\r
-*Query.where(String fragment, List&lt;?&gt; args)*<br/>\r
-- Fixed inherited JaQu bug related to model classes and wildcard queries (select *).<p/>\r
-Iciql maps resultset columns by the index of the model class field from a list.  This assumes that *all* columns in the resultset have a corresponding model field definition.  This works fine for most queries because iciql explicitly selects columns from the table (*select alpha, beta...*) when you execute *select()*.  The problem is when iciql issues a dynamic wildcard query and your model does not represent all columns in the resultset: columns and fields may fail to correctly line-up.<p/>\r
-Iciql now maps all fields by their column name, not by their position.\r
-\r
-**0.7.3** &nbsp; *released 2011-12-06*\r
-\r
-- api change release (API v8)\r
-- Fixed JOIN ON primitives\r
-- Fixed GROUP BY primitives\r
-- Fixed primitive references when selecting into a custom type with primitives\r
-- Improved fluent/type-safety of joins\r
-\r
-**0.7.2** &nbsp; *released 2011-11-30*\r
-\r
-- generated models are now serializable with a default serial version id of 1\r
-- Updated to H2 1.3.162\r
-- Updated to HSQL 2.2.6 (100% unit test pass now that [this bug](https://sourceforge.net/tracker/?func=detail&aid=3390047&group_id=23316&atid=378131) was fixed)\r
-\r
-**0.7.1** &nbsp; *released 2011-08-31*\r
-\r
-- api change release (API v7)\r
-- Undeprecated interface configuration\r
-- Interface configuration now maps ALL fields, not just public fields\r
-- Added @IQIgnore annotation to explicitly skip fields for interface configuration \r
-- Created additional Define static methods to bring interface configuration to near-parity with annotation configuration\r
-- Documented POJO configuration option (limited subset of interface configuration)\r
-- Fix to PostgreSQL dialect when creating autoincrement columns\r
-- Fix to default dialect when creating autoincrement columns\r
-- Added Db.open(url) method\r
-\r
-**0.7.0** &nbsp; *released 2011-08-17*\r
-\r
-- api change release (API v6)\r
-- Finished MySQL dialect implementation.  MySQL 5.0.51b passes 100% of tests.\r
-- Added PostgreSQL dialect.  PostgreSQL 9.0 passes all but the boolean-as-int tests.\r
-- Added Db.dropTable(T) method\r
-- Overhauled test suite and included more database configurations.\r
-- Renamed StatementLogger to IciqlLogger\r
-- Added IciqlLogger.warn method\r
-- Added IciqlLogger.drop method\r
-\r
-**0.6.6** &nbsp; *released 2011-08-15*\r
-\r
-- api change release (API v5)\r
-- Disabled two concurrency unit tests since I believe they are flawed and do not yield reproducible results\r
-- Added Derby database dialect.  Derby 10.7.1.1 and 10.8.1.2 pass 100% of tests.\r
-- Implemented HSQL MERGE syntax.  HSQL 2.2.4 fails 1 test which is a known [bug in HSQL](https://sourceforge.net/tracker/?func=detail&aid=3390047&group_id=23316&atid=378131)\r
-- Updated to H2 1.3.159\r
-\r
-**0.6.5** &nbsp; *released 2011-08-12*\r
-\r
-- fixed failure of db.delete(PrimitiveModel) and db.update(PrimitiveModel)\r
-\r
-**0.6.4** &nbsp; *released 2011-08-12*\r
-\r
-- api change release (API v4)\r
-- @IQTable.createIfRequired -> @IQTable.create\r
-- don't INSERT primitive autoIncrement fields, let database assign value\r
-- full support for primitives in all clauses\r
-- DECIMAL(length, scale) support\r
-- unspecified length String fields are now CLOB instead of TEXT.  dialects can intercept this and convert to another type. e.g. MySQL dialect can change CLOB to TEXT.\r
-- java.lang.Boolean now maps to BOOLEAN instead of BIT\r
-- expressions on unmapped fields will throw an IciqlException\r
-- expressions on unsupported types will throw an IciqlException\r
-- improved exception reporting by including generated statement, if available \r
-- moved dialects back to main package\r
-- improved automatic dialect determination on pooled connections\r
-- moved create table and create index statement generation into dialects\r
-- added HSQL dialect.  HSQL fails 4 out of 50 unit tests.\r
-    - 2 failures are unimplemented merge\r
-    - 1 has been filed and accepted as a [bug in HSQL](https://sourceforge.net/tracker/?func=detail&aid=3390047&group_id=23316&atid=378131)\r
-    - 1 is a concurrency issue, but the test may be flawed\r
-- added untested MySQL dialect\r
-- renamed <b>_ iq_versions</b> table to *iq_versions* since leading _ character is troublesome for some databases.\r
-- @IQColumn(allowNull=true) -> @IQColumn(nullable=true)\r
-- All **Object** columns are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)*\r
-- All **Primitive** columns are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)*\r
-- allow using objects to assign default values<br/>\r
-%BEGINCODE%\r
-// CREATE TABLE ... myDate DATETIME DEFAULT '2000-02-01 00:00:00'\r
-@IQColumn\r
-Date myDate = new Date(100, 1, 1);\r
-%ENDCODE%\r
-- changed @IQTable.primaryKey definition to use array of column names<br/>\r
-%BEGINCODE%\r
-@IQTable( primaryKey = {"name", "nickname"})\r
-%ENDCODE%\r
-\r
-**0.6.3** &nbsp; *released 2011-08-08*\r
-\r
-- api change release (API v3)\r
-- finished enum support (issue 4)\r
-- added UUID type support (H2 databases only)\r
-- added partial primitives support *(primitives may not be used for compile-time condition clauses)*\r
-- added *between(A y).and(A z)* condition syntax\r
-- moved dialects into separate package\r
-\r
-**0.6.2** &nbsp; *released 2011-08-05*\r
-\r
-- api change release (API v2)\r
-- fix to versioning to support H2 1.3.158+\r
-- added BLOB support (issue 1)\r
-- added java.lang.Enum support (issue 2)\r
-- allow runtime flexible mapping of BOOL columns to Integer fields\r
-- allow runtime flexible mapping of INT columns to Boolean fields\r
-- annotations overhaul to reduce verbosity\r
-    - @IQSchema(name="public") -> @IQSchema("public")\r
-    - @IQDatabase(version=2) -> @IQVersion(2)\r
-    - @IQTable(version=2) -> @IQVersion(2)\r
-    - @IQIndex annotation simplified to be used for one index definition and expanded to specify index name\r
-    - added @IQIndexes annotation to specify multiple IQIndex annotations<br/>\r
-%BEGINCODE%\r
-@IQIndexes({ @IQIndex("name"), @IQIndex(name="myindexname" value={"name", "nickname"}) })\r
-%ENDCODE%\r
-    - @IQColumn(maxLength=20) -> @IQColumn(length=20)\r
-    - @IQColumn(trimString=true) -> @IQColumn(trim=true)\r
-    \r
-**0.5.0** &nbsp; *released 2011-08-03*\r
-\r
-- initial release (API v1)\r
-\r
-*API changes compared to JaQu from H2 1.3.157 sources*\r
-\r
-- deprecated model class interface configuration\r
-- added *Db.open(Connection conn)* method, changed constructor to default scope\r
-- added *Db.registerDialect* static methods to register custom dialects\r
-- added *Query.where(String fragment, Object... args)* method to build a runtime query fragment when compile-time queries are too strict\r
-- added *Db.executeQuery(String query, Object... args)* to execute a complete sql query with optional arguments\r
-- added *Db.executeQuery(Class modelClass, String query, Object... args)* to execute a complete sql query, with optional arguments, and build objects from the result\r
-- added *Db.buildObjects(Class modelClass, ResultSet rs)* method to build objects from the ResultSet of a plain sql query\r
-- added *ThreadLocal&lt;T&gt; com.iciql.Utils.newThreadLocal(final Class&lt;? extends T&gt; clazz)* method\r
-- added optional console statement logger and SLF4J statement logger\r
-- refactored dialect support\r
-- throw *IciqlException* (which is a RuntimeException) instead of RuntimeException\r
-- synchronized *Db.classMap* for concurrent sharing of a Db instance\r
-- Database/table versioning uses the <b>_iq_versions </b> table, the <b>_ jq_versions</b> table, if present, is ignored\r
-- Changed the following class names:\r
-    - org.h2.jaqu.Table =&gt; com.iciql.Iciql\r
-    - org.h2.jaqu.JQSchema =&gt; com.iciql.IQSchema\r
-    - org.h2.jaqu.JQDatabase =&gt; com.iciql.IQDatabase\r
-    - org.h2.jaqu.JQIndex =&gt; com.iciql.IQIndex\r
-    - org.h2.jaqu.JQTable =&gt; com.iciql.IQTable\r
-    - org.h2.jaqu.JQColumn =&gt; com.iciql.IQColumn\r
-- Changed the following method names:\r
-    - org.h2.jaqu.Table.define() =&gt; com.iciql.Iciql.defineIQ()\r
-    - QueryConditon.bigger =&gt; QueryCondition.exceeds\r
-    - QueryConditon.biggerEqual =&gt; QueryCondition.atLeast\r
-    - QueryConditon.smaller =&gt; QueryCondition.lessThan\r
-    - QueryConditon.smallEqual =&gt; QueryCondition.atMost\r
diff --git a/src/site/06_jaqu_comparison.mkd b/src/site/06_jaqu_comparison.mkd
deleted file mode 100644 (file)
index 20df5d5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-\r
-## Comparison to JaQu \r
-\r
-This is an overview of the fundamental differences between the original JaQu project and the current featureset of iciql.  \r
-\r
-<table class="table">\r
-<tr><th></th><th>Iciql</th><th>JaQu</th></tr>\r
-<tr><th colspan="3">core</th></tr>\r
-<tr><td>deployment</td><td>small, discrete library</td><td>depends on H2 database jar file</td></tr>\r
-<tr><td>databases</td><td>H2, HSQL, Derby, MySQL, and PostreSQL</td><td>H2 only</td></tr>\r
-<tr><td>logging</td><td>console, SLF4J, or custom logging</td><td>console logging</td></tr>\r
-<tr><td>exceptions</td><td>always includes generated statement in exception, when available</td><td>--</td></tr>\r
-<tr><td>column mappings</td><td>wildcard queries index result sets by column name</td><td>all result sets built by field index<br/>this can fail for wildcard queries</td></tr>\r
-<tr><td>savepoints</td><td>bulk operations (insert, update, delete) use savepoints with rollback in the event of failure</td><td>--</td></tr>\r
-<tr><th colspan="3">syntax and api</th></tr>\r
-<tr><td>VIEWs</td><td>create readonly views either from a class definition or from a fluent statement</td><td>--</td></tr>\r
-<tr><td>dynamic queries</td><td>methods and where clauses for dynamic queries that build iciql objects</td><td>--</td></tr>\r
-<tr><td>DROP</td><td>syntax to drop a table or view</td><td></td></tr>\r
-<tr><td>BETWEEN</td><td>syntax for specifying a BETWEEN x AND y clause</td><td>--</td></tr>\r
-<tr><th colspan="3">types</th></tr>\r
-<tr><td>primitives</td><td>fully supported</td><td>--</td></tr>\r
-<tr><td>enums</td><td>fully supported</td><td>--</td></tr>\r
-<tr><td>DECIMAL(length,scale)</td><td>can specify length/precision and scale</td><td>--</td></tr>\r
-<tr><td>BOOLEAN</td><td>flexible mapping of boolean as bool, varchar, or int</td><td>--</td></tr>\r
-<tr><td>BLOB</td><td>partially supported <em>(can not be used in a WHERE clause)</em></td><td>--</td></tr>\r
-<tr><td>UUID</td><td>fully supported <em>(H2 only)</em> </td><td>--</td></tr>\r
-<tr><th colspan="3">configuration</th></tr>\r
-<tr><td>DEFAULT values</td><td>set from annotation, <em>default object values</em>, or Define.defaultValue()</td><td>set from annotations</td></tr>\r
-<tr><td>Interface Configuration<br/>Mapped Fields</td><td><em>all fields</em> are mapped regardless of scope<br/>fields are ignored by annotating with @IQIgnore</td><td><em>all public fields</em> are mapped<br/>fields are ignored by reducing their scope</td></tr>\r
-<tr><td>Index names</td><td>can be set</td><td>--</td></tr>\r
-</table>
\ No newline at end of file
diff --git a/src/site/building.mkd b/src/site/building.mkd
new file mode 100644 (file)
index 0000000..b5548bc
--- /dev/null
@@ -0,0 +1,35 @@
+## Building from Source\r
+\r
+[Eclipse](http://eclipse.org) is recommended for development as the project settings are preconfigured.\r
+\r
+Additionally, [eclipse-cs](http://eclipse-cs.sourceforge.net), [FindBugs](http://findbugs.sourceforge.net), and [EclEmma](http://www.eclemma.org) are recommended development tools.\r
+\r
+### Build Dependencies (bundled in repository)\r
+- [ant-googlecode](http://code.google.com/p/ant-googlecode) (New BSD)\r
+\r
+### Build Dependencies (downloaded during build)\r
+- [Moxie Build Toolkit](http://moxie.gitblit.com) (Apache 2.0)\r
+- [H2 Database](http://h2database.com) (Eclipse Public License 1.0)\r
+- [HSQL Database Engine](http://hsqldb.org) (BSD)\r
+- [Apache Derby Database](http://db.apache.org/derby) (Apache 2.0)\r
+- [MySQL Connector/J](http://dev.mysql.com/downloads/connector/j) (GPL)\r
+- [PostgreSQL JDBC Connector](http://jdbc.postgresql.org) (BSD)\r
+- [JUnit](http://junit.org) (Common Public License)\r
+- [SLF4J](http://www.slf4j.org) (MIT/X11)\r
+- [Apache Commons Pool](http://commons.apache.org/pool) (Apache 2.0)\r
+- [Apache Commons DBCP](http://commons.apache.org/dbcp) (Apache 2.0)\r
+\r
+### Instructions\r
+1. Clone the git repository from [Github](${project.scmUrl}).\r
+2. Import the iciql project into your Eclipse workspace.<br/>\r
+*There will be some build errors.*\r
+3. Using Ant, execute the `build.xml` script in the project root.<br/>\r
+*This will download all necessary build dependencies.*\r
+4. Select your iciql project root and **Refresh** the project, this should correct all build problems.\r
+\r
+## Contributing\r
+Patches welcome in any form.\r
+\r
+Contributions must be your own original work and must licensed under the [Apache License, Version 2.0][apachelicense], the same license used by iciql.\r
+\r
+[apachelicense]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0"
\ No newline at end of file
index 31098f5b1cb8701f978172fe58fc1313c37a72a3..f7130d408a4123255a3c5bbe10455daf150bea05 100644 (file)
@@ -2,7 +2,7 @@
 // GLOBAL VALUES\r
 // --------------------------------------------------\r
 @standardGray:                         #ccc;\r
-@cornflower:                           #abd4ff;\r
+@cornflower:                           #99cbff;\r
 @white:                                                #fff;\r
 \r
 // Dropdown\r
diff --git a/src/site/examples.mkd b/src/site/examples.mkd
new file mode 100644 (file)
index 0000000..33cb9c4
--- /dev/null
@@ -0,0 +1,196 @@
+## Select Statements\r
+\r
+%BEGINCODE%\r
+// select * from products\r
+List<Product> allProducts = db.from(p).select();\r
+\r
+// select * from customers where region='WA'\r
+Customer c = new Customer();\r
+List<Customer> waCustomers = db.from(c). where(c.region).is("WA").select();\r
+\r
+public static class ProductPrice {\r
+       public String productName;\r
+       public String category;\r
+       public Double price;\r
+}\r
+\r
+// select with generation of new anonymous inner class\r
+List<ProductPrice> productPrices =\r
+    db.from(p).\r
+    orderBy(p.productId).\r
+    select(new ProductPrice() {{\r
+        productName = p.productName;\r
+        category = p.category;\r
+        price = p.unitPrice;\r
+    }});\r
+%ENDCODE%\r
+\r
+## Insert Statements\r
+\r
+%BEGINCODE%\r
+// single record insertion\r
+db.insert(singleProduct);\r
+\r
+// single record insertion with primary key retrieval\r
+Long key = db.insertAndGetKey(singleProduct);\r
+\r
+// batch record insertion\r
+db.insertAll(myProducts);\r
+\r
+// batch insertion with primary key retrieval\r
+List<Long> myKeys = db.insertAllAndGetKeys(list);\r
+%ENDCODE%\r
+\r
+## Update Statements\r
+\r
+%BEGINCODE%\r
+// single record update\r
+db.update(singleProduct);\r
+\r
+// batch record updates\r
+db.updateAll(myProducts);\r
+\r
+// update query\r
+db.from(p).set(p.productName).to("updated")\r
+       .increment(p.unitPrice).by(3.14)\r
+       .increment(p.unitsInStock).by(2)\r
+       .where(p.productId).is(1).update();\r
+       \r
+// reusable, parameterized update query\r
+String q = db.from(p).set(p.productName).toParameter().where(p.productId).is(1).toSQL();\r
+db.executeUpdate(q, "Lettuce");\r
+\r
+%ENDCODE%\r
+\r
+## Merge Statements\r
+Merge statements currently generate the [H2 merge syntax](http://h2database.com/html/grammar.html#merge).\r
\r
+%BEGINCODE%\r
+Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();\r
+pChang.unitPrice = 19.5;\r
+pChang.unitsInStock = 16;\r
+db.merge(pChang);\r
+%ENDCODE%\r
+\r
+## Delete Statements\r
+\r
+%BEGINCODE%\r
+// single record deletion\r
+db.delete(singleProduct);  \r
+\r
+// batch record deletion\r
+db.deleteAll(myProducts);\r
+\r
+// delete query\r
+db.from(p).where(p.productId).atLeast(10).delete();\r
+\r
+%ENDCODE%\r
+\r
+## Inner Join Statements\r
+\r
+%BEGINCODE%\r
+final Customer c = new Customer();\r
+final Order o = new Order();\r
+\r
+List<Customer> customersWithLargeOrders =\r
+    db.from(c).\r
+    innerJoin(o).on(c.customerId).is(o.customerId).\r
+    where(o.total).greaterThan(new BigDecimal("500.00")).\r
+    groupBy(c.customerId).select();\r
+\r
+\r
+List<CustOrder> orders =\r
+    db.from(c).\r
+    innerJoin(o).on(c.customerId).is(o.customerId).\r
+    where(o.total).lessThan(new BigDecimal("500.00")).\r
+    orderBy(1).\r
+    select(new CustOrder() {{\r
+        customerId = c.customerId;\r
+        orderId = o.orderId;\r
+        total = o.total;\r
+    }});\r
+%ENDCODE%\r
+\r
+## View Statements\r
+\r
+%BEGINCODE%\r
+// the view named "ProductView" is created from the "Products" table\r
+@IQView(viewTableName = "Products")\r
+public class ProductView {\r
+\r
+    @IQColumn\r
+    @IQConstraint("this >= 200 AND this < 300")\r
+    Long id;\r
+       \r
+    @IQColumn\r
+    String name;\r
+}\r
+\r
+final ProductView v = new ProductView();\r
+List<ProductView> allProducts = db.from(v).select();\r
+\r
+// this version of the view model "ProductView" inherits table metadata\r
+// from the Products class which is annotated with IQTable\r
+@IQView(inheritColumns = true)\r
+public class ProductView extends Products {\r
+\r
+    // inherited BUT replaced to define the constraint\r
+    @IQColumn\r
+    @IQConstraint("this >= 200 AND this < 300")\r
+    Long id;\r
+       \r
+    // inherited from Products\r
+    //@IQColumn\r
+    //String name;\r
+}\r
+\r
+final ProductView v = new ProductView();\r
+List<ProductView> allProducts = db.from(v).select();\r
+\r
+// in this example we are creating a view based on a fluent query\r
+// and using 2 levels of inheritance.  IQConstraints are ignored\r
+// when using this approach because we are fluently defining them.\r
+@IQView(inheritColumns = true)\r
+public class ProductViewInherited extends ProductView {\r
+\r
+}\r
+\r
+final Products p = new Products();\r
+db.from(p).where(p.id).atLeast(200L).and(p.id).lessThan(300L).createView(ProductViewInherited.class);\r
+\r
+// now replace the view with a variation\r
+db.from(p).where(p.id).atLeast(250L).and(p.id).lessThan(350L).replaceView(ProductViewInherited.class);\r
+\r
+// now drop the view from the database\r
+db.dropView(ProductViewInherited.class);\r
+\r
+%ENDCODE%\r
+\r
+## Dynamic Queries\r
+\r
+Dynamic queries skip all field type checking and, depending on which approach you use, may skip model class/table name checking too.\r
+\r
+%BEGINCODE%\r
+// where fragment with object parameters\r
+List<Product> restock = db.from(p).where("unitsInStock=? and productName like ? order by productId", 0, "Chef%").select();\r
+\r
+// parameterized query which can be cached and re-used later\r
+String q = db.from(p).where(p.unitsInStock).isParameter().and(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
+List<Product> allProducts = db.executeQuery(Product.class, q, 0, "Chef%");\r
+\r
+// statement with binding to your model class\r
+List<Product> allProducts = db.executeQuery(Product.class, "select * from products");\r
+\r
+// statement with object parameters and binding to your model class\r
+List<Product> restock = db.executeQuery(Product.class, "select * from products where unitsInStock=?", 0);\r
+\r
+/**\r
+ * If you want to process the intermediate ResultSet\r
+ * yourself make sure to use the <i>closeSilently()</i> method \r
+ * to ensure the parent statement is closed too.\r
+ */\r
+ResultSet rs = db.executeQuery("select * from products");\r
+List<Product> allProducts = db.buildObjects(Product.class, rs);\r
+JdbcUtils.closeSilently(rs, true);\r
+\r
+%ENDCODE%
\ No newline at end of file
diff --git a/src/site/index.mkd b/src/site/index.mkd
new file mode 100644 (file)
index 0000000..1c2bbd3
--- /dev/null
@@ -0,0 +1,63 @@
+## Overview\r
+\r
+iciql **is**...\r
+\r
+- a model-based, database access wrapper for JDBC\r
+- for modest database schemas and basic statement generation\r
+- for those who want to write code, instead of SQL, using IDE completion and compile-time type-safety\r
+- small (200KB) with debug symbols and no runtime dependencies\r
+- pronounced *icicle* (although it could be French: *ici ql* - here query language)\r
+- a friendly fork of the H2 [JaQu][jaqu] project\r
+\r
+iciql **is not**...\r
+\r
+- a complete alternative to JDBC\r
+- designed to compete with more powerful database query tools like [jOOQ][jooq] or [Querydsl][querydsl]\r
+- designed to compete with enterprise [ORM][orm] tools like [Hibernate][hibernate] or [mybatis][mybatis]\r
+\r
+### Example Usage\r
+<table class="table">\r
+<tr>\r
+<th>iciql</th><th>sql</th>\r
+</tr>\r
+<tr>\r
+<td>\r
+%BEGINCODE%\r
+Product p = new Product();\r
+List<Product> restock = db.from(p).where(p.unitsInStock).is(0).select();\r
+List<Product> all = db.executeQuery(Product.class, "select * from products");\r
+%ENDCODE%\r
+\r
+</td><td>\r
+<br/>\r
+select * from products p where p.unitsInStock = 0<br/>\r
+select * from products\r
+</td>\r
+</tr>\r
+</table>\r
+\r
+### Supported Databases (Unit-Tested)\r
+- [H2](http://h2database.com) ${h2.version}\r
+- [HSQLDB](http://hsqldb.org) ${hsqldb.version}\r
+- [Derby](http://db.apache.org/derby) ${derby.version}\r
+- [MySQL](http://mysql.com) ${mysql.version}\r
+- [PostgreSQL](http://postgresql.org) ${postgresql.version}\r
+\r
+Support for others is possible and may only require creating a simple "dialect" class.\r
+\r
+### Java Runtime Requirement\r
+\r
+iciql requires a Java 6 Runtime Environment (JRE) or a Java 6 Development Kit (JDK).\r
\r
+### License\r
+iciql is distributed under the terms of the [Apache Software Foundation license, version 2.0][apachelicense]\r
+\r
+[jaqu]: http://h2database.com/html/jaqu.html "H2 JaQu project"\r
+[orm]: http://en.wikipedia.org/wiki/Object-relational_mapping "Object Relational Mapping"\r
+[jooq]: http://jooq.sourceforge.net "jOOQ"\r
+[querydsl]: http://source.mysema.com/display/querydsl/Querydsl "Querydsl"\r
+[hibernate]: http://www.hibernate.org "Hibernate"\r
+[mybatis]: http://www.mybatis.org "mybatis"\r
+[github]: http://github.com/gitblit/iciql "iciql git repository"\r
+[googlecode]: http://code.google.com/p/iciql "iciql project management"\r
+[apachelicense]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0"
\ No newline at end of file
diff --git a/src/site/jaqu_comparison.mkd b/src/site/jaqu_comparison.mkd
new file mode 100644 (file)
index 0000000..20df5d5
--- /dev/null
@@ -0,0 +1,31 @@
+\r
+## Comparison to JaQu \r
+\r
+This is an overview of the fundamental differences between the original JaQu project and the current featureset of iciql.  \r
+\r
+<table class="table">\r
+<tr><th></th><th>Iciql</th><th>JaQu</th></tr>\r
+<tr><th colspan="3">core</th></tr>\r
+<tr><td>deployment</td><td>small, discrete library</td><td>depends on H2 database jar file</td></tr>\r
+<tr><td>databases</td><td>H2, HSQL, Derby, MySQL, and PostreSQL</td><td>H2 only</td></tr>\r
+<tr><td>logging</td><td>console, SLF4J, or custom logging</td><td>console logging</td></tr>\r
+<tr><td>exceptions</td><td>always includes generated statement in exception, when available</td><td>--</td></tr>\r
+<tr><td>column mappings</td><td>wildcard queries index result sets by column name</td><td>all result sets built by field index<br/>this can fail for wildcard queries</td></tr>\r
+<tr><td>savepoints</td><td>bulk operations (insert, update, delete) use savepoints with rollback in the event of failure</td><td>--</td></tr>\r
+<tr><th colspan="3">syntax and api</th></tr>\r
+<tr><td>VIEWs</td><td>create readonly views either from a class definition or from a fluent statement</td><td>--</td></tr>\r
+<tr><td>dynamic queries</td><td>methods and where clauses for dynamic queries that build iciql objects</td><td>--</td></tr>\r
+<tr><td>DROP</td><td>syntax to drop a table or view</td><td></td></tr>\r
+<tr><td>BETWEEN</td><td>syntax for specifying a BETWEEN x AND y clause</td><td>--</td></tr>\r
+<tr><th colspan="3">types</th></tr>\r
+<tr><td>primitives</td><td>fully supported</td><td>--</td></tr>\r
+<tr><td>enums</td><td>fully supported</td><td>--</td></tr>\r
+<tr><td>DECIMAL(length,scale)</td><td>can specify length/precision and scale</td><td>--</td></tr>\r
+<tr><td>BOOLEAN</td><td>flexible mapping of boolean as bool, varchar, or int</td><td>--</td></tr>\r
+<tr><td>BLOB</td><td>partially supported <em>(can not be used in a WHERE clause)</em></td><td>--</td></tr>\r
+<tr><td>UUID</td><td>fully supported <em>(H2 only)</em> </td><td>--</td></tr>\r
+<tr><th colspan="3">configuration</th></tr>\r
+<tr><td>DEFAULT values</td><td>set from annotation, <em>default object values</em>, or Define.defaultValue()</td><td>set from annotations</td></tr>\r
+<tr><td>Interface Configuration<br/>Mapped Fields</td><td><em>all fields</em> are mapped regardless of scope<br/>fields are ignored by annotating with @IQIgnore</td><td><em>all public fields</em> are mapped<br/>fields are ignored by reducing their scope</td></tr>\r
+<tr><td>Index names</td><td>can be set</td><td>--</td></tr>\r
+</table>
\ No newline at end of file
diff --git a/src/site/javadoc.mkd b/src/site/javadoc.mkd
new file mode 100644 (file)
index 0000000..0d0f161
--- /dev/null
@@ -0,0 +1,7 @@
+<div class="javadoc_nav">\r
+<a href="javadoc/overview-summary.html" target="javadoc">packages</a>\r
+ | <a href="javadoc/overview-tree.html" target="javadoc">tree</a>\r
+ | <a href="javadoc/deprecated-list.html" target="javadoc">deprecated</a>\r
+ | <a href="javadoc/index-all.html" target="javadoc">index</a>\r
+</div>\r
+<iframe name="javadoc" src="javadoc/overview-summary.html" width="100%" height="650" frameborder="0"></iframe>\r
diff --git a/src/site/model_classes.mkd b/src/site/model_classes.mkd
new file mode 100644 (file)
index 0000000..8fedf18
--- /dev/null
@@ -0,0 +1,335 @@
+## Model Classes\r
+A model class represents a single table within your database.  Fields within your model class represent columns in the table.  The object types of your fields are reflectively mapped to SQL types by iciql at runtime.\r
+\r
+Models can be manually written using one of three approaches: *annotation configuration*, *interface configuration*, or *POJO configuration*.  All approaches can be used within a project and all can be used within a single model class, although that is discouraged.\r
+\r
+Alternatively, model classes can be automatically generated by iciql using the model generation tool.  Please see the [tools](tools.html) page for details.\r
+\r
+### Configuration Requirements and Limitations\r
+\r
+1. Your model class **must** provide a public default constructor.\r
+2. All **Object** fields are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)* or *Define.nullable(field, false)*.\r
+3. All **Primitive** fields are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)* or *Define.nullable(field, true)*.\r
+4. Only the specified types are supported.  Any other types are not supported.\r
+5. Triggers, views, and other advanced database features are not supported.\r
+\r
+### Supported Data Types\r
+\r
+---NOMARKDOWN---\r
+<table class="table">\r
+<tr><td colspan="3"><b>Fully Supported Types</b><br/>\r
+can be used for all iciql expressions\r
+</tr>\r
+<tr><th>Object</th><th>Primitive</th><th>SQL Type</th></tr>\r
+<tr><td>java.lang.String</td><td></td>\r
+<td>VARCHAR <em>(length > 0)</em> or CLOB <em>(length == 0)</em></td></tr>\r
+       \r
+<tr><td>java.lang.Boolean</td><td>boolean</td>\r
+<td>BOOLEAN<br/><i>can only <b>declare and explicitly reference</b> one <u>primitive boolean</u> per model<br/>multiple primitives are allowed if not using where/set/on/and/or/groupBy/orderBy(boolean)</i></td></tr>\r
+       \r
+<tr><td>java.lang.Byte</td><td>byte</td>\r
+<td>TINYINT</td></tr>\r
+       \r
+<tr><td>java.lang.Short</td><td>short</td>\r
+<td>SMALLINT</td></tr>\r
+       \r
+<tr><td>java.lang.Integer</td><td>int</td>\r
+<td>INT</td></tr>\r
+       \r
+<tr><td>java.lang.Long</td><td>long</td>\r
+<td>BIGINT</td></tr>\r
+       \r
+<tr><td>java.lang.Float</td><td>float</td>\r
+<td>REAL</td></tr>\r
+       \r
+<tr><td>java.lang.Double</td><td>double</td>\r
+<td>DOUBLE</td></tr>\r
+       \r
+<tr><td>java.math.BigDecimal</td><td> </td>\r
+<td>DECIMAL <em>(length == 0)</em> or DECIMAL(length,scale) <em>(length > 0)</em></td></tr>\r
+       \r
+<tr><td>java.sql.Date</td><td> </td>\r
+<td>DATE</td></tr>\r
+       \r
+<tr><td>java.sql.Time</td><td> </td>\r
+<td>TIME</td></tr>\r
+       \r
+<tr><td>java.sql.Timestamp</td><td> </td>\r
+<td>TIMESTAMP</td></tr>\r
+\r
+<tr><td>java.util.Date</td><td> </td>\r
+<td>TIMESTAMP</td></tr>\r
+\r
+<tr><td>java.lang.Enum.name()<br/><em>default type</em></td><td></td>\r
+<td>VARCHAR <em>(length > 0)</em> or CLOB <em>(length == 0)</em><br/><em>EnumType.NAME</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
+\r
+<tr><td>java.lang.Enum.ordinal()</td><td> </td>\r
+<td>INT<br/><em>EnumType.ORDINAL</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
+\r
+<tr><td>java.lang.Enum implements<br/><em>com.iciql.Iciql.EnumId.enumId()</em></td><td> </td>\r
+<td>INT<br/><em>EnumType.ENUMID</em><br/><i>can only <b>declare and explicitly reference</b> one instance of <u>each enum type</u> per model<br/>multiple instances of an enum type within a model is allowed if not using where/set/on/and/or/groupBy/orderBy(enum)</i></td></tr>\r
+\r
+<tr><td colspan="3"><b>Partially Supported Types</b><br/>\r
+can not be directly referenced in an expression</td></tr>\r
+<tr><td>byte []</td> <td></td>\r
+<td>BLOB</td><tr/>\r
+\r
+<tr><td colspan="3"><b>H2 Database Types</b><br/>\r
+fully supported when paired with an H2 database \r
+</td></tr>\r
+<tr><td>java.util.UUID</td><td> </td>\r
+<td>UUID</td></tr>\r
+\r
+</table>\r
+---NOMARKDOWN---\r
+**NOTE:**<br/>\r
+The reverse lookup used for model generation, SQL type -> Java type, contains more mappings.<br/>\r
+Please consult the `com.iciql.ModelUtils` class for details. \r
+\r
+## Annotation Configuration\r
+The recommended approach to setup a model class is to annotate the class and field declarations.\r
+\r
+### advantages\r
+\r
+- annotated models support annotated field inheritance making it possible to design a single base class that defines the fields and then create table subclasses that specify the table mappings.\r
+- model runtime dependency is limited to the small, portable `com.iciql.Iciql` class file which contains the annotation definitions\r
+\r
+### disadvantages\r
+\r
+- more verbose model classes\r
+- indexes are defined using "fragile" string column names\r
+- compound primary keys are defined using "fragile" string column names\r
+\r
+### field mapping\r
+\r
+- By default, **ONLY** fields annotated with *@IQColumn* are mapped.\r
+- scope is irrelevant.\r
+- transient is irrelevant.\r
+\r
+### default values\r
+\r
+You may specify default values for an *@IQColumn* by either:\r
+\r
+1. specifying the default value string within your annotation<br/>\r
+**NOTE:**<br/>\r
+The annotated default value always takes priority over a field default value.\r
+%BEGINCODE%\r
+// notice the single ticks!\r
+@IQColumn(defaultValue="'2000-01-01 00:00:00'")\r
+Date myDate;\r
+%ENDCODE%\r
+\r
+2. setting a default value on the field<br/>\r
+**NOTE:**<br/>\r
+Primitive types have an implicit default value of *0* or *false*.\r
+%BEGINCODE%\r
+@IQColumn\r
+Date myDate = new Date(100, 0, 1);\r
+\r
+@IQColumn\r
+int myId;\r
+%ENDCODE%\r
+\r
+If you want to specify a database-specific variable or function as your default value (e.g. CURRENT_TIMESTAMP) you must do that within the annotation.  Also note that the *IQColumn.defaultValue* must be a well-formatted SQL DEFAULT expression whereas object defaults will be automatically converted to an SQL DEFAULT expression.\r
+\r
+### Special Case: primitive autoincrement fields and 0\r
+%BEGINCODE%\r
+@IQColumn(autoIncrement = true)\r
+int myId;\r
+%ENDCODE%\r
+\r
+Because primitive types have implicit default values, this field will be excluded from an INSERT statement if its value is 0.  Iciql can not differentiate an implicit/uninitialized 0 from a explicitly assigned 0.\r
+\r
+### Example Annotated Model\r
+%BEGINCODE%\r
+import com.iciql.Iciql.EnumType;\r
+import com.iciql.Iciql.IQColumn;\r
+import com.iciql.Iciql.IQEnum;\r
+import com.iciql.Iciql.IQIndex;\r
+import com.iciql.Iciql.IQTable;\r
+\r
+@IQTable\r
+@IQIndexes({\r
+  @IQIndex({"productName", "category"}),\r
+  @IQIndex(name="nameindex", value="productName")\r
+})\r
+public class Product {\r
+\r
+       @IQEnum(EnumType.ORDINAL)\r
+       public enum Availability {\r
+               ACTIVE, DISCONTINUED;\r
+       }\r
+\r
+       @IQColumn(primaryKey = true)\r
+       public Integer productId;\r
+      \r
+       @IQColumn(length = 200, trim = true)\r
+       public String productName;\r
+      \r
+       @IQColumn(length = 50, trim = true)\r
+       public String category;\r
+      \r
+       @IQColumn\r
+       public Double unitPrice;\r
+      \r
+       @IQColumn(name = "units")\r
+       public Integer unitsInStock;\r
+      \r
+       @IQColumn\r
+       private Integer reorderQuantity;\r
+       \r
+       @IQColumn\r
+       private Availability availability;\r
+       \r
+       // ignored because it is not annotated AND the class is @IQTable annotated\r
+       private Integer ignoredField;\r
+      \r
+       public Product() {\r
+               // default constructor\r
+       }\r
+}\r
+%ENDCODE%\r
+\r
+## Interface Configuration\r
+Alternatively, you may map your model classes using the interface approach by implementing the `com.iciql.Iciql` interface.\r
+\r
+This is a less verbose configuration style, but it comes at the expense of introducing a compile-time dependency on the logic of the iciql library.  This might be a deterrent, for example, if you were serializing your model classes to another process that may not have the iciql library.\r
+\r
+The `com.iciql.Iciql` interface specifies a single method, *defineIQ()*.  In your implementation of *defineIQ()* you would use static method calls to set:\r
+\r
+- the schema name\r
+- the table name (if it's not the class name)\r
+- the column name (if it's not the field name)\r
+- the max length and trim of a string field\r
+- the precision and scale of a decimal field\r
+- the autoincrement flag of a long or integer field\r
+- the nullable flag of a field \r
+- the primaryKey (single field or compound)\r
+- any indexes (single field or compound)\r
+\r
+### advantages\r
+\r
+- less verbose model class\r
+- compile-time index definitions\r
+- compile-time compound primary key definitions\r
+\r
+### disadvantages\r
+\r
+- model runtime dependency on entire iciql library\r
+- *defineIQ()* is called from a static synchronized block which may be a bottleneck for highly concurrent systems\r
+\r
+### field mapping\r
+\r
+- **ALL** fields are mapped unless annotated with *@IQIgnore*.\r
+- scope is irrelevant.\r
+- transient is irrelevant.\r
+\r
+### default values\r
+\r
+You may specify default values for an field by either:\r
+\r
+1. specifying the default value string within your *defineIQ()* method<br/>\r
+**NOTE:**<br/>\r
+The defineIQ() value always takes priority over a field default value.\r
+%BEGINCODE%\r
+Date myDate;\r
+\r
+public void defineIQ() {\r
+    // notice the single ticks!\r
+    Define.defaultValue(myDate, "'2000-01-01 00:00:00'");\r
+}\r
+%ENDCODE%\r
+\r
+2. setting a default value on the field<br/>\r
+**NOTE:**<br/>\r
+Primitive types have an implicit default value of *0* or *false*.\r
+%BEGINCODE%\r
+Date myDate = new Date(100, 0, 1);\r
+\r
+int myId;\r
+%ENDCODE%\r
+\r
+### Example Interface Model\r
+%BEGINCODE%\r
+import com.iciql.Iciql;\r
+import com.iciql.Iciql.IQIgnore;\r
+\r
+public class Product implements Iciql {\r
+       public Integer productId;\r
+       public String productName;\r
+       public String category;\r
+       public Double unitPrice;\r
+       public Integer unitsInStock;\r
+       \r
+       @IQIgnore\r
+       Integer reorderQuantity;\r
+      \r
+       public Product() {\r
+       }\r
+      \r
+       @Override\r
+       public void defineIQ() {\r
+               com.iciql.Define.primaryKey(productId);\r
+               com.iciql.Define.columnName(unitsInStock, "units");\r
+               com.iciql.Define.length(productName, 200);\r
+               com.iciql.Define.length(category, 50);\r
+               com.iciql.Define.index(productName, category);\r
+       }\r
+}\r
+%ENDCODE%\r
+\r
+\r
+## POJO (Plain Old Java Object) Configuration\r
+\r
+This approach is very similar to the *interface configuration* approach; it is the least verbose and also the least useful.\r
+\r
+This approach would be suitable for quickly modeling an existing table where only SELECT and INSERT statements will be generated.\r
+\r
+### advantages\r
+\r
+- nearly zero-configuration\r
+\r
+### disadvantages\r
+\r
+- can not execute DELETE, UPDATE, or MERGE statements (they require a primary key specification)\r
+- table name MUST MATCH model class name\r
+- column names MUST MATCH model field names\r
+- can not specify any column attributes\r
+- can not specify indexes\r
+\r
+### field mapping\r
+\r
+- **ALL** fields are mapped unless annotated with *@IQIgnore*.\r
+- scope is irrelevant.\r
+- transient is irrelevant.\r
+\r
+### default values\r
+\r
+You may specify a default value on the field.\r
+\r
+**NOTE:**<br/>\r
+Primitive types have an implicit default value of *0* or *false*.\r
+%BEGINCODE%\r
+Date myDate = new Date(100, 0, 1);\r
+\r
+int myId;\r
+%ENDCODE%\r
+\r
+### Example POJO Model\r
+%BEGINCODE%\r
+import com.iciql.Iciql.IQIgnore;\r
+\r
+public class Product {\r
+       public Integer productId;\r
+       public String productName;\r
+       public String category;\r
+       public Double unitPrice;\r
+       public Integer units;\r
+       \r
+       @IQIgnore\r
+       Integer reorderQuantity;\r
+      \r
+       public Product() {\r
+       }   \r
+}\r
+%ENDCODE%
\ No newline at end of file
diff --git a/src/site/performance.mkd b/src/site/performance.mkd
new file mode 100644 (file)
index 0000000..34e545c
--- /dev/null
@@ -0,0 +1,22 @@
+\r
+## Performance\r
+\r
+The information provided here may be based on flawed test procedures.  You have to be the judge of what is performant and non-performant.\r
+\r
+### iciql statement generation\r
+\r
+Performance of iciql statement generation is not currently benchmarked.\r
+\r
+### iciql+database performance comparison\r
+\r
+The following data was generated by running the *single-threaded* iciql test suite.  All database connections are pooled and re-used within each execution of the test suite using [Apache Commons DBCP](http://commons.apache.org/dbcp).\r
+\r
+Connections are pooled to normalize embedded database performance with out-of-process database performance.  Some of the Java embedded database configurations have a very high startup-time penalty.  Notably, H2 is slow to open a database and its performance is substantially affected if connection pooling is not enabled to keep the embedded database open.\r
+\r
+All tables are created as CACHED when the database distinguishes between CACHED and MEMORY tables.\r
+  \r
+All performance numbers include the combined overhead of iciql statement generation and JUnit 4 test framework execution so they are not bare-metal database metrics.  \r
+\r
+<pre>\r
+%DBPERFORMANCE%\r
+</pre>
\ No newline at end of file
diff --git a/src/site/table_versioning.mkd b/src/site/table_versioning.mkd
new file mode 100644 (file)
index 0000000..2e95aaa
--- /dev/null
@@ -0,0 +1,29 @@
+## Database & Table Versioning\r
+\r
+Iciql supports an optional, simple versioning mechanism.  There are two parts to the mechanism.\r
+\r
+1. You must supply an implementation of `com.iciql.DbUpgrader` to your `com.iciql.Db` instance.\r
+2. One or more of your table model classes must specify the `IQVersion(version)` annotation<br/>\r
+AND/OR<br/>\r
+Your `com.iciql.DbUpgrader` implementation must specify the `IQVersion(version)` annotation\r
+\r
+### How does it work?\r
+If you choose to use versioning, iciql will maintain a table within your database named *iq_versions* which is defined as:\r
+\r
+    CREATE TABLE IQ_VERSIONS(SCHEMANAME VARCHAR(255) NOT NULL, TABLENAME VARCHAR(255) NOT NULL, VERSION INT NOT NULL)\r
+    \r
+This database table is automatically created if and only if at least one of your model classes specifies a *version* > 0.\r
+\r
+When you generate a statement, iciql will compare the annotated version field of your model class to its last known value in the *iq_versions* table.  If *iq_versions* lags behind the model annotation, iciql will immediately call the registered `com.iciql.DbUpgrader` implementation before generating and executing the current statement.\r
+\r
+When an upgrade scenario is identified, the current version and the annotated version information is passed to either:\r
+\r
+- `DbUpgrader.upgradeDatabase(db, fromVersion, toVersion)`\r
+- `DbUpgrader.upgradeTable(db, schema, table, fromVersion, toVersion)`\r
+\r
+both of which allow for non-linear upgrades.  If the upgrade method call is successful and returns *true*, iciql will update the *iq_versions* table with the annotated version number.\r
+\r
+The actual upgrade procedure is beyond the scope of iciql and is your responsibility to implement.  This is simply a mechanism to automatically identify when an upgrade is necessary.\r
+\r
+**NOTE:**<br/>\r
+The database entry of the *iq_versions* table is specified as SCHEMANAME='' and TABLENAME=''.
\ No newline at end of file
diff --git a/src/site/templates/atom.ftl b/src/site/templates/atom.ftl
new file mode 100644 (file)
index 0000000..06d28da
--- /dev/null
@@ -0,0 +1,2 @@
+<#include "macros.ftl">\r
+<@AtomMacro posts=releases posturl="${project.url}/history.html#" />
\ No newline at end of file
diff --git a/src/site/templates/macros.ftl b/src/site/templates/macros.ftl
new file mode 100644 (file)
index 0000000..e7c275b
--- /dev/null
@@ -0,0 +1,147 @@
+<#macro LogMacro title version date description log logTitle="">\r
+       <#if log??>\r
+       <h3 id="${version}" class="section"><a href="#${version}" class="sectionlink"><i class="icon-share-alt"> </i></a>${title} (${version}) <small>${description}</small></h3>\r
+       <table class="table">\r
+               <tbody>\r
+                       <tr>\r
+                               <td style="background-color:inherit;width:100px">${date}</td>\r
+                               <td style="background-color:inherit;"><@LogDescriptionMacro log=log title=logTitle /></td>\r
+                       </tr>\r
+               </tbody>\r
+       </table>\r
+       </#if>\r
+</#macro>\r
+\r
+<#macro LogDescriptionMacro log title=log.title>\r
+       <#if (title!?length > 0)>\r
+               <p class="lead">${title}</p>            \r
+       </#if>\r
+       \r
+       <#if (log.html!?length > 0)>\r
+               <p>${log.html}</p>\r
+       </#if>\r
+       \r
+       <#if (log.text!?length > 0)>\r
+               <blockquote><p>${log.text!?html?replace("\n", "<br />")}</p></blockquote>               \r
+       </#if>\r
+\r
+       <#if (log.note!?length > 0)>\r
+               <div class="alert alert-info">\r
+                       <h4>Note</h4>\r
+                       ${log.note?html?replace("\n", "<p />")}\r
+               </div>\r
+       </#if>\r
+\r
+       <#if (log.security!?size > 0)>\r
+               <@SecurityListMacro title="security" list=log.security/>\r
+       </#if>\r
+       <#if (log.fixes!?size > 0)>\r
+               <@UnorderedListMacro title="fixes" list=log.fixes />\r
+       </#if>\r
+       <#if (log.changes!?size > 0)>\r
+               <@UnorderedListMacro title="changes" list=log.changes />\r
+       </#if>\r
+       <#if (log.additions!?size > 0)>\r
+               <@UnorderedListMacro title="additions" list=log.additions />\r
+       </#if>\r
+       <#if (log.settings!?size > 0)>\r
+               <@SettingsTableMacro title="new settings" list=log.settings />          \r
+       </#if>\r
+       <#if (log.dependencyChanges!?size > 0)>\r
+               <@UnorderedListMacro title="dependency changes" list=log.dependencyChanges />\r
+       </#if>\r
+       <#if (log.contributors!?size > 0)>\r
+               <@UnorderedListMacro title="contributors" list=log.contributors?sort />\r
+       </#if>  \r
+</#macro>\r
+\r
+<#macro SecurityListMacro list title>\r
+       <h4 style="color:red;">${title}</h4>\r
+       <ul>\r
+       <#list list as item>\r
+               <li>${item?html?replace("\n", "<br/>")}</li>\r
+       </#list>\r
+       </ul>\r
+</#macro>\r
+\r
+<#macro UnorderedListMacro list title>\r
+       <h4>${title}</h4>\r
+       <ul>\r
+       <#list list as item>\r
+               <li>${item?html?replace("\n", "<br/>")}</li>\r
+       </#list>\r
+       </ul>\r
+</#macro>\r
+\r
+<#macro SettingsTableMacro list title>\r
+       <h4>${title}</h4>\r
+       <table class="table">\r
+               <#list list as item>\r
+               <tr>\r
+                       <td><em>${item.name}</em></td><td>${item.defaultValue}</td>\r
+               </tr>\r
+               </#list>\r
+       </table>\r
+</#macro>\r
+\r
+<#macro RssMacro posts posturl>\r
+<?xml version="1.0" standalone='yes'?>\r
+<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\r
+       <channel>\r
+               <title><![CDATA[${project.name}]]></title>\r
+               <link>${project.url}</link>\r
+               <description><![CDATA[${project.description}]]></description>\r
+               <generator>Moxie Toolkit</generator>\r
+               <#list posts as post>\r
+               <item>\r
+               <title><![CDATA[${post.title}]]></title>\r
+               <link><![CDATA[${posturl}${post.id}]]></link>\r
+               <guid isPermaLink="true">${posturl}${post.id}</guid>\r
+                       <#if (post.text!?length > 0)>\r
+               <description><![CDATA[${post.text}]]></description>\r
+               </#if>\r
+               <#if (post.keywords!?size > 0)>\r
+                       <#list post.keywords as keyword>\r
+                       <category><![CDATA[${keyword}]]></category>\r
+                       </#list>\r
+               </#if>\r
+               <#if (post.author!?length > 0)>\r
+                       <dc:creator><![CDATA[${post.author}]]></dc:creator>\r
+               <#else>\r
+                       <dc:creator><![CDATA[${project.name}]]></dc:creator>\r
+               </#if>\r
+               <pubDate>${post.date?string("EEE, dd MMM yyyy HH:mm:ss Z")}</pubDate>\r
+               </item>\r
+               </#list>\r
+       </channel>\r
+</rss>\r
+</#macro>\r
+\r
+<#macro AtomMacro posts posturl>\r
+<?xml version="1.0" standalone='yes'?>\r
+<feed xmlns="http://www.w3.org/2005/Atom">\r
+       <generator uri="${project.url}" version="${project.version}">${project.name}</generator>\r
+       <title><![CDATA[${project.name}]]></title>\r
+       <updated>${project.releaseDate}</updated>\r
+       <#list posts as post>\r
+       <entry>\r
+               <content type="text/plain" />\r
+               <title type="text"><![CDATA[${post.title}]]></title>\r
+               <#if (post.text!?length > 0)>\r
+               <summary type="text"><![CDATA[${post.text}]]></summary>\r
+               </#if>\r
+               <link href="${posturl}${post.id}" rel="via" />\r
+               <guid isPermaLink="true">${posturl}${post.id}</guid>\r
+               <#if (post.text!?length > 0)>\r
+               <content><![CDATA[${post.text}]]></content>\r
+               </#if>\r
+               <#if (post.keywords!?size > 0)>\r
+               <#list post.keywords as keyword>\r
+               <category label="<![CDATA[${keyword}]]>" />\r
+               </#list>\r
+               </#if>\r
+               <published>${post.date?string("yyyy-MM-dd'T'HH:mm:ssZ")}</published>\r
+       </entry>\r
+       </#list>\r
+</feed>\r
+</#macro>
\ No newline at end of file
diff --git a/src/site/templates/releasecurrent.ftl b/src/site/templates/releasecurrent.ftl
new file mode 100644 (file)
index 0000000..3bfd709
--- /dev/null
@@ -0,0 +1,25 @@
+<#include "macros.ftl" >
+
+<!-- CURRENT RELEASE -->
+<@LogMacro 
+       title="Current Release"
+       log=release 
+       version=project.releaseVersion 
+       date=reference.releaseDate?string("yyyy-MM-dd") 
+       description="this is the current stable release" />
+
+<!-- NEXT RELEASE -->
+<#if snapshot??>
+<@LogMacro 
+       title="Next Release"
+       log=snapshot
+       version=project.version
+       date="PENDING"
+       description="these changes are queued for an upcoming release" />
+</#if>
+
+<div>
+       <ul class="pager">
+               <li class="next"><a href="releases.html">All Releases &rarr;</a></li>
+       </ul>
+</div>
diff --git a/src/site/templates/releasehistory.ftl b/src/site/templates/releasehistory.ftl
new file mode 100644 (file)
index 0000000..eaaaad2
--- /dev/null
@@ -0,0 +1,21 @@
+<#include "macros.ftl" >
+
+<!-- HISTORY -->
+<#if (releases!?size > 0)>
+       <p></p>
+       <h2>All Releases</h2>
+       <table class="table">
+               <tbody>
+               <!-- RELEASE HISTORY -->
+               <#list releases?sort_by("date")?reverse as log>
+               <tr id="${log.id}">
+                       <td style="width:100px" id="${log.id}">
+                               <b><a href="#${log.id}">${log.id}</a></b><br/>
+                               ${log.date?string("yyyy-MM-dd")}
+                       </td>
+                       <td><@LogDescriptionMacro log=log /></td>
+               </tr>
+               </#list>
+               </tbody>
+       </table>
+</#if>
\ No newline at end of file
diff --git a/src/site/templates/rss.ftl b/src/site/templates/rss.ftl
new file mode 100644 (file)
index 0000000..90e86eb
--- /dev/null
@@ -0,0 +1,2 @@
+<#include "macros.ftl">\r
+<@RssMacro posts=releases posturl="${project.url}/releases.html#" />
\ No newline at end of file
diff --git a/src/site/tools.mkd b/src/site/tools.mkd
new file mode 100644 (file)
index 0000000..6d8c348
--- /dev/null
@@ -0,0 +1,95 @@
+## Model Generation\r
+If you do not have or do not want to annotate your existing model classes, you can use the included model generation tool to create iciql model classes.\r
+\r
+    java -jar iciql.jar <parameters>\r
+\r
+### Parameters\r
+<table class="table">\r
+<tr><th>-url</th><td>JDBC url for the database</td><td><em>REQUIRED</em></td></tr>\r
+<tr><th>-username</th><td>username for JDBC connection</td><td><em>optional</em></td></tr>\r
+<tr><th>-password</th><td>password for JDBC connection</td><td><em>optional</em></td></tr>\r
+<tr><th>-schema</th><td>the target schema for model generation</td><td><em>default:</em> all schemas</td></tr>\r
+<tr><th>-table</th><td>the target table for model generation</td><td><em>default:</em> all tables</td></tr>\r
+<tr><th>-package</th><td>the destination package name for generated models</td><td><em>default:</em> default package</td></tr>\r
+<tr><th>-folder</th><td>the output folder for .java files</td><td><em>default:</em> current folder</td></tr>\r
+<tr><th>-annotateSchema</th><td>include the schema name in the class annotations</td><td><em>default:</em> true</td></tr>\r
+<tr><th>-trimStrings</th><td>annotate trimStrings=true for any VARCHAR string mappings &nbsp; </td><td><em>default:</em> false</td></tr>\r
+</table>\r
+\r
+## Model Validation\r
+Iciql can validate your model classes against your database to ensure that your models are optimally defined and are consistent with the current table and index definitions.\r
+\r
+Each `com.iciql.ValidationRemark` returned by the validation has an associated level from the following enum:\r
+%BEGINCODE%\r
+public static enum Level {\r
+       CONSIDER, WARN, ERROR;\r
+}\r
+%ENDCODE%\r
+\r
+A typical validation may output recommendations for adjusting a model field annotation such as setting the *maxLength* of a string to match the length of its linked VARCHAR column.\r
+\r
+### Sample Model Validation using JUnit 4\r
+%BEGINCODE%\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.sql.SQLException;\r
+\r
+import org.junit.After;\r
+import org.junit.Before;\r
+import org.junit.Rule;\r
+import org.junit.Test;\r
+import org.junit.rules.ErrorCollector;\r
+\r
+import com.iciql.Db;\r
+import com.iciql.DbInspector;\r
+import com.iciql.ValidationRemark;\r
+import com.iciql.test.models.Product;\r
+import com.iciql.test.models.ProductAnnotationOnly;\r
+import com.iciql.test.models.ProductMixedAnnotation;\r
+\r
+public class ValidateModels {\r
+\r
+       /*\r
+        * The ErrorCollector Rule allows execution of a test to continue after the\r
+        * first problem is found and report them all at once\r
+        */\r
+       @Rule\r
+       public ErrorCollector errorCollector = new ErrorCollector();\r
+       \r
+       private Db db;\r
+       \r
+       @Before\r
+       public void setUp() {\r
+               db = Db.open("jdbc:h2:mem:", "sa", "sa");\r
+       }\r
+\r
+       @After\r
+       public void tearDown() {\r
+               db.close();\r
+       }\r
+       \r
+       @Test\r
+       public void testValidateModels() {\r
+               DbInspector inspector = new DbInspector(db);\r
+               validateModel(inspector, new Product());\r
+               validateModel(inspector, new ProductAnnotationOnly());\r
+               validateModel(inspector, new ProductMixedAnnotation());\r
+       }\r
+       \r
+       private void validateModel(DbInspector inspector, Object o) {\r
+               List<ValidationRemark> remarks = inspector.validateModel(o, false);\r
+               assertTrue("Validation remarks are null for " + o.getClass().getName(), remarks != null);\r
+               log("Validation remarks for " + o.getClass().getName());\r
+               for (ValidationRemark remark : remarks) {\r
+                       log(remark.toString());\r
+                       if (remark.isError()) {\r
+                               errorCollector.addError(new SQLException(remark.toString()));\r
+                       }\r
+               }\r
+       }\r
+       \r
+       private void log(String message) {\r
+               System.out.println(message);\r
+       }\r
+}\r
+%ENDCODE%
\ No newline at end of file
diff --git a/src/site/usage.mkd b/src/site/usage.mkd
new file mode 100644 (file)
index 0000000..7b9d89d
--- /dev/null
@@ -0,0 +1,197 @@
+## Usage\r
+\r
+Aside from this brief usage guide, please consult the [examples](examples.html), the [javadoc](javadoc.html) and the [source code](${project.scmUrl}).\r
+\r
+### Instantiating a Db\r
+\r
+Use one of the static utility methods to instantiate a Db instance:\r
+\r
+    Db.open(String url, String user, String password);\r
+    Db.open(String url, String user, char[] password);\r
+    Db.open(Connection conn);\r
+    Db.open(DataSource dataSource);\r
\r
+### Compile-Time Statements\r
+\r
+You compose your statements using the builder pattern where each method call returns an object that is used to specify the next part of the statement.  Through clever usage of generics, pioneered by the original JaQu project, compile-time safety flows through the statement.\r
+\r
+%BEGINCODE%\r
+Db db = Db.open("jdbc:h2:mem:", "sa", "sa");\r
+db.insertAll(Product.getList());\r
+db.insertAll(Customer.getList());\r
+\r
+List<Product> restock =\r
+       db.from(p).\r
+       where(p.unitsInStock).\r
+       is(0).orderBy(p.productId).select();\r
+               \r
+for (Product product : restock) {\r
+       db.from(p).\r
+       set(p.unitsInStock).to(25).\r
+       where(p.productId).is(product.productId).update();\r
+}\r
+db.close();\r
+%ENDCODE%\r
\r
+Please see the [examples](examples.html) page for more code samples. \r
\r
+### Dynamic Runtime Queries\r
+\r
+Iciql gives you compile-time type-safety, but it becomes inconvenient if your design requires more dynamic statement generation.  For these scenarios iciql offers some runtime query support through a hybrid approach or a pure JDBC approach.\r
+\r
+#### Where String Fragment Approach\r
+This approach is a mixture of iciql and jdbc.  It uses the traditional prepared statement *field=?* tokens with iciql compile-time model class type checking.  There is no field token type-safety checking.\r
+%BEGINCODE%\r
+List<Product> restock = db.from(p).where("unitsInStock=? and productName like ? order by productId", 0, "Chef%").select();\r
+%ENDCODE%\r
+\r
+#### Db.executeQuery Approaches\r
+There may be times when the hybrid approach is still too restrictive and you'd prefer to write straight SQL.  You can do that too and use iciql to build objects from your ResultSet, but be careful:\r
+\r
+1. Make sure to _select *_ in your query otherwise db.buildObjects() will throw a RuntimeException\r
+2. There is no model class type checking nor field type checking. \r
+\r
+%BEGINCODE%\r
+List<Product> allProducts = db.executeQuery(Product.class, "select * from products");\r
+List<Product> restock = db.executeQuery(Product.class, "select * from products where unitsInStock=?", 0);\r
+\r
+// parameterized query which can be cached and re-used later\r
+String q = db.from(p).where(p.unitsInStock).isParameter().toSQL();\r
+List<Product> restock = db.executeQuery(Product.class, q, 0);\r
+\r
+%ENDCODE% \r
+\r
+Or if you want access to the raw *ResultSet* before building your model object instances...\r
+\r
+%BEGINCODE%\r
+ResultSet rs = db.executeQuery("select * from products");\r
+List<Product> allProducts = db.buildObjects(Product.class, rs);\r
+// This method ensures the creating statement is closed\r
+JdbcUtils.closeSilently(rs, true);\r
+%ENDCODE% \r
+\r
+### Natural Syntax\r
+\r
+<span class="warning">work-in-progress</span>\r
+\r
+The original JaQu source offers partial support for Java expressions in *where* clauses.\r
+\r
+This works by decompiling a Java expression, at runtime, to an SQL condition.  The expression is written as an anonymous inner class implementation of the `com.iciql.Filter` interface.\r
+A proof-of-concept decompiler is included, but is incomplete.\r
+\r
+The proposed syntax is:\r
+%BEGINCODE%\r
+long count = db.from(co).\r
+    where(new Filter() { public boolean where() {\r
+        return co.id == x\r
+            && co.name.equals(name)\r
+            && co.value == new BigDecimal("1")\r
+            && co.amount == 1L\r
+            && co.birthday.before(new java.util.Date())\r
+            && co.created.before(java.sql.Timestamp.valueOf("2005-05-05 05:05:05"))\r
+            && co.time.before(java.sql.Time.valueOf("23:23:23"));\r
+        }\r
+    }).selectCount();\r
+%ENDCODE%\r
+\r
+### JDBC Statements, ResultSets, and Exception Handling\r
+\r
+Iciql opens and closes all JDBC objects automatically.  SQLExceptions thrown during execution of a statement (except for *close()* calls), will be caught, wrapped, and rethrown as an `IciqlException`, which is a RuntimeException.\r
+\r
+Iciql does not throw any [checked exceptions](http://en.wikipedia.org/wiki/Exception_handling#Checked_exceptions).\r
+\r
+### Statement Logging\r
+\r
+Iciql provides a mechanism to log generated statements and warnings to the console, to SLF4J, or to your own logging framework.  Exceptions are not logged using this mechanism; exceptions are wrapped and rethrown as `IciqlException`, which is a RuntimeException.\r
+\r
+#### Console Logging\r
+%BEGINCODE%\r
+IciqlLogger.activeConsoleLogger();\r
+IciqlLogger.deactiveConsoleLogger();\r
+%ENDCODE%\r
+\r
+#### SLF4J Logging\r
+%BEGINCODE%\r
+Slf4jIciqlListener slf4j = new Slf4jIciqlListener();\r
+slf4j.setLevel(StatementType.CREATE, Level.WARN);\r
+slf4j.setLevel(StatementType.DELETE, Level.WARN);\r
+slf4j.setLevel(StatementType.MERGE, Level.OFF);\r
+IciqlLogger.registerListener(slf4j);\r
+IciqlLogger.unregisterListener(slf4j);\r
+%ENDCODE%\r
+\r
+#### Custom Logging\r
+%BEGINCODE%\r
+IciqlListener custom = new IciqlListener() {\r
+    public void logIciql(StatementType type, String statement) {\r
+        // do log\r
+    }\r
+};\r
+IciqlLogger.registerListener(custom);\r
+IciqlLogger.unregisterListener(custom);\r
+%ENDCODE%\r
+\r
+## Understanding Aliases and Model Classes\r
+Consider the following example:\r
+%BEGINCODE%\r
+Product p = new Product();\r
+List<Product> restock = db.from(p).where(p.unitsInStock).is(0).select();\r
+%ENDCODE%\r
+\r
+The Product model class instance named **p** is an *alias* object.  An *alias* is simply an instance of your model class that is only used to build the compile-time/runtime representation of your table.\r
+\r
+1. *Alias* instances are **NOT** thread-safe and must not be used concurrently.\r
+2. *Alias* instances have no other purpose than to provide a compile-time/runtime map of your table.\r
+3. If you inspected an *alias* instance after using one you would find that it's fields have been assigned numeric values.<br/>These values are assigned from a static counter in `com.iciql.Utils.newObject()` during execution of the *db.from()* method.<p/>For *Object* fields, these values are meaningless since objects are mapped by reference.<br/>For *Primitive* fields these values do matter because primitives are mapped by value.  The proper alias is selected as long as the primitive variant methods are used.  e.g. db.from(p).where(int).is(Integer).select()\r
+\r
+If your statement is a query, like in the above example, iciql will generate new instances of your *alias* model class and return them as a list where each entry of the list represents a row from the JDBC `ResultSet`.\r
\r
+### Why are Aliases not thread-safe?\r
+\r
+The _db.from(p)_ call reinstantiates each member field of p.  Those reinstantiated fields are then subsequently used in clauses like _where(p.unitsInStock)_.  If your *alias* instance is shared concurrently then its highly probable that when _queryA_ executes, _queryC_ has reinstantiated all the *alias* fields and broken _queryA's_ runtime field mapping.\r
+\r
+Depending on your design, you might consider using a [ThreadLocal](http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html) variable if you do not want to keep instantiating *alias* instances.  A utility function is included for easily creating ThreadLocal variables.\r
+\r
+%BEGINCODE%\r
+final ThreadLocal<Product> p = Utils.newThreadLocal(Product.class);\r
+db.from(p.get()).select();\r
+%ENDCODE%\r
+\r
+## Best Practices\r
+\r
+1. Close your *Db* instances when you are done with them, this closes the underlying connection or directs the pool to "close" the connection.\r
+2. Aliases instances are not thread-safe so DO NOT SHARE an alias!<br/>Consider using a *ThreadLocal* alias instance with the `com.iciql.Utils.newThreadLocal()` utility method.\r
+\r
+<p/>\r
+<table class="table">\r
+<tr><th>Not Thread-Safe</th><th>Thread-Safe</th></tr>\r
+<tr><td>\r
+%BEGINCODE%\r
+final Product p = new Product();\r
+for (int i = 0; i < 5; i++) {\r
+    Thread thread = new Thread(new Runnable() {\r
+        public void run() {\r
+            // from(p) reinstantiates p's fields\r
+            db.from(p).select();\r
+        }\r
+    }, "Thread-" + i);\r
+    thread.start();\r
+}\r
+%ENDCODE%\r
+\r
+</td><td>\r
+%BEGINCODE%\r
+final ThreadLocal<Product> p = Utils.newThreadLocal(Product.class);\r
+for (int i = 0; i < 5; i++) {\r
+    Thread thread = new Thread(new Runnable() {\r
+        public void run() {\r
+            // a unique p for this thread            \r
+            db.from(p.get()).select();\r
+        }\r
+    }, "Thread-" + i);\r
+    thread.start();\r
+}\r
+%ENDCODE%\r
+\r
+</td></tr>\r
+</table>
\ No newline at end of file