/// <summary>
        /// Parses COMMENT ON INDEX.
        /// </summary>
        private static void ParseIndex(Parser parser, PgDatabase database)
        {
            var indexName = parser.ParseIdentifier();

            var objectName = ParserUtils.GetObjectName(indexName);

            var schemaName = ParserUtils.GetSchemaName(indexName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            PgIndex index = schema.GetIndex(objectName);

            if (index == null)
            {
                PgConstraint primaryKey = schema.GetPrimaryKey(objectName);
                parser.Expect("IS");
                primaryKey.Comment = GetComment(parser);
                parser.Expect(";");
            }
            else
            {
                parser.Expect("IS");
                index.Comment = GetComment(parser);
                parser.Expect(";");
            }
        }
예제 #2
0
        private static void ParseSchema(Parser parser, PgDatabase database)
        {
            var schemaName = ParserUtils.GetObjectName(parser.ParseIdentifier());
            var schema     = database.GetSchema(schemaName);

            parser.Expect("IS");
            schema.Comment = GetComment(parser);
            parser.Expect(";");
        }
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");
            parser.ExpectOptional("OR", "REPLACE");
            parser.Expect("RULE");

            var ruleIdentifier = parser.ParseIdentifier();
            var rule           = new PgRule(ParserUtils.GetObjectName(ruleIdentifier));
            var schemaName     = ParserUtils.GetSchemaName(ruleIdentifier, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            parser.Expect("AS", "ON");
            rule.EventType = parser.ExpectOptionalOneOf("SELECT", "INSERT", "UPDATE", "DELETE");
            parser.Expect("TO");
            var tableIdentifier = parser.ParseIdentifier();

            if (parser.ExpectOptional("WHERE"))
            {
                var endIndex = parser.String.IndexOf("DO");
                rule.Condition = parser.GetSubString(0, endIndex);
            }

            rule.TableName = ParserUtils.GetObjectName(tableIdentifier);

            parser.Expect("DO");
            rule.Do      = parser.ExpectOptionalOneOf("ALSO", "INSTEAD");
            rule.Command = parser.Rest() + ";";

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format("CannotFindSchema {0}. Statement {1}", schemaName, statement));
            }

            // check if the rule is a view
            if (rule.EventType == "SELECT" && rule.Do == "INSTEAD")
            {
                var table = schema.Tables.Single(t => t.Name == rule.TableName);
                schema.Tables.Remove(table);
                schema.Views.Add(new PgView(table.Name)
                {
                    Comment = table.Comment, Query = rule.Command
                });
            }
            else
            {
                schema.Rules.Add(rule);
            }
        }
예제 #4
0
파일: PgDiff.cs 프로젝트: hryz/apgdiff.net
 private static void CreateNewSchemas(TextWriter writer, PgDatabase oldDatabase, PgDatabase newDatabase)
 {
     foreach (var newSchema in newDatabase.Schemas)
     {
         if (oldDatabase.GetSchema(newSchema.Name) == null)
         {
             writer.WriteLine();
             writer.WriteLine(newSchema.GetCreationSql());
         }
     }
 }
예제 #5
0
파일: PgDiff.cs 프로젝트: hryz/apgdiff.net
 private static void DropOldSchemas(TextWriter writer, PgDatabase oldDatabase, PgDatabase newDatabase)
 {
     foreach (var oldSchema in oldDatabase.Schemas)
     {
         if (newDatabase.GetSchema(oldSchema.Name) == null)
         {
             writer.WriteLine();
             writer.WriteLine($"DROP SCHEMA {PgDiffUtils.GetQuotedName(oldSchema.Name)} CASCADE;");
         }
     }
 }
예제 #6
0
        private static void ParseView(Parser parser, PgDatabase database)
        {
            var viewName   = parser.ParseIdentifier();
            var objectName = ParserUtils.GetObjectName(viewName);
            var schemaName = ParserUtils.GetSchemaName(viewName, database);

            var view = database.GetSchema(schemaName).GetView(objectName);

            parser.Expect("IS");
            view.Comment = GetComment(parser);
            parser.Expect(";");
        }
