예제 #1
0
        protected override void DoCompile()
        {
            var node = Schema.Source;

            m_All = new RDBMSEntity(null, node, RDBMSEntityType.Schema, node.AttrByName(NAME_ATTR).ValueAsString("schema"));
            TransformEntityName(m_All);
            base.DoCompile();
        }
예제 #2
0
        /// <summary>
        /// Override to map a name from schema into the name that should be used in the output (i.e. real table name)
        /// </summary>
        public virtual void TransformEntityName(RDBMSEntity entity)
        {
            var name       = entity.OriginalName;
            var parentName = entity.ParentEntity != null ? "{0}_".Args(entity.ParentEntity.TransformedShortName) : string.Empty;

            if (entity.EntityType == RDBMSEntityType.PrimaryKey || entity.EntityType == RDBMSEntityType.Reference)
            {
                var parentParentName = entity.ParentEntity != null && entity.ParentEntity.ParentEntity != null ? "{0}_".Args(entity.ParentEntity.ParentEntity.TransformedShortName) : string.Empty;
                parentName = entity.ParentEntity.EntityType == RDBMSEntityType.Column ? parentParentName : parentName;
            }


            string result = entity.OriginalName;

            switch (entity.EntityType)
            {
            case RDBMSEntityType.Table:       { result = "tbl_" + name;    break; }

            case RDBMSEntityType.Column:      { result = name;             break; }

            case RDBMSEntityType.Domain:      { result = name;             break; }

            case RDBMSEntityType.PrimaryKey:  { result = "pk_" + parentName + name;  break; }

            case RDBMSEntityType.Index:       { result = "idx_" + parentName + name; break; }

            case RDBMSEntityType.Trigger:     { result = "trg_" + parentName + name; break; }

            case RDBMSEntityType.View:        { result = "viw_" + name;            break; }

            case RDBMSEntityType.StoreProc:   { result = "sp_" + name;             break; }

            case RDBMSEntityType.CheckConstraint:  { result = "cc_" + name;             break; }

            case RDBMSEntityType.Reference:   { result = "fk_" + parentName + name;  break; }
            }

            entity.TransformedName      = result;
            entity.TransformedShortName = entity.OriginalShortName;

            if (entity.TransformedShortName.IsNullOrWhiteSpace())
            {
                entity.TransformedShortName = entity.TransformedName;
            }

            if (NameCaseSensitivity == NameCaseSensitivity.ToUpper)
            {
                entity.TransformedName      = entity.TransformedName.ToUpperInvariant();
                entity.TransformedShortName = entity.TransformedShortName.ToUpperInvariant();
            }
            else if (NameCaseSensitivity == NameCaseSensitivity.ToLower)
            {
                entity.TransformedName      = entity.TransformedName.ToLowerInvariant();
                entity.TransformedShortName = entity.TransformedShortName.ToLowerInvariant();
            }
        }
예제 #3
0
        public override void TransformEntityName(RDBMSEntity entity)
        {
            base.TransformEntityName(entity);

            if (entity.EntityType == RDBMSEntityType.Column)
            {
                entity.TransformedName      = entity.TransformedName.ToUpperInvariant();
                entity.TransformedShortName = entity.TransformedShortName.ToUpperInvariant();
            }
        }
예제 #4
0
        /// <summary>
        /// Override to read primary key definition form sub-section of table (not column level)
        /// </summary>
        protected virtual void DoReadPrimaryKeySection(IConfigSectionNode pkNode, RDBMSEntity table)
        {
            var keyName = pkNode.Value;

            if (keyName.IsNullOrWhiteSpace())
            {
                keyName = "PRIMARY";
            }
            var pKey = new RDBMSEntity(table, pkNode, RDBMSEntityType.PrimaryKey, keyName);

            TransformEntityName(pKey);
        }
