private ProcedureSetStatement CreateSetStatement(ProcedureStatement statement, Column column)
        {
            ProcedureExpressionStatement rightExpression = new ProcedureExpressionStatement(statement, column.DefaultValue);

            rightExpression.Function = ProcedureFunctionType.Snippet; // Value will be written as is

            var setStatement = new ProcedureSetStatement(statement, new TableRefColumn(column));

            setStatement.RightExpression = rightExpression;

            return(setStatement);
        }
        private ProcedureSetStatement CreateSetStatement(ProcedureStatement statement, Column column)
        {
            ProcedureExpressionStatement rightExpression = new ProcedureExpressionStatement(statement, column.DefaultValue);
            rightExpression.Function = ProcedureFunctionType.Snippet; // Value will be written as is

            var setStatement = new ProcedureSetStatement(statement, new TableRefColumn(column));
            setStatement.RightExpression = rightExpression;

            return setStatement;
        }
        private void UpdateProcedure(CodeFluent.Model.Persistence.Procedure procedure)
        {
            if (procedure.Table == null || procedure.Table.Entity == null)
            {
                return;
            }

            // Find columns to add to SELECT
            // RowVersion and Identity columns are already part of the SELECT
            var columns = procedure.Table.Entity.Properties
                          .Where(property => property.MustReadOnSave && !property.IsPersistenceIdentity)
                          .SelectMany(property => property.Columns)
                          .Where(column => column != null && !column.IsRowVersion)
                          .ToList();

            var properties = procedure.Table.Entity.Properties
                             .Where(property => property.MustReadOnSave && !property.IsPersistenceIdentity && property.Columns.Count == 0)
                             .ToList();

            if (columns.Count == 0 && properties.Count == 0)
            {
                return;
            }

            // Visit the body of the procedure
            procedure.Body.Visit <ProcedureStatement>(statement =>
            {
                // We need to find a block statement (a list of statements) that looks like
                // INSERT OR UPDATE statement
                // statement (generally IfStatement)
                // SELECT ...

                /*
                 *
                 * -- Statement 1 : ProcedureBlockStatement which contains UPDATE & if(@error)
                 * UPDATE [Login] SET
                 * [Login].[Login_ProviderName] = @Login_ProviderName,
                 * [Login].[_trackLastWriteTime] = GETDATE()
                 *  WHERE (([Login].[Login_Id] = @Login_Id) AND ([Login].[_rowVersion] = @_rowVersion))
                 *
                 * SELECT @error = @@ERROR, @rowcount = @@ROWCOUNT
                 * IF(@error != 0)
                 * BEGIN
                 *  IF @tran = 1 ROLLBACK TRANSACTION
                 *  RETURN
                 * END
                 *
                 * -- Statement 2 : ProcedureIfStatement
                 * IF(@rowcount = 0)
                 * BEGIN
                 *  IF @tran = 1 ROLLBACK TRANSACTION
                 *  RAISERROR (50001, 16, 1, 'Login_Save')
                 *  RETURN
                 * END
                 *
                 * -- Statement 3 : ProcedureSelectStatement
                 * SELECT DISTINCT [Login].[_rowVersion]
                 *  FROM [Login]
                 *  WHERE ([Login].[Login_Id] = @Login_Id)
                 *
                 */


                var blockStatement = statement as ProcedureBlockStatement;
                if (blockStatement == null)
                {
                    return;
                }

                bool insertOrUpdate = false;

                foreach (var s in blockStatement.Statements)
                {
                    if (IsInsertOrUpdateStatement(s))
                    {
                        insertOrUpdate = true;
                    }

                    var selectStatement = s as ProcedureSelectStatement;
                    if (insertOrUpdate && selectStatement != null)    // SELECT statement after INSERT or UPDATE statement
                    {
                        if (IsReadIdentityStatement(selectStatement)) // SELECT DISTINCT @Id = SCOPE_IDENTITY()
                        {
                            continue;
                        }

                        foreach (var column in columns)
                        {
                            var setStatment = new ProcedureSetStatement(selectStatement, new TableRefColumn(column));
                            selectStatement.Set.Add(setStatment);
                        }

                        foreach (var property in properties) // not persistent : select expression AS 'persistent name'
                        {
                            ProcedureExpressionStatement literalExpression = new ProcedureExpressionStatement(selectStatement, ProcedureExpressionStatement.CreateLiteral(GetSelectExpression(property)));
                            var setStatment = new ProcedureSetStatement(selectStatement, literalExpression, (ProcedureExpressionStatement)null, new ProcedureExpressionStatement(selectStatement, property.PersistenceName));
                            selectStatement.Set.Add(setStatment);
                        }
                    }
                }
            });
        }
        private void UpdateProcedure(CodeFluent.Model.Persistence.Procedure procedure)
        {
            if (procedure.Table == null || procedure.Table.Entity == null)
                return;

            // Find columns to add to SELECT
            // RowVersion and Identity columns are already part of the SELECT
            var columns = procedure.Table.Entity.Properties
                .Where(property => property.MustReadOnSave && !property.IsPersistenceIdentity)
                .SelectMany(property => property.Columns)
                .Where(column => column != null && !column.IsRowVersion)
                .ToList();

            var properties = procedure.Table.Entity.Properties
                .Where(property => property.MustReadOnSave && !property.IsPersistenceIdentity && property.Columns.Count == 0)
                .ToList();

            if (columns.Count == 0 && properties.Count == 0)
                return;

            // Visit the body of the procedure
            procedure.Body.Visit<ProcedureStatement>(statement =>
            {
                // We need to find a block statement (a list of statements) that looks like
                // INSERT OR UPDATE statement
                // statement (generally IfStatement)
                // SELECT ...
                
                /*
                 * 
                -- Statement 1 : ProcedureBlockStatement which contains UPDATE & if(@error)
                UPDATE [Login] SET
                 [Login].[Login_ProviderName] = @Login_ProviderName,
                 [Login].[_trackLastWriteTime] = GETDATE()
                    WHERE (([Login].[Login_Id] = @Login_Id) AND ([Login].[_rowVersion] = @_rowVersion))
                
                SELECT @error = @@ERROR, @rowcount = @@ROWCOUNT
                IF(@error != 0)
                BEGIN
                    IF @tran = 1 ROLLBACK TRANSACTION
                    RETURN
                END
                
                -- Statement 2 : ProcedureIfStatement
                IF(@rowcount = 0)
                BEGIN
                    IF @tran = 1 ROLLBACK TRANSACTION
                    RAISERROR (50001, 16, 1, 'Login_Save')
                    RETURN
                END
                
                -- Statement 3 : ProcedureSelectStatement
                SELECT DISTINCT [Login].[_rowVersion] 
                    FROM [Login]
                    WHERE ([Login].[Login_Id] = @Login_Id)
                
                */
                

                var blockStatement = statement as ProcedureBlockStatement;
                if (blockStatement == null)
                    return;

                bool insertOrUpdate = false;

                foreach (var s in blockStatement.Statements)
                {
                    if (IsInsertOrUpdateStatement(s)) 
                    {
                        insertOrUpdate = true;
                    }

                    var selectStatement = s as ProcedureSelectStatement;
                    if (insertOrUpdate && selectStatement != null) // SELECT statement after INSERT or UPDATE statement
                    {
                        if (IsReadIdentityStatement(selectStatement)) // SELECT DISTINCT @Id = SCOPE_IDENTITY() 
                            continue;

                        foreach (var column in columns)
                        {
                            var setStatment = new ProcedureSetStatement(selectStatement, new TableRefColumn(column));
                            selectStatement.Set.Add(setStatment);
                        }

                        foreach (var property in properties) // not persistent : select expression AS 'persistent name'
                        {
                            ProcedureExpressionStatement literalExpression = new ProcedureExpressionStatement(selectStatement, ProcedureExpressionStatement.CreateLiteral(GetSelectExpression(property)));
                            var setStatment = new ProcedureSetStatement(selectStatement, literalExpression, (ProcedureExpressionStatement)null, new ProcedureExpressionStatement(selectStatement, property.PersistenceName));
                            selectStatement.Set.Add(setStatment);
                        }
                    }
                }
            });
        }