예제 #7
0
        private static void ParseTable(Parser parser, PgDatabase database)
        {
            var tableName  = parser.ParseIdentifier();
            var objectName = ParserUtils.GetObjectName(tableName);
            var schemaName = ParserUtils.GetSchemaName(tableName, database);

            var table = database.GetSchema(schemaName).GetTable(objectName);

            parser.Expect("IS");
            table.Comment = GetComment(parser);
            parser.Expect(";");
        }
        /// <summary>
        /// Parses COMMENT ON COLUMN.
        /// </summary>
        private static void ParseColumn(Parser parser, PgDatabase database)
        {
            var columnName = parser.ParseIdentifier();

            var objectName = ParserUtils.GetObjectName(columnName);

            var tableName = ParserUtils.GetSecondObjectName(columnName);

            var schemaName = ParserUtils.GetThirdObjectName(columnName);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            PgTable table = schema.GetTable(tableName);

            if (table == null)
            {
                PgView view = schema.GetView(tableName);
                parser.Expect("IS");

                var comment = GetComment(parser);

                if (comment == null)
                {
                    view.RemoveColumnComment(objectName);
                }
                else
                {
                    view.AddColumnComment(objectName, comment);
                }

                parser.Expect(";");
            }
            else
            {
                PgColumn column = table.GetColumn(objectName);

                if (column == null)
                {
                    throw new TeamworkParserException($"CannotFindColumnInTable {columnName} from table {table.Name}");
                }

                parser.Expect("IS");
                column.Comment = GetComment(parser);
                parser.Expect(";");
            }
        }
        /// <summary>
        /// Parses ALTER SEQUENCE statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("ALTER", "SEQUENCE");

            var sequenceName = parser.ParseIdentifier();

            var schemaName = ParserUtils.GetSchemaName(sequenceName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            var schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} from statement {statement}");
            }

            var objectName = ParserUtils.GetObjectName(sequenceName);

            PgSequence sequence = schema.GetSequence(objectName);

            if (sequence == null)
            {
                throw new TeamworkParserException($"CannotFindSequence {sequenceName} from statement {statement}");
            }

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("OWNED", "BY"))
                {
                    if (parser.ExpectOptional("NONE"))
                    {
                        sequence.Owner = null;
                    }
                    else
                    {
                        sequence.Owner = parser.Expression();
                    }
                }
                else
                {
                    throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Parses CREATE INDEX statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");

            var unique = parser.ExpectOptional("UNIQUE");

            parser.Expect("INDEX");
            parser.ExpectOptional("CONCURRENTLY");

            var indexName = ParserUtils.GetObjectName(parser.ParseIdentifier());

            parser.Expect("ON");

            var tableName = parser.ParseIdentifier();

            var definition = parser.Rest();

            var schemaName = ParserUtils.GetSchemaName(tableName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} from  {statement}");
            }

            var objectName = ParserUtils.GetObjectName(tableName);

            PgTable table = schema.GetTable(objectName);

            if (table == null)
            {
                throw new TeamworkParserException($"CannotFindTable {tableName} from {statement}");
            }

            var index = new PgIndex(indexName);

            table.AddIndex(index);
            schema.Add(index);
            index.Definition = definition.Trim();
            index.TableName  = table.Name;
            index.Unique     = unique;
        }
