<commit_before>package liquibase.parser.xml;

import liquibase.ChangeSet;
import liquibase.DatabaseChangeLog;
import liquibase.FileOpener;
import liquibase.change.*;
import liquibase.change.custom.CustomChangeWrapper;
import liquibase.exception.CustomChangeException;
import liquibase.exception.LiquibaseException;
import liquibase.exception.MigrationFailedException;
import liquibase.log.LogFactory;
import liquibase.parser.ChangeLogParser;
import liquibase.preconditions.*;
import liquibase.util.ObjectUtil;
import liquibase.util.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

class XMLChangeLogHandler extends DefaultHandler {

    protected Logger log;

    private DatabaseChangeLog databaseChangeLog;
    private Change change;
    private StringBuffer text;
    private AndPrecondition rootPrecondition;
    private Stack<PreconditionLogic> preconditionLogicStack = new Stack<PreconditionLogic>();
    private ChangeSet changeSet;
    private FileOpener fileOpener;
    private Precondition currentPrecondition;


    protected XMLChangeLogHandler(String physicalChangeLogLocation, FileOpener fileOpener) {
        log = LogFactory.getLogger();
        this.fileOpener = fileOpener;

        databaseChangeLog = new DatabaseChangeLog(physicalChangeLogLocation);
        databaseChangeLog.setPhysicalFilePath(physicalChangeLogLocation);
    }

