GithubHelp home page GithubHelp logo

Comments (1)

andnorxor avatar andnorxor commented on June 26, 2024

For a quick fix I've updated the Code as follows (changes are commented with "// modification of original source")

The following changes ...

  • ... are only superficially tested and not well thought out
  • ... enable support for catalog aware databases
  • ... consider the @Table annotation schema property
  • ... pass the filepath to the changeset to make the liquibase FormattedSqlChangeLogSerializer work.

LiquibaseChangeSetWriter.java

private SchemaDiff differenceOf(Database database) throws LiquibaseException {
		Set<? extends RelationalPersistentEntity<?>> entities = mappingContext.getPersistentEntities().stream()
            .filter(schemaFilter)
            .collect(Collectors.toSet());

        // modification of original source
        String schema = database.supportsCatalogs() ?
            database.getDefaultSchemaName() :
            database.getDefaultCatalogName();

        Tables mappedEntities = Tables.from(entities.stream(), sqlTypeMapping, schema, mappingContext);
        Tables existingTables = getLiquibaseModel(database, getEntitySchemas(database, entities));

		return SchemaDiff.diff(mappedEntities, existingTables, nameComparator);
	}
	
    // modification of original source
private CatalogAndSchema[] getEntitySchemas(Database database, Set<? extends RelationalPersistentEntity<?>> entities) {
        return entities.stream()
            .filter(it -> it.isAnnotationPresent(org.springframework.data.relational.core.mapping.Table.class))
            .map(entity -> entity.getRequiredAnnotation(org.springframework.data.relational.core.mapping.Table.class))
            .map(tableAnnotation -> new CatalogAndSchema(database.getDefaultCatalogName(), tableAnnotation.schema()))
            .distinct()
            .toArray(CatalogAndSchema[]::new);
    }
    
private void writeChangeSet(DatabaseChangeLog databaseChangeLog, ChangeSet changeSet, File changeLogFile)
			throws IOException {

		List<ChangeLogChild> changes = new ArrayList<>(databaseChangeLog.getChangeSets());
		changes.add(changeSet);

		try (FileOutputStream fos = new FileOutputStream(changeLogFile)) {
            // modification of original source
            changeSet.setFilePath(changeLogFile.getAbsolutePath());
			changeLogSerializer.write(changes, fos);
		}
	} 

	private Tables getLiquibaseModel(Database targetDatabase, CatalogAndSchema[] catalogAndSchemas) throws LiquibaseException {

		SnapshotControl snapshotControl = new SnapshotControl(targetDatabase);

		DatabaseSnapshot snapshot = SnapshotGeneratorFactory.getInstance()
            .createSnapshot(catalogAndSchemas, targetDatabase, snapshotControl);

		Set<liquibase.structure.core.Table> tables = snapshot.get(liquibase.structure.core.Table.class);
		List<Table> existingTables = new ArrayList<>(tables.size());

		for (liquibase.structure.core.Table table : tables) {

			// Exclude internal Liquibase tables from comparison
			if (isLiquibaseTable.test(table.getName())) {
				continue;
			}

            // modification of original source
            String schema = targetDatabase.supportsCatalogs() ?
                table.getSchema().getSchema().getName() :
                table.getSchema().getCatalogName();

			Table tableModel = new Table(schema, table.getName());

			List<liquibase.structure.core.Column> columns = table.getColumns();

			for (liquibase.structure.core.Column column : columns) {

				String type = column.getType().toString();
				boolean nullable = column.isNullable();
				Column columnModel = new Column(column.getName(), type, nullable, false);

				tableModel.columns().add(columnModel);
			}

			tableModel.foreignKeys().addAll(extractForeignKeys(table));

			existingTables.add(tableModel);
		}

		return new Tables(existingTables);
	}

Tables.java

	public static Tables from(Stream<? extends RelationalPersistentEntity<?>> persistentEntities,
			SqlTypeMapping sqlTypeMapping, @Nullable String defaultSchema,
			MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context) {

		List<ForeignKeyMetadata> foreignKeyMetadataList = new ArrayList<>();
		List<Table> tables = persistentEntities
				.filter(it -> it.isAnnotationPresent(org.springframework.data.relational.core.mapping.Table.class)) //
				.map(entity -> {

                    // modification of original source
                    org.springframework.data.relational.core.mapping.Table tableAnnotation =
                        entity.getRequiredAnnotation(org.springframework.data.relational.core.mapping.Table.class);

                    String tableSchema = !tableAnnotation.schema().isEmpty() ?
                        tableAnnotation.schema() : defaultSchema;

					Table table = new Table(tableSchema, entity.getTableName().getReference());

					Set<RelationalPersistentProperty> identifierColumns = new LinkedHashSet<>();
					entity.getPersistentProperties(Id.class).forEach(identifierColumns::add);

					for (RelationalPersistentProperty property : entity) {

						if (property.isEntity() && !property.isEmbedded()) {
							foreignKeyMetadataList.add(createForeignKeyMetadata(entity, property, context, sqlTypeMapping));
							continue;
						}

						Column column = new Column(property.getColumnName().getReference(), sqlTypeMapping.getColumnType(property),
								sqlTypeMapping.isNullable(property), identifierColumns.contains(property));
						table.columns().add(column);
					}
					return table;
				}).collect(Collectors.toList());

		applyForeignKeyMetadata(tables, foreignKeyMetadataList);

		return new Tables(tables);
	}

from spring-data-relational.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.