예제 #11
0
        /// <summary>
        /// Parses CREATE VIEW statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");
            parser.ExpectOptional("OR", "REPLACE");
            parser.Expect("VIEW");

            var viewName = parser.ParseIdentifier();

            var columnsExist = parser.ExpectOptional("(");

            var columnNames = new List <string>(10);

            if (columnsExist)
            {
                while (!parser.ExpectOptional(")"))
                {
                    columnNames.Add(ParserUtils.GetObjectName(parser.ParseIdentifier()));
                    parser.ExpectOptional(",");
                }
            }

            parser.ExpectOptional("WITH", "(security_barrier='false')");

            parser.Expect("AS");

            var query = parser.Rest();

            var view = new PgView(ParserUtils.GetObjectName(viewName))
            {
                ColumnNames = columnNames,
                Query       = query,
            };
            var schemaName = ParserUtils.GetSchemaName(viewName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} {statement}");
            }

            schema.Add(view);
        }
        private void DropOldSchemas(Database database, StreamWriter writer, PgDatabase oldDatabase, PgDatabase newDatabase)
        {
            foreach (PgSchema oldSchema in oldDatabase.Schemas)
            {
                if (newDatabase.GetSchema(oldSchema.Name) == null)
                {
                    // ignore the ignored schemas
                    if (database.IgnoredSchemas.Contains(oldSchema.Name))
                    {
                        continue;
                    }

                    writer.WriteLine();
                    writer.WriteLine("DROP SCHEMA IF EXISTS " + oldSchema.Name.QuoteName() + " CASCADE;");
                }
            }
        }
        private void CreateNewSchemas(Database database, StreamWriter writer, PgDatabase oldDatabase, PgDatabase newDatabase)
        {
            foreach (PgSchema newSchema in newDatabase.Schemas)
            {
                // ignore the ignored schemas
                if (database.IgnoredSchemas.Contains(newSchema.Name))
                {
                    continue;
                }

                if (oldDatabase.GetSchema(newSchema.Name) == null)
                {
                    writer.WriteLine();
                    writer.WriteLine(newSchema.CreationSQL);
                }
            }
        }
        /// <summary>
        /// Parses COMMENT ON SEQUENCE.
        /// </summary>
        private static void ParseSequence(Parser parser, PgDatabase database)
        {
            var sequenceName = parser.ParseIdentifier();

            var objectName = ParserUtils.GetObjectName(sequenceName);

            var schemaName = ParserUtils.GetSchemaName(sequenceName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSequence sequence = database.GetSchema(schemaName).GetSequence(objectName);

            parser.Expect("IS");
            sequence.Comment = GetComment(parser);
            parser.Expect(";");
        }
예제 #15
0
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");

            var unique = parser.ExpectOptional("UNIQUE");

            parser.Expect("INDEX");
            parser.ExpectOptional("CONCURRENTLY");

            var indexName = ParserUtils.GetObjectName(parser.ParseIdentifier());

            parser.Expect("ON");

            var tableName  = parser.ParseIdentifier();
            var definition = parser.GetRest();
            var schemaName = ParserUtils.GetSchemaName(tableName, database);
            var schema     = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }

            var objectName = ParserUtils.GetObjectName(tableName);
            var table      = schema.GetTable(objectName);

            if (table == null)
            {
                throw new Exception(string.Format(Resources.CannotFindTable, tableName, statement));
            }

            var index = new PgIndex(indexName);

            table.AddIndex(index);
            schema.AddIndex(index);
            index.Definition = definition.Trim();
            index.TableName  = table.Name;
            index.Unique     = unique;
        }
예제 #16
0
        private static void ParseColumn(Parser parser, PgDatabase database)
        {
            var columnName = parser.ParseIdentifier();
            var objectName = ParserUtils.GetObjectName(columnName);
            var tableName  = ParserUtils.GetSecondObjectName(columnName);
            var schemaName = ParserUtils.GetThirdObjectName(columnName);
            var schema     = database.GetSchema(schemaName);

            var table = schema.GetTable(tableName);

            if (table == null)
            {
                var view = schema.GetView(tableName);
                parser.Expect("IS");

                var comment = GetComment(parser);

                if (comment == null)
                {
                    view.RemoveColumnComment(objectName);
                }
                else
                {
                    view.AddColumnComment(objectName, comment);
                }
                parser.Expect(";");
            }
            else
            {
                var column = table.GetColumn(objectName);

                if (column == null)
                {
                    throw new ParserException(string.Format(Resources.CannotFindColumnInTable, columnName, table.Name));
                }

                parser.Expect("IS");
                column.Comment = GetComment(parser);
                parser.Expect(";");
            }
        }