    public DatabaseChangeLog getDatabaseChangeLog() {
        return databaseChangeLog;
    }

    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        try {
            if ("comment".equals(qName)) {
                text = new StringBuffer();
            } else if ("databaseChangeLog".equals(qName)) {
                String version = uri.substring(uri.lastIndexOf("/")+1);
                if (!version.equals(XMLChangeLogParser.getSchemaVersion())) {
                    log.warning(databaseChangeLog.getPhysicalFilePath()+" is using schema version "+version+" rather than version "+XMLChangeLogParser.getSchemaVersion());
                }
                databaseChangeLog.setLogicalFilePath(atts.getValue("logicalFilePath"));
            } else if ("include".equals(qName)) {
                String fileName = atts.getValue("file");
                handleIncludedChangeLog(fileName);
            } else if (changeSet == null && "changeSet".equals(qName)) {
                boolean alwaysRun = false;
                boolean runOnChange = false;
                if ("true".equalsIgnoreCase(atts.getValue("runAlways"))) {
                    alwaysRun = true;
                }
                if ("true".equalsIgnoreCase(atts.getValue("runOnChange"))) {
                    runOnChange = true;
                }
                changeSet = new ChangeSet(atts.getValue("id"),
                        atts.getValue("author"),
                        alwaysRun,
                        runOnChange,
                        databaseChangeLog.getFilePath(),
                        databaseChangeLog.getPhysicalFilePath(),
                        atts.getValue("context"),
                        atts.getValue("dbms"));
                if (StringUtils.trimToNull(atts.getValue("failOnError")) != null) {
                    changeSet.setFailOnError(Boolean.parseBoolean(atts.getValue("failOnError")));
                }
            } else if (changeSet != null && "rollback".equals(qName)) {
                text = new StringBuffer();
            } else if (changeSet != null && change == null) {
                change = ChangeFactory.getInstance().create(qName);
                change.setChangeSet(changeSet);
                text = new StringBuffer();
                if (change == null) {
                    throw new MigrationFailedException(changeSet, "Unknown change: " + qName);
                }
                change.setFileOpener(fileOpener);
                if (change instanceof CustomChangeWrapper) {
                    ((CustomChangeWrapper) change).setClassLoader(fileOpener.toClassLoader());
                }
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(change, attributeName, attributeValue);
                }
                change.setUp();
            } else if (change != null && "column".equals(qName)) {
                ColumnConfig column = new ColumnConfig();
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(column, attributeName, attributeValue);
                }
                if (change instanceof AddColumnChange) {
                    ((AddColumnChange) change).addColumn(column);
                } else if (change instanceof CreateTableChange) {
                    ((CreateTableChange) change).addColumn(column);
                } else if (change instanceof InsertDataChange) {
                    ((InsertDataChange) change).addColumn(column);
                } else if (change instanceof UpdateDataChange) {
                    ((UpdateDataChange) change).addColumn(column);
                } else if (change instanceof CreateIndexChange) {
                    ((CreateIndexChange) change).addColumn(column);
                } else if (change instanceof ModifyColumnChange) {
                    ((ModifyColumnChange) change).addColumn(column);
                } else {
                    throw new RuntimeException("Unexpected column tag for " + change.getClass().getName());
                }
            } else if (change != null && "constraints".equals(qName)) {
                ConstraintsConfig constraints = new ConstraintsConfig();
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(constraints, attributeName, attributeValue);
                }
                ColumnConfig lastColumn;
                if (change instanceof AddColumnChange) {
                    lastColumn = ((AddColumnChange) change).getLastColumn();
                } else if (change instanceof CreateTableChange) {
                    lastColumn = ((CreateTableChange) change).getColumns().get(((CreateTableChange) change).getColumns().size() - 1);
                } else {
                    throw new RuntimeException("Unexpected change: " + change.getClass().getName());
                }
                lastColumn.setConstraints(constraints);
            } else if ("preConditions".equals(qName)) {
                rootPrecondition = new AndPrecondition();
                preconditionLogicStack.push(rootPrecondition);

            } else if (rootPrecondition != null) {
                currentPrecondition = PreconditionFactory.getInstance().create(qName);

                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(currentPrecondition, attributeName, attributeValue);
                }
                preconditionLogicStack.peek().addNestedPrecondition(currentPrecondition);

                if (currentPrecondition instanceof PreconditionLogic) {
                    preconditionLogicStack.push(((PreconditionLogic) currentPrecondition));<commit_msg>Bug fix with constraints on modifyColumn tags<commit_after>package liquibase.parser.xml;

import liquibase.ChangeSet;
import liquibase.DatabaseChangeLog;
import liquibase.FileOpener;
import liquibase.change.*;
import liquibase.change.custom.CustomChangeWrapper;
import liquibase.exception.CustomChangeException;
import liquibase.exception.LiquibaseException;
import liquibase.exception.MigrationFailedException;
import liquibase.log.LogFactory;
import liquibase.parser.ChangeLogParser;
import liquibase.preconditions.*;
import liquibase.util.ObjectUtil;
import liquibase.util.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

class XMLChangeLogHandler extends DefaultHandler {

    protected Logger log;

    private DatabaseChangeLog databaseChangeLog;
    private Change change;
    private StringBuffer text;
    private AndPrecondition rootPrecondition;
    private Stack<PreconditionLogic> preconditionLogicStack = new Stack<PreconditionLogic>();
    private ChangeSet changeSet;
    private FileOpener fileOpener;
    private Precondition currentPrecondition;


    protected XMLChangeLogHandler(String physicalChangeLogLocation, FileOpener fileOpener) {
        log = LogFactory.getLogger();
        this.fileOpener = fileOpener;

        databaseChangeLog = new DatabaseChangeLog(physicalChangeLogLocation);
        databaseChangeLog.setPhysicalFilePath(physicalChangeLogLocation);
    }

    public DatabaseChangeLog getDatabaseChangeLog() {
        return databaseChangeLog;
    }

    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        try {
            if ("comment".equals(qName)) {
                text = new StringBuffer();
            } else if ("databaseChangeLog".equals(qName)) {
                String version = uri.substring(uri.lastIndexOf("/")+1);
                if (!version.equals(XMLChangeLogParser.getSchemaVersion())) {
                    log.warning(databaseChangeLog.getPhysicalFilePath()+" is using schema version "+version+" rather than version "+XMLChangeLogParser.getSchemaVersion());
                }
                databaseChangeLog.setLogicalFilePath(atts.getValue("logicalFilePath"));
            } else if ("include".equals(qName)) {
                String fileName = atts.getValue("file");
                handleIncludedChangeLog(fileName);
            } else if (changeSet == null && "changeSet".equals(qName)) {
                boolean alwaysRun = false;
                boolean runOnChange = false;
                if ("true".equalsIgnoreCase(atts.getValue("runAlways"))) {
                    alwaysRun = true;
                }
                if ("true".equalsIgnoreCase(atts.getValue("runOnChange"))) {
                    runOnChange = true;
                }
                changeSet = new ChangeSet(atts.getValue("id"),
                        atts.getValue("author"),
                        alwaysRun,
                        runOnChange,
                        databaseChangeLog.getFilePath(),
                        databaseChangeLog.getPhysicalFilePath(),
                        atts.getValue("context"),
                        atts.getValue("dbms"));
                if (StringUtils.trimToNull(atts.getValue("failOnError")) != null) {
                    changeSet.setFailOnError(Boolean.parseBoolean(atts.getValue("failOnError")));
                }
            } else if (changeSet != null && "rollback".equals(qName)) {
                text = new StringBuffer();
            } else if (changeSet != null && change == null) {
                change = ChangeFactory.getInstance().create(qName);
                change.setChangeSet(changeSet);
                text = new StringBuffer();
                if (change == null) {
                    throw new MigrationFailedException(changeSet, "Unknown change: " + qName);
                }
                change.setFileOpener(fileOpener);
                if (change instanceof CustomChangeWrapper) {
                    ((CustomChangeWrapper) change).setClassLoader(fileOpener.toClassLoader());
                }
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(change, attributeName, attributeValue);
                }
                change.setUp();
            } else if (change != null && "column".equals(qName)) {
                ColumnConfig column = new ColumnConfig();
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(column, attributeName, attributeValue);
                }
                if (change instanceof AddColumnChange) {
                    ((AddColumnChange) change).addColumn(column);
                } else if (change instanceof CreateTableChange) {
                    ((CreateTableChange) change).addColumn(column);
                } else if (change instanceof InsertDataChange) {
                    ((InsertDataChange) change).addColumn(column);
                } else if (change instanceof UpdateDataChange) {
                    ((UpdateDataChange) change).addColumn(column);
                } else if (change instanceof CreateIndexChange) {
                    ((CreateIndexChange) change).addColumn(column);
                } else if (change instanceof ModifyColumnChange) {
                    ((ModifyColumnChange) change).addColumn(column);
                } else {
                    throw new RuntimeException("Unexpected column tag for " + change.getClass().getName());
                }
            } else if (change != null && "constraints".equals(qName)) {
                ConstraintsConfig constraints = new ConstraintsConfig();
                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(constraints, attributeName, attributeValue);
                }
                ColumnConfig lastColumn;
                if (change instanceof AddColumnChange) {
                    lastColumn = ((AddColumnChange) change).getLastColumn();
                } else if (change instanceof CreateTableChange) {
                    lastColumn = ((CreateTableChange) change).getColumns().get(((CreateTableChange) change).getColumns().size() - 1);
                } else if (change instanceof ModifyColumnChange) {
                    lastColumn = ((ModifyColumnChange) change).getColumns().get(((ModifyColumnChange) change).getColumns().size() - 1);
                } else {
                    throw new RuntimeException("Unexpected change: " + change.getClass().getName());
                }
                lastColumn.setConstraints(constraints);
            } else if ("preConditions".equals(qName)) {
                rootPrecondition = new AndPrecondition();
                preconditionLogicStack.push(rootPrecondition);

            } else if (rootPrecondition != null) {
                currentPrecondition = PreconditionFactory.getInstance().create(qName);

                for (int i = 0; i < atts.getLength(); i++) {
                    String attributeName = atts.getQName(i);
                    String attributeValue = atts.getValue(i);
                    setProperty(currentPrecondition, attributeName, attributeValue);
                }
                preconditionLogicStack.peek().addNestedPrecondition(currentPrecondition);

                if (currentPrecondition instanceof PreconditionLogic) {
                    preconditionLogicStack.push(((PreconditionLogic) currentPrecondition));
{'fraction_non_alphanumeric': 0.09630565203662772, 'fraction_numerical': 0.0008209662140827281, 'mean_word_length': 2.1247040252565115, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3225257', 'n_tokens_mistral': 3849, 'n_tokens_neox': 3594, 'n_words': 787}