blob: aeb03ae22b228489b2fd851e2a9edce14c703344 [file] [log] [blame]
/*
* Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
* Copyright (c) 2010, Paul Merlin. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.qi4j.entitystore.sql.internal;
import java.util.ArrayList;
import java.util.List;
import org.qi4j.api.injection.scope.This;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sql.generation.api.grammar.builders.modification.DeleteBySearchBuilder;
import org.sql.generation.api.grammar.builders.modification.UpdateBySearchBuilder;
import org.sql.generation.api.grammar.common.SQLStatement;
import org.sql.generation.api.grammar.common.datatypes.SQLDataType;
import org.sql.generation.api.grammar.definition.table.AutoGenerationPolicy;
import org.sql.generation.api.grammar.definition.table.UniqueSpecification;
import org.sql.generation.api.grammar.factories.BooleanFactory;
import org.sql.generation.api.grammar.factories.ColumnsFactory;
import org.sql.generation.api.grammar.factories.DefinitionFactory;
import org.sql.generation.api.grammar.factories.LiteralFactory;
import org.sql.generation.api.grammar.factories.ModificationFactory;
import org.sql.generation.api.grammar.factories.QueryFactory;
import org.sql.generation.api.grammar.factories.TableReferenceFactory;
import org.sql.generation.api.vendor.SQLVendor;
public interface DatabaseSQLStringsBuilder
{
void init();
String[] buildSQLForSchemaCreation();
String[] buildSQLForIndexCreation();
String[] buildSQLForTableCreation();
String buildSQLForSelectAllEntitiesStatement();
String buildSQLForSelectEntityStatement();
String buildSQLForInsertEntityStatement();
String buildSQLForUpdateEntityStatement();
String buildSQLForRemoveEntityStatement();
@SuppressWarnings("PublicInnerClass")
abstract class CommonMixin
implements DatabaseSQLStringsBuilder
{
private static final Logger LOGGER = LoggerFactory.getLogger( DatabaseSQLStringsBuilder.class );
@This
private DatabaseSQLServiceState _state;
private SQLVendor vendor;
private String schemaName;
private String[] schemaCreationSQLs;
private String[] indexCreationSQLs;
private String[] tableCreationSQLs;
private String selectAllEntitiesSQL;
private String selectEntitySQL;
private String insertEntitySQL;
private String updateEntitySQL;
private String removeEntitySQL;
@Override
public void init()
{
this.vendor = this._state.vendor().get();
this.schemaName = this._state.schemaName().get();
this.schemaCreationSQLs = this.toString( this.createSchemaStatements( this.vendor ) );
LOGGER.trace( "SQL for schema creation: {}", this.schemaCreationSQLs );
this.indexCreationSQLs = this.toString( this.createIndicesStatements( this.vendor ) );
LOGGER.trace( "SQL for index creation: {}", this.indexCreationSQLs );
this.tableCreationSQLs = this.toString( this.createTableStatements( this.vendor ) );
LOGGER.trace( "SQL for table creation: {}", this.tableCreationSQLs );
this.selectAllEntitiesSQL = this.vendor.toString( this.createSelectAllEntitiesStatement( this.vendor ) );
LOGGER.trace( "SQL for select all entities: {}", this.selectAllEntitiesSQL );
this.selectEntitySQL = this.vendor.toString( this.createSelectEntityStatement( this.vendor ) );
LOGGER.trace( "SQL for select entity: {}", this.selectEntitySQL );
this.insertEntitySQL = this.vendor.toString( this.createInsertEntityStatement( this.vendor ) );
LOGGER.trace( "SQL for insert entity: {}", this.insertEntitySQL );
this.updateEntitySQL = this.vendor.toString( this.createUpdateEntityStatement( this.vendor ) );
LOGGER.trace( "SQL for update entity: {}", this.updateEntitySQL );
this.removeEntitySQL = this.vendor.toString( this.createRemoveEntityStatement( this.vendor ) );
LOGGER.trace( "SQL for remove entity: {}", this.removeEntitySQL );
}
protected String[] toString( SQLStatement[] stmts )
{
List<String> result = new ArrayList<String>();
if( stmts != null )
{
for( Integer idx = 0; idx < stmts.length; ++idx )
{
SQLStatement statement = stmts[idx];
if( statement != null )
{
String stringStatement = this.vendor.toString( statement );
if( stringStatement != null && stringStatement.length() > 0 )
{
result.add( this.vendor.toString( statement ) );
}
}
}
}
return result.toArray( new String[ result.size() ] );
}
protected SQLVendor getVendor()
{
return this.vendor;
}
protected String getSchemaName()
{
return this.schemaName;
}
protected SQLStatement[] createSchemaStatements( SQLVendor vendor )
{
// @formatter:off
return new SQLStatement[]
{
vendor.getDefinitionFactory().createSchemaDefinitionBuilder()
.setSchemaName( this.schemaName )
.createExpression()
};
// @formatter:on
}
protected SQLStatement[] createIndicesStatements( SQLVendor vendor )
{
// TODO
return new SQLStatement[] {};
}
protected SQLStatement[] createTableStatements( SQLVendor vendor )
{
DefinitionFactory d = vendor.getDefinitionFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
// @formatter:off
return new SQLStatement[]
{
d.createTableDefinitionBuilder()
.setTableName( t.tableName( this.getSchemaName(), SQLs.TABLE_NAME ) )
.setTableContentsSource( d.createTableElementListBuilder()
.addTableElement( d.createColumnDefinition( SQLs.ENTITY_PK_COLUMN_NAME, this.getPKType(), false, AutoGenerationPolicy.BY_DEFAULT ) )
.addTableElement( d.createColumnDefinition( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, this.getOptimisticLockType(), false ) )
.addTableElement( d.createColumnDefinition( SQLs.ENTITY_IDENTITY_COLUMN_NAME, this.getIDType(), false ) )
.addTableElement( d.createColumnDefinition( SQLs.ENTITY_STATE_COLUMN_NAME, this.getStateType(), false ) )
.addTableElement( d.createColumnDefinition( SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME, this.getLastModifiedType(), false ) )
.addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
.setUniqueness( UniqueSpecification.PRIMARY_KEY )
.addColumns( SQLs.ENTITY_PK_COLUMN_NAME )
.createExpression() ) )
.addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
.setUniqueness( UniqueSpecification.UNIQUE )
.addColumns( SQLs.ENTITY_IDENTITY_COLUMN_NAME )
.createExpression() ) )
.createExpression()
)
.createExpression()
};
// @formatter:on
}
protected SQLStatement createSelectAllEntitiesStatement( SQLVendor vendor )
{
QueryFactory q = vendor.getQueryFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
// @formatter:off
return q.simpleQueryBuilder()
.select( SQLs.ENTITY_PK_COLUMN_NAME, SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, SQLs.ENTITY_STATE_COLUMN_NAME )
.from( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
.createExpression();
// @formatter:on
}
protected SQLStatement createSelectEntityStatement( SQLVendor vendor )
{
QueryFactory q = vendor.getQueryFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
BooleanFactory b = vendor.getBooleanFactory();
ColumnsFactory c = vendor.getColumnsFactory();
LiteralFactory l = vendor.getLiteralFactory();
// @formatter:off
return q.simpleQueryBuilder()
.select( SQLs.ENTITY_PK_COLUMN_NAME, SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, SQLs.ENTITY_STATE_COLUMN_NAME )
.from( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
.where( b.eq( c.colName( SQLs.ENTITY_IDENTITY_COLUMN_NAME ), l.param() ) )
.createExpression();
// @formatter:on
}
protected SQLStatement createInsertEntityStatement( SQLVendor vendor )
{
ModificationFactory m = vendor.getModificationFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
LiteralFactory l = vendor.getLiteralFactory();
// @formatter:off
return m.insert()
.setTableName( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
.setColumnSource( m.columnSourceByValues()
.addColumnNames(
SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME,
SQLs.ENTITY_IDENTITY_COLUMN_NAME,
SQLs.ENTITY_STATE_COLUMN_NAME,
SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME
)
.addValues(
l.n( 0 ),
l.param(),
l.param(),
l.param()
)
.createExpression()
)
.createExpression();
// @formatter:on
}
protected SQLStatement createUpdateEntityStatement( SQLVendor vendor )
{
ModificationFactory m = vendor.getModificationFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
LiteralFactory l = vendor.getLiteralFactory();
BooleanFactory b = vendor.getBooleanFactory();
ColumnsFactory c = vendor.getColumnsFactory();
// @formatter:off
UpdateBySearchBuilder builder = m.updateBySearch()
.setTargetTable( m.createTargetTable( t.tableName( this.schemaName, SQLs.TABLE_NAME ) ) )
.addSetClauses(
m.setClause( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, m.updateSourceByExp( l.param() ) ),
m.setClause( SQLs.ENTITY_STATE_COLUMN_NAME, m.updateSourceByExp( l.param() ) ),
m.setClause( SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME, m.updateSourceByExp( l.param() ) )
);
builder
.getWhereBuilder()
.reset( b.eq( c.colName( SQLs.ENTITY_PK_COLUMN_NAME ), l.param() ) )
.and( b.eq( c.colName( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ), l.param() ) );
return builder.createExpression();
// @formatter:on
}
protected SQLStatement createRemoveEntityStatement( SQLVendor vendor )
{
ModificationFactory m = vendor.getModificationFactory();
TableReferenceFactory t = vendor.getTableReferenceFactory();
LiteralFactory l = vendor.getLiteralFactory();
BooleanFactory b = vendor.getBooleanFactory();
ColumnsFactory c = vendor.getColumnsFactory();
// @formatter:off
DeleteBySearchBuilder builder = m.deleteBySearch()
.setTargetTable( m.createTargetTable( t.tableName( this.schemaName, SQLs.TABLE_NAME ) ) );
builder.getWhere()
.reset( b.eq( c.colName( SQLs.ENTITY_PK_COLUMN_NAME ), l.param() ) );
return builder.createExpression();
// @formatter:on
}
protected SQLDataType getPKType()
{
return this.vendor.getDataTypeFactory().bigInt();
}
protected SQLDataType getOptimisticLockType()
{
return this.vendor.getDataTypeFactory().bigInt();
}
protected SQLDataType getIDType()
{
return this.vendor.getDataTypeFactory().sqlVarChar( 64 );
}
protected SQLDataType getStateType()
{
return this.vendor.getDataTypeFactory().sqlVarChar( 10000 );
}
protected SQLDataType getLastModifiedType()
{
return this.vendor.getDataTypeFactory().bigInt();
}
@Override
public String[] buildSQLForSchemaCreation()
{
return this.schemaCreationSQLs;
}
@Override
public String[] buildSQLForIndexCreation()
{
return this.indexCreationSQLs;
}
@Override
public String buildSQLForSelectAllEntitiesStatement()
{
return this.selectAllEntitiesSQL;
}
@Override
public String buildSQLForSelectEntityStatement()
{
return this.selectEntitySQL;
}
@Override
public String buildSQLForInsertEntityStatement()
{
return this.insertEntitySQL;
}
@Override
public String buildSQLForUpdateEntityStatement()
{
return this.updateEntitySQL;
}
@Override
public String buildSQLForRemoveEntityStatement()
{
return this.removeEntitySQL;
}
@Override
public String[] buildSQLForTableCreation()
{
return this.tableCreationSQLs;
}
}
}