예제 #17
0
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");
            parser.ExpectOptional("OR", "REPLACE");
            parser.Expect("VIEW");

            var viewName = parser.ParseIdentifier();

            var columnsExist = parser.ExpectOptional("(");
            var columnNames  = new List <string>();

            if (columnsExist)
            {
                while (!parser.ExpectOptional(")"))
                {
                    columnNames.Add(ParserUtils.GetObjectName(parser.ParseIdentifier()));
                    parser.ExpectOptional(",");
                }
            }

            parser.Expect("AS");

            var query = parser.GetRest();

            var view = new PgView(ParserUtils.GetObjectName(viewName));

            view.ColumnNames = columnNames;
            view.Query       = query;

            var schemaName = ParserUtils.GetSchemaName(viewName, database);
            var schema     = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }

            schema.AddView(view);
        }
        /// <summary>
        /// Parses COMMENT ON CONSTRAINT.
        /// </summary>
        private static void ParseConstraint(Parser parser, PgDatabase database)
        {
            var constraintName = ParserUtils.GetObjectName(parser.ParseIdentifier());

            parser.Expect("ON");

            var tableName  = parser.ParseIdentifier();
            var objectName = ParserUtils.GetObjectName(tableName);
            var schemaName = ParserUtils.GetSchemaName(constraintName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgConstraint constraint = database.GetSchema(schemaName).GetTable(objectName).GetConstraint(constraintName);

            parser.Expect("IS");
            constraint.Comment = GetComment(parser);
            parser.Expect(";");
        }
예제 #19
0
        public static void Parse(PgDatabase database, string statement, bool outputIgnoredStatements)
        {
            var parser = new Parser(statement);

            parser.Expect("ALTER", "SEQUENCE");

            var sequenceName = parser.ParseIdentifier();
            var schemaName   = ParserUtils.GetSchemaName(sequenceName, database);
            var schema       = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }

            var objectName = ParserUtils.GetObjectName(sequenceName);
            var sequence   = schema.GetSequence(objectName);

            if (sequence == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSequence, sequenceName, statement));
            }


            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("OWNED", "BY"))
                {
                    sequence.OwnedBy = parser.ExpectOptional("NONE")
                        ? null
                        : parser.GetExpression();
                }
                else
                {
                    parser.ThrowUnsupportedCommand();
                }
            }
        }
        /// <summary>
        /// Parses COMMENT ON TRIGGER.
        /// </summary>
        private static void ParseTrigger(Parser parser, PgDatabase database)
        {
            var triggerName = ParserUtils.GetObjectName(parser.ParseIdentifier());

            parser.Expect("ON");

            var tableName = parser.ParseIdentifier();

            var objectName = ParserUtils.GetObjectName(tableName);

            var schemaName = ParserUtils.GetSchemaName(triggerName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgTrigger trigger = database.GetSchema(schemaName).GetTable(objectName).GetTrigger(triggerName);

            parser.Expect("IS");
            trigger.Comment = GetComment(parser);
            parser.Expect(";");
        }
예제 #21
0
        private static void ParseIndex(Parser parser, PgDatabase database)
        {
            var indexName  = parser.ParseIdentifier();
            var objectName = ParserUtils.GetObjectName(indexName);
            var schemaName = ParserUtils.GetSchemaName(indexName, database);
            var schema     = database.GetSchema(schemaName);

            var index = schema.GetIndex(objectName);

            if (index == null)
            {
                var primaryKey = schema.GetPrimaryKey(objectName);
                parser.Expect("IS");
                primaryKey.Comment = GetComment(parser);
                parser.Expect(";");
            }
            else
            {
                parser.Expect("IS");
                index.Comment = GetComment(parser);
                parser.Expect(";");
            }
        }
예제 #22
0
        public static void Parse(PgDatabase database, string statement, bool outputIgnoredStatements)
        {
            var parser = new Parser(statement);

            parser.Expect("ALTER", "VIEW");

            var viewName   = parser.ParseIdentifier();
            var schemaName = ParserUtils.GetSchemaName(viewName, database);
            var schema     = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }


            var objectName = ParserUtils.GetObjectName(viewName);
            var view       = schema.GetView(objectName);

            if (view == null)
            {
                throw new Exception(string.Format(Resources.CannotFindView, viewName, statement));
            }

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("ALTER"))
                {
                    parser.ExpectOptional("COLUMN");

                    var columnName = ParserUtils.GetObjectName(parser.ParseIdentifier());

                    if (parser.ExpectOptional("SET", "DEFAULT"))
                    {
                        var expression = parser.GetExpression();
                        view.AddColumnDefaultValue(columnName, expression);
                    }
                    else if (parser.ExpectOptional("DROP", "DEFAULT"))
                    {
                        view.RemoveColumnDefaultValue(columnName);
                    }
                    else
                    {
                        parser.ThrowUnsupportedCommand();
                    }
                }
                else if (parser.ExpectOptional("OWNER", "TO"))
                {
                    // we do not parse this one so we just consume the identifier
                    if (outputIgnoredStatements)
                    {
                        database.IgnoredStatements.Add($"ALTER TABLE {viewName} OWNER TO {parser.ParseIdentifier()};");
                    }
                    else
                    {
                        parser.ParseIdentifier();
                    }
                }
                else
                {
                    parser.ThrowUnsupportedCommand();
                }
            }
        }