예제 #5
0
        /// <summary>
        /// Override to read primary key definition form sub-section of table (not column level)
        /// </summary>
        protected virtual void DoReadIndexSection(IConfigSectionNode idxNode, RDBMSEntity table)
        {
            var idxName = idxNode.Value;

            if (idxName.IsNullOrWhiteSpace())
            {
                m_CompileErrors.Add(new SchemaCompilationException(idxNode.RootPath,
                                                                   "Table '{0}' declares an index without a name '{1}'".Args(table.OriginalName, idxNode.RootPath)));
                return;
            }
            var idx = new RDBMSEntity(table, idxNode, RDBMSEntityType.Index, idxName);

            TransformEntityName(idx);
        }
예제 #6
0
        public RDBMSEntity(RDBMSEntity parentEntity, IConfigNode sourceNode, RDBMSEntityType entityType, string originalName, string originalShortName = null, string transformedName = null, string transformedShortName = null)
        {
            if (parentEntity != null)
            {
                parentEntity.Children.Add(this);
            }

            ParentEntity         = parentEntity;
            SourceNode           = sourceNode;
            EntityType           = entityType;
            OriginalName         = originalName;
            OriginalShortName    = originalShortName;
            TransformedName      = transformedName;
            TransformedShortName = transformedShortName;
        }
예제 #7
0
        /// <summary>
        /// Override to outpur foreign keys
        /// </summary>
        protected virtual void DoForeignKeys(RDBMSEntity table, StringBuilder sb, ref bool firstItem, Outputs outputs)
        {
            var tableLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Reference);


            var columnLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Column)
                                  .SelectMany(col => col.Children)
                                  .Where(c => c.EntityType == RDBMSEntityType.Reference);


            var allKeys = tableLevelKeys.Concat(columnLevelKeys);


            foreach (var fke in allKeys)
            {
                var rt = ((IConfigSectionNode)fke.SourceNode).AttrByName(TABLE_SECTION).Value;
                var rc = ((IConfigSectionNode)fke.SourceNode).AttrByName(COLUMN_SECTION).Value;

                if (rt.IsNullOrWhiteSpace() || rc.IsNullOrWhiteSpace())
                {
                    m_CompileErrors.Add(new SchemaCompilationException(fke.SourceNode.RootPath,
                                                                       "Both table and column names are required for reference '{0}' table section '{1}'".Args(table.OriginalName, fke.SourceNode.Name)));
                    continue;
                }

                var refTable = new RDBMSEntity(null, null, RDBMSEntityType.Table, rt);
                TransformEntityName(refTable);

                var refColumn = new RDBMSEntity(refTable, null, RDBMSEntityType.Column, rc);
                TransformEntityName(refColumn);


                var refTableWasAltreadyDeclared = m_All.Children.Any(t => t.EntityType == RDBMSEntityType.Table && refTable.OriginalName.Equals(t.OriginalName, NameComparison));

                var useAlterStatement = !refTableWasAltreadyDeclared || m_SeparateForeignKeys;

                var constraint = TransformKeywordCase("  constraint {0} foreign key ({1}) references {2}({3})")
                                 .Args(
                    GetQuotedIdentifierName(RDBMSEntityType.Reference, fke.TransformedName),
                    GetQuotedIdentifierName(RDBMSEntityType.Column, fke.ParentEntity.TransformedName),
                    GetQuotedIdentifierName(RDBMSEntityType.Table, refTable.TransformedName),
                    GetQuotedIdentifierName(RDBMSEntityType.Column, refColumn.TransformedName)
                    );


                if (useAlterStatement)
                {
                    var ksb = outputs[RDBMSCompiler.FOREIGN_KEYS_OUTPUT];
                    ksb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Reference, true));

                    ksb.AppendLine(TransformKeywordCase("  alter table {0} add {1}")
                                   .Args(
                                       GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName),
                                       constraint
                                       )
                                   );

                    ksb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Reference, false));
                }
                else
                {
                    if (!firstItem)
                    {
                        sb.AppendLine(",");
                    }
                    sb.Append(constraint);
                    firstItem = false;
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Override to output primary keys
        /// </summary>
        protected virtual void DoPrimaryKeys(RDBMSEntity table, StringBuilder sb, ref bool firstItem)
        {
            var tableLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.PrimaryKey);


            var columnLevelKeys = table.Children.Where(c => c.EntityType == RDBMSEntityType.Column)
                                  .SelectMany(col => col.Children)
                                  .Where(c => c.EntityType == RDBMSEntityType.PrimaryKey);


            var allKeys = tableLevelKeys.Concat(columnLevelKeys);

            var pk = allKeys.FirstOrDefault();

            if (pk == null)
            {
                return;
            }
            if (allKeys.Count() > 1)
            {
                m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath,
                                                                   "Table '{0}' defines more than one primary key. Only first on '{1}' is used"
                                                                   .Args(table.OriginalName, pk.ParentEntity.OriginalName)));
            }



            if (pk.ParentEntity.EntityType == RDBMSEntityType.Column)
            {
                if (!firstItem)
                {
                    sb.AppendLine(",");
                }
                sb.Append(TransformKeywordCase("  constraint {0} primary key ({1})")
                          .Args(
                              GetQuotedIdentifierName(RDBMSEntityType.PrimaryKey, pk.TransformedName),
                              GetQuotedIdentifierName(RDBMSEntityType.Column, pk.ParentEntity.TransformedName)
                              )
                          );
            }
            else    //table
            {
                var colNames = new List <string>();
                foreach (var col in ((ConfigSectionNode)pk.SourceNode).Children.Where(c => c.IsSameName(COLUMN_SECTION)))
                {
                    var cn     = col.Value;
                    var column = table.Children.FirstOrDefault(c => c.EntityType == RDBMSEntityType.Column && c.OriginalName.Equals(cn, NameComparison));
                    if (column == null)
                    {
                        m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath,
                                                                           "Table '{0}' defines primary key which references column by name '{1}' which does not exist"
                                                                           .Args(table.OriginalName, cn)));
                        return;
                    }

                    colNames.Add(GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName));
                }

                var colNamesLine = string.Join(", ", colNames);

                if (!firstItem)
                {
                    sb.AppendLine(",");
                }
                sb.Append(TransformKeywordCase("  constraint {0} primary key ({1})")
                          .Args(
                              GetQuotedIdentifierName(RDBMSEntityType.PrimaryKey, pk.TransformedName),
                              colNamesLine
                              )
                          );
            }

            firstItem = false;
        }
