
=== modified file 'src/com/goldencode/p2j/persist/SchemaCheck.java'
--- old/src/com/goldencode/p2j/persist/SchemaCheck.java	2023-01-31 20:49:01 +0000
+++ new/src/com/goldencode/p2j/persist/SchemaCheck.java	2023-02-13 22:53:22 +0000
@@ -195,10 +195,19 @@
                                    : comparator.compareWithPrevious();
          if (!result.isSame())
          {
+            SchemaValidator.validate(result.getState().getSequences());
+
             Set<Table> tablesToUnload = new HashSet<>();
             Set<Table> tablesToLoad = new HashSet<>();
             for (Difference difference : result.getDifferences())
             {
+               // Sequences are not attached to tables directly. Differences in sequences (or any other change
+               // not related to tables) should not reload any classes.
+               if (difference.getUpdatedTable() == null)
+               {
+                  continue;
+               }
+
                Element newElement = difference.getNewElement();
                if (newElement != null)
                {

=== modified file 'src/com/goldencode/p2j/persist/dialect/Dialect.java'
--- old/src/com/goldencode/p2j/persist/dialect/Dialect.java	2023-01-28 04:45:51 +0000
+++ new/src/com/goldencode/p2j/persist/dialect/Dialect.java	2023-02-13 22:13:34 +0000
@@ -1565,6 +1565,18 @@
    }
 
    /**
+    * Provides SQL to load sequences.
+    *
+    * @param   database
+    *          database object
+    * @return  sequence SQL
+    */
+   public String getSequenceSQL(Database database)
+   {
+      throw new UnsupportedOperationException("SQL for sequences is not yet implemented for this dialect");
+   }
+
+   /**
     * Helper interface for weights' aggregation
     */
    public static interface WeightAggregator

=== modified file 'src/com/goldencode/p2j/persist/dialect/MariaDbLenientDialect.java'
--- old/src/com/goldencode/p2j/persist/dialect/MariaDbLenientDialect.java	2023-01-27 15:42:43 +0000
+++ new/src/com/goldencode/p2j/persist/dialect/MariaDbLenientDialect.java	2023-02-13 22:33:19 +0000
@@ -1557,6 +1557,19 @@
    }
 
    /**
+    * Provides SQL to load sequences.
+    *
+    * @param   database
+    *          database object
+    * @return  sequence SQL
+    */
+   @Override
+   public String getSequenceSQL(Database database)
+   {
+      return "SELECT `table_name` AS sequence_name FROM information_schema.tables WHERE `table_schema` = '" + database.getName() + "' AND `table_type` = 'SEQUENCE'";
+   }
+
+   /**
     * Obtain a DDL statement which drops a SQL index.
     *
     * @param   ifExists

=== modified file 'src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java'
--- old/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java	2023-01-27 15:15:41 +0000
+++ new/src/com/goldencode/p2j/persist/dialect/P2JPostgreSQLDialect.java	2023-02-13 22:16:07 +0000
@@ -2529,6 +2529,19 @@
    {
       return null;
    }
+
+   /**
+    * Provides SQL to load sequences.
+    *
+    * @param   database
+    *          database object
+    * @return  sequence SQL
+    */
+   @Override
+   public String getSequenceSQL(Database database)
+   {
+      return "SELECT sequence_name FROM information_schema.sequences WHERE sequence_catalog = '" + database.getName() + "'";
+   }
    
    /**
     * UDF types 

=== modified file 'src/com/goldencode/p2j/persist/orm/schema/DatabaseState.java'
--- old/src/com/goldencode/p2j/persist/orm/schema/DatabaseState.java	2023-01-26 11:18:48 +0000
+++ new/src/com/goldencode/p2j/persist/orm/schema/DatabaseState.java	2023-02-13 21:54:22 +0000
@@ -83,6 +83,11 @@
     * Table list that further expands to columns and indexes.
     */
    private final Collection<Table> tables = new HashSet<>();
+
+   /**
+    * Sequence list.
+    */
+   private final Collection<Sequence> sequences = new HashSet<>();
    
    /**
     * Default constructor.
@@ -103,6 +108,16 @@
    {
       return tables;
    }
+
+   /**
+    * Getter for sequences.
+    *
+    * @return Sequence list
+    */
+   public Collection<Sequence> getSequences()
+   {
+      return sequences;
+   }
    
    /**
     * Getter for timestamp.

=== modified file 'src/com/goldencode/p2j/persist/orm/schema/SchemaComparator.java'
--- old/src/com/goldencode/p2j/persist/orm/schema/SchemaComparator.java	2023-01-28 04:45:51 +0000
+++ new/src/com/goldencode/p2j/persist/orm/schema/SchemaComparator.java	2023-02-13 22:33:19 +0000
@@ -108,6 +108,8 @@
    private static final String XML_COLUMNS = "columns";
    private static final String XML_COLUMN = "column";
    private static final String XML_INDEX = "index";
+   private static final String XML_SEQUENCES = "sequences";
+   private static final String XML_SEQUENCE = "sequence";
    private static final String XML_NAME = "name";
    private static final String XML_TYPE = "type";
    private static final String XML_PRECISION = "precision";
@@ -217,7 +219,8 @@
          getAndCompareTables(conn, previousState, comparisonResult);
          getAndCompareColumns(conn, previousState, comparisonResult);
          getAndCompareIndexes(conn, previousState, comparisonResult);
-         
+         getAndCompareSequences(conn, previousState, comparisonResult);
+
          if (!comparisonResult.isSame())
          {
             if (WRITE_KNOWN_STATE_FILE)
@@ -295,6 +298,17 @@
                   }
                }
             }
+            NodeList sequenceNodes = dom.getElementsByTagName(XML_SEQUENCES);
+            for (int i = 0; i < sequenceNodes.getLength(); i++)
+            {
+               Node sequenceNode = sequenceNodes.item(i);
+               Sequence sequence = new Sequence(
+                  database,
+                  XmlHelper.getAttribute(sequenceNode, XML_NAME),
+                  XmlHelper.getAttribute(sequenceNode, XML_COMMENT)
+               );
+               lastKnownState.getSequences().add(sequence);
+            }
          }
          catch (FileNotFoundException exc)
          {
@@ -323,13 +337,13 @@
       try (FileOutputStream fos = new FileOutputStream(LAST_KNOWN_STATE_FILE))
       {
          Document dom = XmlHelper.newDocument();
-         Element root = dom.createElement(XML_TABLES);
+         Element tableRoot = dom.createElement(XML_TABLES);
          for (Table table : lastKnownState.getTables())
          {
             Element tableNode = dom.createElement(XML_TABLE);
             XmlHelper.setAttributeOptional(tableNode, XML_NAME, table.getName());
             XmlHelper.setAttributeOptional(tableNode, XML_COMMENT, table.getComment());
-            root.appendChild(tableNode);
+            tableRoot.appendChild(tableNode);
             
             for (Attribute attribute : table.getAttributes())
             {
@@ -354,7 +368,17 @@
                tableNode.appendChild(indexNode);
             }
          }
-         dom.appendChild(root);
+         dom.appendChild(tableRoot);
+
+         Element sequenceRoot = dom.createElement(XML_SEQUENCES);
+         for (Sequence sequence : lastKnownState.getSequences())
+         {
+            Element sequenceNode = dom.createElement(XML_SEQUENCE);
+            XmlHelper.setAttributeOptional(sequenceNode, XML_NAME, sequence.getName());
+            XmlHelper.setAttributeOptional(sequenceNode, XML_COMMENT, sequence.getComment());
+            sequenceRoot.appendChild(sequenceNode);
+         }
+         dom.appendChild(sequenceRoot);
          
          XmlHelper.write(dom, fos);
       }
@@ -664,6 +688,62 @@
          }
       }
    }
+
+   /**
+    * Load information on sequences from the provided connection, put the state into result. If previous state is provided
+    * we can compare current state with the previous one and report any differences into result.
+    *
+    * @param   conn
+    *          Already initiated connection.
+    * @param   previousState
+    *          Last known state.
+    * @param   comparisonResult
+    *          Instance of result to be filled in.
+    *
+    * @throws  SQLException
+    *          on unsuccessful calls to DB.
+    */
+   private void getAndCompareSequences(Connection conn,
+                                       DatabaseState previousState,
+                                       ComparisonResult comparisonResult)
+   throws SQLException
+   {
+      Dialect dialect = Dialect.getDialect(database);
+      // Load sequences from DB
+      ResultSet sequences = conn.prepareStatement(dialect.getSequenceSQL(database)).executeQuery();
+
+      // Put all data into the new State
+      DatabaseState currentState = comparisonResult.getState();
+      while (sequences.next())
+      {
+         currentState.getSequences()
+                 .add(new Sequence(database, sequences.getString("sequence_name"), ""));
+      }
+
+      // Compare if old State is available
+      if (previousState != null)
+      {
+         // Detect added
+         for (Sequence sequence : currentState.getSequences())
+         {
+            if (!previousState.getSequences().contains(sequence))
+            {
+               comparisonResult.getDifferences()
+                       .add(new Difference(null, null, sequence));
+            }
+         }
+
+         // Detect removed
+         for (Sequence sequence : currentState.getSequences())
+         {
+            if (!currentState.getSequences().contains(sequence))
+            {
+               comparisonResult.getDifferences()
+                       .add(new Difference(null, sequence, null));
+            }
+         }
+      }
+   }
    
    /**
     * If table validation or DMO generation failed, this method can remove it from result so that it can be loaded next time.

=== modified file 'src/com/goldencode/p2j/persist/orm/schema/SchemaValidator.java'
--- old/src/com/goldencode/p2j/persist/orm/schema/SchemaValidator.java	2023-01-26 11:18:48 +0000
+++ new/src/com/goldencode/p2j/persist/orm/schema/SchemaValidator.java	2023-02-13 23:04:15 +0000
@@ -63,6 +63,7 @@
 
 package com.goldencode.p2j.persist.orm.schema;
 
+import com.goldencode.p2j.persist.*;
 import com.goldencode.p2j.persist.orm.*;
 import com.goldencode.p2j.persist.orm.schema.element.*;
 import com.goldencode.p2j.util.*;
@@ -135,4 +136,21 @@
          }
       }
    }
+
+   /**
+    * Apply validation rules on sequences. Currently just check that p2j_id_generator_sequence exists.
+    *
+    * @param   sequences
+    *          Sequence list to validate
+    * @throws  ErrorConditionException
+    *          Exception is thrown in case of a failed validation
+    */
+   public static void validate(Collection<Sequence> sequences)
+   throws ErrorConditionException
+   {
+      if (sequences.stream().noneMatch(sequence -> sequence.getName().equalsIgnoreCase(Persistence.ID_GEN_SEQUENCE)))
+      {
+         ErrorManager.recordOrThrowError(0, "Sequence " + Persistence.ID_GEN_SEQUENCE + " is not defined in database.");
+      }
+   }
 }