예제 #23
0
        private static void ParseFunction(Parser parser, PgDatabase database)
        {
            var functionName = parser.ParseIdentifier();
            var objectName   = ParserUtils.GetObjectName(functionName);
            var schemaName   = ParserUtils.GetSchemaName(functionName, database);
            var schema       = database.GetSchema(schemaName);

            parser.Expect("(");

            var tmpFunction = new PgFunction();

            tmpFunction.Name = objectName;

            while (!parser.ExpectOptional(")"))
            {
                string mode;

                if (parser.ExpectOptional("IN"))
                {
                    mode = "IN";
                }
                else if (parser.ExpectOptional("OUT"))
                {
                    mode = "OUT";
                }
                else if (parser.ExpectOptional("INOUT"))
                {
                    mode = "INOUT";
                }
                else if (parser.ExpectOptional("VARIADIC"))
                {
                    mode = "VARIADIC";
                }
                else
                {
                    mode = null;
                }

                var    position     = parser.GetPosition();
                string argumentName = null;
                var    dataType     = parser.ParseDataType();

                var position2 = parser.GetPosition();

                if (!parser.ExpectOptional(")") && !parser.ExpectOptional(","))
                {
                    parser.SetPosition(position);
                    argumentName = ParserUtils.GetObjectName(parser.ParseIdentifier());
                    dataType     = parser.ParseDataType();
                }
                else
                {
                    parser.SetPosition(position2);
                }

                var argument = new PgFunction.Argument
                {
                    DataType = dataType,
                    Mode     = mode,
                    Name     = argumentName
                };
                tmpFunction.AddArgument(argument);

                if (parser.ExpectOptional(")"))
                {
                    break;
                }

                parser.Expect(",");
            }

            var function =
                schema.GetFunction(tmpFunction.GetSignature());

            parser.Expect("IS");
            function.Comment = GetComment(parser);
            parser.Expect(";");
        }
예제 #24
0
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE", "SEQUENCE");

            var sequenceName = parser.ParseIdentifier();
            var sequence     = new PgSequence(ParserUtils.GetObjectName(sequenceName));
            var schemaName   = ParserUtils.GetSchemaName(sequenceName, database);
            var schema       = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }

            schema.AddSequence(sequence);

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("INCREMENT"))
                {
                    parser.ExpectOptional("BY");
                    sequence.Increment = parser.ParseString();
                }
                else if (parser.ExpectOptional("MINVALUE"))
                {
                    sequence.MinValue = parser.ParseString();
                }
                else if (parser.ExpectOptional("MAXVALUE"))
                {
                    sequence.MaxValue = parser.ParseString();
                }
                else if (parser.ExpectOptional("START"))
                {
                    parser.ExpectOptional("WITH");
                    sequence.StartWith = parser.ParseString();
                }
                else if (parser.ExpectOptional("CACHE"))
                {
                    sequence.Cache = parser.ParseString();
                }
                else if (parser.ExpectOptional("CYCLE"))
                {
                    sequence.Cycle = true;
                }
                else if (parser.ExpectOptional("OWNED", "BY"))
                {
                    sequence.OwnedBy = parser.ExpectOptional("NONE")
                        ? null
                        : ParserUtils.GetObjectName(parser.ParseIdentifier());
                }
                else if (parser.ExpectOptional("NO"))
                {
                    if (parser.ExpectOptional("MINVALUE"))
                    {
                        sequence.MinValue = null;
                    }
                    else if (parser.ExpectOptional("MAXVALUE"))
                    {
                        sequence.MaxValue = null;
                    }
                    else if (parser.ExpectOptional("CYCLE"))
                    {
                        sequence.Cycle = false;
                    }
                    else
                    {
                        parser.ThrowUnsupportedCommand();
                    }
                }
                else
                {
                    parser.ThrowUnsupportedCommand();
                }
            }
        }