예제 #9
0
        /// <summary>
        /// Override to compile a RDBMS Table
        /// </summary>
        protected virtual void DoColumn(IConfigSectionNode columnNode, RDBMSEntity table, StringBuilder sb, ref bool firstColumn, Outputs outputs)
        {
            var colComment = columnNode.AttrByName(SCRIPT_COMMENT_ATTR).Value;

            if (colComment.IsNotNullOrWhiteSpace())
            {
                sb.AppendLine("  -- {0}".Args(colComment));
            }

            var columnName = columnNode.Value;

            if (columnName.IsNullOrWhiteSpace())
            {
                m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Table '{0}' missing column name.".Args(table.OriginalName)));
                return;
            }

            var column = new RDBMSEntity(table, columnNode, RDBMSEntityType.Column, columnName, columnNode.AttrByName(SHORT_NAME_ATTR).Value ?? columnName);

            TransformEntityName(column);

            var typeNode = columnNode.Navigate(TYPE_ATTR + "|$" + TYPE_ATTR);

            if (typeNode == null || typeNode.VerbatimValue.IsNullOrWhiteSpace())
            {
                m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Column '{0}' missing {1} attribute.".Args(columnName, TYPE_ATTR)));
                return;
            }

            var columnType = typeNode.Value;
            var type       = new RDBMSEntity(column, typeNode, RDBMSEntityType.Domain, columnType);

            TransformEntityName(type);

            var domain = CreateDomain("{0}.{1}::{2}".Args(table.OriginalName, column.OriginalName, type.OriginalName), type.OriginalName, typeNode);

            if (domain == null)
            {
                m_CompileErrors.Add(new SchemaCompilationException(columnNode.RootPath, "Domain could not be created: " + type.TransformedName));
                return;
            }

            domain.TransformColumnName(this, column);

            if (!firstColumn)
            {
                sb.AppendLine(",");
            }

            #region Column Line
            {
                var cn        = GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName);
                var tn        = GetQuotedIdentifierName(RDBMSEntityType.Domain, domain.GetTypeName(this));
                var required  = (domain.GetColumnRequirement(this) ?? false) || columnNode.AttrByName(REQUIRED_ATTR).ValueAsBool();
                var nn        = TransformKeywordCase(GetColumnNullNotNullClause(column, required));
                var auto      = domain.GetColumnAutoGeneratedScript(this, column, outputs);
                var dfltValue = columnNode.AttrByName(DEFAULT_ATTR).Value ?? domain.GetColumnDefaultScript(this, column, outputs);
                var dflt      = dfltValue.IsNotNullOrWhiteSpace()? "{0} {1}".Args(TransformKeywordCase("default"), EscapeString(dfltValue)) : string.Empty;
                var chk       = domain.GetColumnCheckScript(this, column, outputs);
                var cmntValue = columnNode.AttrByName(COMMENT_ATTR).Value;
                var cmnt      = cmntValue.IsNotNullOrWhiteSpace()? "{0} {1}".Args(TransformKeywordCase("comment"), EscapeString(cmntValue)) : string.Empty;
                sb.Append(FormatColumnStatement(cn, tn, nn, auto, dflt, chk, cmnt));
            }
            #endregion

            firstColumn = false;

            foreach (var colSubNode in columnNode.Children)
            {
                if (colSubNode.IsSameName(PRIMARY_KEY_SECTION) || colSubNode.IsSameName(REFERENCE_SECTION))
                {
                    var keyType = colSubNode.IsSameName(PRIMARY_KEY_SECTION) ? RDBMSEntityType.PrimaryKey : RDBMSEntityType.Reference;
                    var keyName = colSubNode.Value;
                    if (keyName.IsNullOrWhiteSpace())
                    {
                        keyName = column.OriginalShortName;
                    }
                    var key = new RDBMSEntity(column, colSubNode, keyType, keyName, colSubNode.AttrByName(SHORT_NAME_ATTR).Value);
                    TransformEntityName(key);
                }
                else if (colSubNode.IsSameName(TYPE_ATTR))
                {
                }                                                   //type may be used as section as well
                else
                {
                    m_CompileErrors.Add(new SchemaCompilationException(colSubNode.RootPath,
                                                                       "Unrecognized item inside '{0}.{1}' column, section '{2}'"
                                                                       .Args(table.OriginalName, columnName, colSubNode.Name)));
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Override to compile a indexes per table
        /// </summary>
        protected virtual void DoTableIndexes(RDBMSEntity table, Outputs outputs)
        {
            var sb = m_SeparateIndexes ? outputs[RDBMSCompiler.INDEXES_OUTPUT] : outputs[RDBMSCompiler.TABLES_OUTPUT];

            var indexes = table.Children.Where(c => c.EntityType == RDBMSEntityType.Index);

            foreach (var idx in indexes)
            {
                var node   = (IConfigSectionNode)idx.SourceNode;
                var unique = node.AttrByName(UNIQUE_ATTR).ValueAsBool();

                var colNames = new List <string>();
                foreach (var col in node.Children.Where(c => c.IsSameName(COLUMN_SECTION)))
                {
                    var cn     = col.Value;
                    var column = table.Children.FirstOrDefault(c => c.EntityType == RDBMSEntityType.Column && c.OriginalName.Equals(cn, NameComparison));
                    if (column == null)
                    {
                        m_CompileErrors.Add(new SchemaCompilationException(table.SourceNode.RootPath,
                                                                           "Table '{0}' defines index '{1}' which references column by name '{2}' which does not exist"
                                                                           .Args(table.OriginalName, idx.OriginalName, cn)));
                        return;
                    }

                    var colName = GetQuotedIdentifierName(RDBMSEntityType.Column, column.TransformedName);

                    var colLen = col.AttrByName(LENGTH_ATTR).ValueAsInt();
                    if (colLen > 0)
                    {
                        colName += "({0})".Args(colLen);
                    }

                    var colOrder = col.AttrByName(ORDER_ATTR).ValueAsEnum <RDBMSSortOrder>();
                    var ord      = TransformSortOrder(colOrder);
                    if (ord.IsNotNullOrWhiteSpace())
                    {
                        colName = "{0} {1}".Args(colName, ord);
                    }

                    colNames.Add(colName);
                }

                var colNamesLine = string.Join(", ", colNames);

                var comment       = node.AttrByName(COMMENT_ATTR).Value;
                var commentClause = comment.IsNullOrWhiteSpace()? string.Empty :
                                    TransformKeywordCase(" comment {0}").Args(EscapeString(comment));

                sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Index, true));

                sb.Append(TransformKeywordCase("  create {0} index {1} on {2}({3}){4}")
                          .Args(
                              TransformKeywordCase(unique?"unique":string.Empty),
                              GetQuotedIdentifierName(RDBMSEntityType.Index, idx.TransformedName),
                              GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName),
                              colNamesLine,
                              commentClause
                              )
                          );

                sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Index, false));
            }
        }
