#region Apache Notice /***************************************************************************** * $Revision: 408099 $ * $LastChangedDate$ * $LastChangedBy$ * * iBATIS.NET Data Mapper * Copyright (C) 2008/2005 - The Apache Software Foundation * * * 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. * ********************************************************************************/ #endregion using System; using System.Text; using Apache.Ibatis.Common.Configuration; using Apache.Ibatis.Common.Contracts; using Apache.Ibatis.Common.Exceptions; using Apache.Ibatis.DataMapper.Configuration.Interpreters.Config; using Apache.Ibatis.DataMapper.Configuration.Serializers; using Apache.Ibatis.DataMapper.MappedStatements; using Apache.Ibatis.DataMapper.Model.ParameterMapping; using Apache.Ibatis.DataMapper.Model.Sql.Dynamic; using Apache.Ibatis.DataMapper.Model.Sql.Dynamic.Elements; using Apache.Ibatis.DataMapper.Model.Sql.External; using Apache.Ibatis.DataMapper.Model.Sql.SimpleDynamic; using Apache.Ibatis.DataMapper.Model.Sql.Static; using Apache.Ibatis.DataMapper.Model.Statements; using Apache.Ibatis.DataMapper.Session; namespace Apache.Ibatis.DataMapper.Configuration { /// /// This implementation of , builds all statement. /// public partial class DefaultModelBuilder { private readonly InlineParameterMapParser paramParser = new InlineParameterMapParser(); /// /// Builds the mapped statements. /// /// The store. /// private void BuildMappedStatements(IConfigurationStore store, ConfigurationSetting configurationSetting) { for (int i = 0; i < store.Statements.Length; i++) { IConfiguration statementConfig = store.Statements[i]; IMappedStatement mappedStatement = null; switch (statementConfig.Type) { case ConfigConstants.ELEMENT_STATEMENT: mappedStatement = BuildStatement(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_SELECT: mappedStatement = BuildSelect(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_INSERT: mappedStatement = BuildInsert(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_UPDATE: mappedStatement = BuildUpdate(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_DELETE: mappedStatement = BuildDelete(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_PROCEDURE: mappedStatement = BuildProcedure(statementConfig, configurationSetting); break; case ConfigConstants.ELEMENT_SQL: break; default: throw new ConfigurationException("Cannot build the statement, cause invalid statement type '" + statementConfig.Type + "'."); } if (mappedStatement!=null) { modelStore.AddMappedStatement(mappedStatement); } } } /// /// Builds a Mapped Statement for a statement. /// /// The statement. /// The mapped statement. /// private IMappedStatement BuildCachingStatement(IStatement statement, MappedStatement mappedStatement) { IMappedStatement mapStatement = mappedStatement; if (statement.CacheModel != null && isCacheModelsEnabled) { mapStatement = new CachingStatement(mappedStatement); } return mapStatement; } /// /// Builds a for a statement configuration. /// /// The statement config. /// private IMappedStatement BuildStatement(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer statementDeSerializer = new StatementDeSerializer(); IStatement statement = statementDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new MappedStatement(modelStore, statement); return BuildCachingStatement(statement, mappedStatement); } /// /// Builds an for a insert configuration. /// /// The statement config. /// private IMappedStatement BuildInsert(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer insertDeSerializer = new InsertDeSerializer(); IStatement statement = insertDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new InsertMappedStatement(modelStore, statement); Insert insert = (Insert)statement; if (insert.SelectKey != null) { ConfigurationCollection selectKeys = statementConfig.Children.Find(ConfigConstants.ELEMENT_SELECTKEY); IConfiguration selectKeyConfig = selectKeys[0]; ProcessSqlStatement(selectKeyConfig, insert.SelectKey); MappedStatement mapStatement = new MappedStatement(modelStore, insert.SelectKey); modelStore.AddMappedStatement(mapStatement); } return BuildCachingStatement(statement, mappedStatement); } /// /// Builds an for a statement configuration. /// /// The statement config. /// private IMappedStatement BuildUpdate(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer updateDeSerializer = new UpdateDeSerializer(); IStatement statement = updateDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new UpdateMappedStatement(modelStore, statement); return BuildCachingStatement(statement, mappedStatement); } /// /// Builds an for a delete configuration. /// /// The statement config. /// private IMappedStatement BuildDelete(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer deleteDeSerializer = new DeleteDeSerializer(); IStatement statement = deleteDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new DeleteMappedStatement(modelStore, statement); return BuildCachingStatement(statement, mappedStatement); } /// /// Builds an for a select configuration. /// /// The statement config. /// private IMappedStatement BuildSelect(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer selectDeSerializer = new SelectDeSerializer(); IStatement statement = selectDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new SelectMappedStatement(modelStore, statement); return BuildCachingStatement(statement, mappedStatement); } /// /// Builds an for a procedure configuration. /// /// The statement config. /// private IMappedStatement BuildProcedure(IConfiguration statementConfig, ConfigurationSetting configurationSetting) { BaseStatementDeSerializer procedureDeSerializer = new ProcedureDeSerializer(); IStatement statement = procedureDeSerializer.Deserialize(modelStore, statementConfig, configurationSetting); ProcessSqlStatement(statementConfig, statement); MappedStatement mappedStatement = new MappedStatement(modelStore, statement); return BuildCachingStatement(statement, mappedStatement); } /// /// Process the Sql cpmmand text statement (Build ISql) /// /// The statement configuration. /// The statement. private void ProcessSqlStatement(IConfiguration statementConfiguration, IStatement statement) { if(dynamicSqlEngine!=null) { statement.SqlSource = dynamicSqlEngine; } if (statement.SqlSource!=null) { #region sqlSource - external processor string commandText = string.Empty; if (statementConfiguration.Children.Count > 0) { IConfiguration child = statementConfiguration.Children[0]; if (child.Type == ConfigConstants.ELEMENT_TEXT || child.Type == ConfigConstants.ELEMENT_CDATA) { // pass the unformated sql to the external processor commandText = child.Value; } } ExternalSql externalSql = new ExternalSql(modelStore, statement, commandText); statement.Sql = externalSql; #endregion } else { #region default - internal processor bool isDynamic = false; DynamicSql dynamic = new DynamicSql( modelStore.SessionFactory.DataSource.DbProvider.UsePositionalParameters, modelStore.DBHelperParameterCache, modelStore.DataExchangeFactory, statement); StringBuilder sqlBuffer = new StringBuilder(); isDynamic = ParseDynamicTags(statementConfiguration, dynamic, sqlBuffer, isDynamic, false, statement); if (isDynamic) { statement.Sql = dynamic; } else { string sqlText = sqlBuffer.ToString(); string newSqlCommandText = string.Empty; ParameterMap map = inlineParemeterMapBuilder.BuildInlineParemeterMap(statement, sqlText, out newSqlCommandText); if (map != null) { statement.ParameterMap = map; } if (SimpleDynamicSql.IsSimpleDynamicSql(newSqlCommandText)) { statement.Sql = new SimpleDynamicSql( modelStore.DataExchangeFactory, modelStore.DBHelperParameterCache, newSqlCommandText, statement); } else { if (statement is Procedure) { statement.Sql = new ProcedureSql( modelStore.DataExchangeFactory, modelStore.DBHelperParameterCache, newSqlCommandText, statement); // Could not call BuildPreparedStatement for procedure because when NUnit Test // the database is not here (but in theory procedure must be prepared like statement) // It's even better as we can then switch DataSource. } else if (statement is Statement) { statement.Sql = new StaticSql( modelStore.DataExchangeFactory, modelStore.DBHelperParameterCache, statement); // this does not open a connection to the database ISession session = modelStore.SessionFactory.OpenSession(); ((StaticSql)statement.Sql).BuildPreparedStatement(session, newSqlCommandText); session.Close(); } } } #endregion } Contract.Ensure.That(statement.Sql, Is.Not.Null).When("process Sql statement."); } /// /// Parse dynamic tags /// /// The statement config. /// The dynamic. /// The SQL buffer. /// if set to true [is dynamic]. /// if set to true [post parse required]. /// The statement. /// private bool ParseDynamicTags( IConfiguration statementConfig, IDynamicParent dynamic, StringBuilder sqlBuffer, bool isDynamic, bool postParseRequired, IStatement statement) { ConfigurationCollection children = statementConfig.Children; int count = children.Count; for (int i = 0; i < count; i++) { IConfiguration child = children[i]; if (child.Type == ConfigConstants.ELEMENT_TEXT || child.Type == ConfigConstants.ELEMENT_CDATA) { string childValueString = child.Value; if (statement.PreserveWhitespace) { childValueString = childValueString .Replace('\n', ' ') .Replace('\r', ' ') .Replace('\t', ' ') .Trim(); } SqlText sqlText = null; if (postParseRequired) { sqlText = new SqlText(); sqlText.Text = childValueString; } else { sqlText = InlineParameterMapParser.ParseInlineParameterMap(modelStore.DataExchangeFactory, statementConfig.Id, null, childValueString); } dynamic.AddChild(sqlText); sqlBuffer.Append(" " + childValueString); } else if (child.Type == ConfigConstants.ELEMENT_SELECTKEY || child.Type == ConfigConstants.ELEMENT_INCLUDE) { } else { IDeSerializer serializer = deSerializerFactory.GetDeSerializer(child.Type); if (serializer != null) { isDynamic = true; SqlTag tag; tag = serializer.Deserialize(child); dynamic.AddChild(tag); if (child.Children.Count > 0) { isDynamic = ParseDynamicTags(child, tag, sqlBuffer, isDynamic, tag.Handler.IsPostParseRequired, statement); } } } } return isDynamic; } } }