예제 #25
0
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE", "TABLE");

            // Optional IF NOT EXISTS, irrelevant for our purposes
            parser.ExpectOptional("IF", "NOT", "EXISTS");

            var tableName  = parser.ParseIdentifier();
            var table      = new PgTable(ParserUtils.GetObjectName(tableName));
            var schemaName = ParserUtils.GetSchemaName(tableName, database);
            var schema     = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception(string.Format(Resources.CannotFindSchema, schemaName, statement));
            }

            schema.AddTable(table);

            parser.Expect("(");

            while (!parser.ExpectOptional(")"))
            {
                if (parser.ExpectOptional("CONSTRAINT"))
                {
                    ParseConstraint(parser, table);
                }
                else
                {
                    ParseColumn(parser, table);
                }

                if (parser.ExpectOptional(")"))
                {
                    break;
                }

                parser.Expect(",");
            }

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("INHERITS"))
                {
                    ParseInherits(parser, table);
                }
                else if (parser.ExpectOptional("WITHOUT"))
                {
                    table.With = "OIDS=false";
                }
                else if (parser.ExpectOptional("WITH"))
                {
                    if (parser.ExpectOptional("OIDS") || parser.ExpectOptional("OIDS=true"))
                    {
                        table.With = "OIDS=true";
                    }
                    else if (parser.ExpectOptional("OIDS=false"))
                    {
                        table.With = "OIDS=false";
                    }
                    else
                    {
                        table.With = parser.GetExpression();
                    }
                }
                else if (parser.ExpectOptional("TABLESPACE"))
                {
                    table.Tablespace = parser.ParseString();
                }
                else
                {
                    parser.ThrowUnsupportedCommand();
                }
            }
        }
예제 #26
0
        /// <summary>
        /// Parses ALTER TABLE statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement, bool outputIgnoredStatements)
        {
            var parser = new Parser(statement);

            parser.Expect("ALTER", "TABLE");
            parser.ExpectOptional("ONLY");

            var tableName = parser.ParseIdentifier();

            var schemaName = ParserUtils.GetSchemaName(tableName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} from {statement}");
            }

            var objectName = ParserUtils.GetObjectName(tableName);

            PgTable table = schema.GetTable(objectName);

            if (table == null)
            {
                PgView view = schema.GetView(objectName);

                if (view != null)
                {
                    ParseView(parser, view, outputIgnoredStatements, tableName, database);
                    return;
                }

                PgSequence sequence = schema.GetSequence(objectName);

                if (sequence != null)
                {
                    ParseSequence(parser, sequence, outputIgnoredStatements, tableName, database);
                    return;
                }

                throw new TeamworkParserException($"CannotFindObject in {tableName} from {statement}");
            }

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("ALTER"))
                {
                    ParseAlterColumn(parser, table);
                }
                else if (parser.ExpectOptional("CLUSTER", "ON"))
                {
                    table.ClusterIndexName = ParserUtils.GetObjectName(parser.ParseIdentifier());
                }
                else if (parser.ExpectOptional("OWNER", "TO"))
                {
                    // we do not parse this one so we just consume the identifier
                    if (outputIgnoredStatements)
                    {
                        database.AddIgnoredStatement("ALTER TABLE " + tableName + " OWNER TO " + parser.ParseIdentifier() + ';');
                    }
                    else
                    {
                        parser.ParseIdentifier();
                    }
                }
                else if (parser.ExpectOptional("ADD"))
                {
                    if (parser.ExpectOptional("FOREIGN", "KEY"))
                    {
                        ParseAddForeignKey(parser, table);
                    }
                    else if (parser.ExpectOptional("CONSTRAINT"))
                    {
                        ParseAddConstraint(parser, table, schema);
                    }
                    else
                    {
                        throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                    }
                }
                else if (parser.ExpectOptional("ENABLE"))
                {
                    ParseEnable(parser, outputIgnoredStatements, tableName, database);
                }
                else if (parser.ExpectOptional("DISABLE"))
                {
                    ParseDisable(parser, outputIgnoredStatements, tableName, database);
                }
                else if (parser.ExpectOptional("REPLICA IDENTITY"))
                {
                    parser.Expect("NOTHING");
                }
                else
                {
                    throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                }

                if (parser.ExpectOptional(";"))
                {
                    break;
                }
                else
                {
                    parser.Expect(",");
                }
            }
        }