예제 #11
0
        /// <summary>
        /// Override to compile a RDBMS Table
        /// </summary>
        protected virtual void DoTable(IConfigSectionNode tableNode, Outputs outputs)
        {
            var tname = tableNode.Value;

            if (tname.IsNullOrWhiteSpace())
            {
                m_CompileErrors.Add(new SchemaCompilationException(tableNode.RootPath, "Table name missing"));
                return;
            }

            var table = new RDBMSEntity(m_All, tableNode, RDBMSEntityType.Table, tname, tableNode.AttrByName(SHORT_NAME_ATTR).Value);

            TransformEntityName(table);


            var sb = outputs[RDBMSCompiler.TABLES_OUTPUT];

            sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Table, true));


            sb.AppendLine("-- {0}".Args(tableNode.AttrByName(SCRIPT_COMMENT_ATTR).ValueAsString("Table " + table.TransformedName)));

            sb.AppendLine("{0} {1}".Args(TransformKeywordCase("create table"),
                                         GetQuotedIdentifierName(RDBMSEntityType.Table, table.TransformedName)));
            sb.AppendLine("(");

            var firstItem = true;

            foreach (var node in tableNode.Children)
            {
                if (node.IsSameName(COLUMN_SECTION))
                {
                    DoColumn(node, table, sb, ref firstItem, outputs);
                }
                else if (node.IsSameName(PRIMARY_KEY_SECTION))
                {
                    DoReadPrimaryKeySection(node, table);
                }
                else if (node.IsSameName(INDEX_SECTION))
                {
                    DoReadIndexSection(node, table);
                }
                else if (node.IsSameName(SCRIPT_INCLUDE_SECTION))
                {
                    IncludeScriptFile(node, outputs); sb.AppendLine();
                }
                else if (node.IsSameName(SCRIPT_TEXT_SECTION))
                {
                    IncludeScriptText(node, outputs); sb.AppendLine();
                }
                else
                {
                    m_CompileErrors.Add(new SchemaCompilationException(node.RootPath, "Unrecognized item inside '{0}' table section '{1}'".Args(tname, node.Name)));
                }
            }

            DoPrimaryKeys(table, sb, ref firstItem);
            DoForeignKeys(table, sb, ref firstItem, outputs);

            sb.AppendLine();
            sb.AppendLine(")");

            var comment = tableNode.AttrByName(COMMENT_ATTR).Value;

            if (comment.IsNotNullOrWhiteSpace())
            {
                sb.AppendLine("    {0} = {1}".Args(TransformKeywordCase("comment"),
                                                   EscapeString(comment)));
            }


            sb.AppendLine(GetStatementDelimiterScript(RDBMSEntityType.Table, false));
            sb.AppendLine();

            DoTableIndexes(table, outputs);
        }
예제 #12
0
 public virtual string GetColumnNullNotNullClause(RDBMSEntity column, bool required)
 {
     return(required ? "not null" : string.Empty);
 }