예제 #27
0
        /// <summary>
        /// Parses CREATE SEQUENCE statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE", "SEQUENCE");

            var sequenceName = parser.ParseIdentifier();

            var sequence = new PgSequence(ParserUtils.GetObjectName(sequenceName));

            var schemaName = ParserUtils.GetSchemaName(sequenceName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} from {statement}");
            }

            schema.Add(sequence);

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("INCREMENT"))
                {
                    parser.ExpectOptional("BY");
#pragma warning disable CS0618 // Type or member is obsolete
                    sequence.Increment = parser.ParseStringCompat();
#pragma warning restore CS0618 // Type or member is obsolete
                }
                else if (parser.ExpectOptional("MINVALUE"))
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    sequence.MinValue = parser.ParseStringCompat();
#pragma warning restore CS0618 // Type or member is obsolete
                }
                else if (parser.ExpectOptional("MAXVALUE"))
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    sequence.MaxValue = parser.ParseStringCompat();
#pragma warning restore CS0618 // Type or member is obsolete
                }
                else if (parser.ExpectOptional("START"))
                {
                    parser.ExpectOptional("WITH");
#pragma warning disable CS0618 // Type or member is obsolete
                    sequence.StartWith = parser.ParseStringCompat();
#pragma warning restore CS0618 // Type or member is obsolete
                }
                else if (parser.ExpectOptional("CACHE"))
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    sequence.Cache = parser.ParseStringCompat();
#pragma warning restore CS0618 // Type or member is obsolete
                }
                else if (parser.ExpectOptional("CYCLE"))
                {
                    sequence.Cycle = true;
                }
                else if (parser.ExpectOptional("OWNED", "BY"))
                {
                    if (parser.ExpectOptional("NONE"))
                    {
                        sequence.Owner = null;
                    }
                    else
                    {
                        sequence.Owner = ParserUtils.GetObjectName(parser.ParseIdentifier());
                    }
                }
                else if (parser.ExpectOptional("NO"))
                {
                    if (parser.ExpectOptional("MINVALUE"))
                    {
                        sequence.MinValue = null;
                    }
                    else if (parser.ExpectOptional("MAXVALUE"))
                    {
                        sequence.MaxValue = null;
                    }
                    else if (parser.ExpectOptional("CYCLE"))
                    {
                        sequence.Cycle = false;
                    }
                    else
                    {
                        throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                    }
                }
                else
                {
                    throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                }
            }
        }
예제 #28
0
        public static void Parse(PgDatabase database, string statement, PgPrivilegeCommand command)
        {
            var parser = new Parser(statement);

            parser.Expect(command.ToString().ToUpper());
            var privilegeKind = parser.ExpectOptionalOneOf(enumEntries.Select(k => k.ToString().ToUpper()).ToArray());
            var kind          = enumEntries.Single(k => k.ToString().ToUpper() == privilegeKind);

            parser.Expect("ON");

            var type           = parser.ParseIdentifier().ToUpper();
            var name           = parser.ParseIdentifier();
            var nameWithSchema = name;

            if (parser.ExpectOptional("("))
            {
                name += "(";
                while (!parser.ExpectOptional(")"))
                {
                    var argumentName = ParserUtils.GetObjectName(parser.ParseIdentifier());
                    var dataType     = parser.ParseDataType();
                    name += $"{argumentName} {dataType}";

                    if (parser.ExpectOptional(")"))
                    {
                        break;
                    }
                    else
                    {
                        parser.Expect(",");
                        name += ", ";
                    }
                }

                name += ")";
            }

            switch (command)
            {
            case PgPrivilegeCommand.Grant:
                parser.Expect("TO");
                break;

            case PgPrivilegeCommand.Revoke:
                parser.Expect("FROM");
                break;

            default:
                throw new ArgumentException($"The postgres privilege command {command} is unknown.");
            }

            var role = parser.ParseIdentifier();

            parser.Expect(";");

            var privilege = new PgPrivilege()
            {
                Command   = command,
                Privilege = kind,
                OnType    = type,
                OnName    = name,
                Role      = role,
            };

            var schemaName = ParserUtils.GetSchemaName(nameWithSchema, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            var schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new Exception($"Cannot find schema {schemaName} for statement {statement}.");
            }

            schema.Add(privilege);
        }
예제 #29
0
        /// <summary>
        /// Parses CREATE FUNCTION and CREATE OR REPLACE FUNCTION statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement)
        {
            var parser = new Parser(statement);

            parser.Expect("CREATE");
            parser.ExpectOptional("OR", "REPLACE");
            parser.Expect("FUNCTION");

            var functionName = parser.ParseIdentifier();
            var schemaName   = ParserUtils.GetSchemaName(functionName, database);

            PgSchema schema = database.GetSchema(schemaName);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} {statement}");
            }

            var function = new PgFunction()
            {
                Name = ParserUtils.GetObjectName(functionName),
            };

            schema.Add(function);

            parser.Expect("(");

            while (!parser.ExpectOptional(")"))
            {
                string mode;
                if (parser.ExpectOptional("IN"))
                {
                    mode = "IN";
                }
                else if (parser.ExpectOptional("OUT"))
                {
                    mode = "OUT";
                }
                else if (parser.ExpectOptional("INOUT"))
                {
                    mode = "INOUT";
                }
                else if (parser.ExpectOptional("VARIADIC"))
                {
                    mode = "VARIADIC";
                }
                else
                {
                    mode = null;
                }

                var    position     = parser.Position;
                string argumentName = null;
                var    dataType     = parser.ParseDataType();

                var position2 = parser.Position;

                if (!parser.ExpectOptional(")") && !parser.ExpectOptional(",") && !parser.ExpectOptional("=") && !parser.ExpectOptional("DEFAULT"))
                {
                    parser.Position = position;
                    argumentName    = ParserUtils.GetObjectName(parser.ParseIdentifier());
                    dataType        = parser.ParseDataType();
                }
                else
                {
                    parser.Position = position2;
                }

                string defaultExpression;
                if (parser.ExpectOptional("=") || parser.ExpectOptional("DEFAULT"))
                {
                    defaultExpression = parser.Expression();
                }
                else
                {
                    defaultExpression = null;
                }

                var argument = new PgFunction.Argument()
                {
                    DataType          = dataType,
                    DefaultExpression = defaultExpression,
                    Mode = mode,
                    Name = argumentName,
                };
                function.AddArgument(argument);

                if (parser.ExpectOptional(")"))
                {
                    break;
                }
                else
                {
                    parser.Expect(",");
                }
            }

            function.Body = parser.Rest();
        }
        /// <summary>
        /// Parses ALTER VIEW statement.
        /// </summary>
        public static void Parse(PgDatabase database, string statement, bool outputIgnoredStatements)
        {
            var parser = new Parser(statement);

            parser.Expect("ALTER", "VIEW");

            var viewName = parser.ParseIdentifier();

            var schemaName = ParserUtils.GetSchemaName(viewName, database);

            if (database.SchemaIsIgnored(schemaName))
            {
                return;
            }

            PgSchema schema = database.GetSchema(schemaName);

            if (schema == null)
            {
                throw new TeamworkParserException($"CannotFindSchema {schemaName} from {statement}");
            }

            var objectName = ParserUtils.GetObjectName(viewName);

            PgView view = schema.GetView(objectName);

            if (view == null)
            {
                throw new TeamworkParserException($"CannotFindView {viewName} from {statement}");
            }

            while (!parser.ExpectOptional(";"))
            {
                if (parser.ExpectOptional("ALTER"))
                {
                    parser.ExpectOptional("COLUMN");

                    var columnName = ParserUtils.GetObjectName(parser.ParseIdentifier());

                    if (parser.ExpectOptional("SET", "DEFAULT"))
                    {
                        var expression = parser.Expression();
                        view.AddColumnDefaultValue(columnName, expression);
                    }
                    else if (parser.ExpectOptional("DROP", "DEFAULT"))
                    {
                        view.RemoveColumnDefaultValue(columnName);
                    }
                    else
                    {
                        throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                    }
                }
                else if (parser.ExpectOptional("OWNER", "TO"))
                {
                    // we do not parse this one so we just consume the identifier
                    if (outputIgnoredStatements)
                    {
                        database.AddIgnoredStatement("ALTER TABLE " + viewName + " OWNER TO " + parser.ParseIdentifier() + ';');
                    }
                    else
                    {
                        parser.ParseIdentifier();
                    }
                }
                else
                {
                    throw new TeamworkParserException("CannotParseStringUnsupportedCommand");
                }
            }
        }