Steve Wall
Steve Wall

Reputation: 1932

grails limited table creation

I'd like to use the Grails feature for creating/updating database tables on a limited basis. Specifically, I'd like Grails to manage some tables, but not all.

Is there a way to limit the tables managed by Grails or is it an all or nothing proposition?

Upvotes: 4

Views: 1975

Answers (2)

Ken Tanaka
Ken Tanaka

Reputation: 35

Thanks for the fix Steve. I'm reposting the fix above, but formatted for stackoverflow. When I first tried this I missed the fact that the original if (!command.toLowerCase()...) reversed logic in the fix as if (command.toLowerCase()...), which effectively made it look like dbCreate = "create-drop" in my config/DataSource.groovy was having no effect. I even worked from the HTML source from this page to see intended line breaks of the code, but still missed that vital bit of logic :-( Once I got this entered correctly it worked great.

private String[] prune(String[] script) {
    List<String> pruned = new ArrayList<String>();
    for (String command : script) {

        boolean ignore = false;

        for (String ignoreName : IGNORE_NAMES) {
            if (command.toLowerCase().contains(" table " + ignoreName.toLowerCase() + " ")) {
                ignore = true;
                break;
            }
        }    

        if (!ignore) {
            pruned.add(command);
        }
    }
    return pruned.toArray(new String[pruned.size()]);
}

Upvotes: 2

Burt Beckwith
Burt Beckwith

Reputation: 75681

In general it's all or nothing since Grails uses Hibernate's HBM2DDL functionality. But you can intercept the process using a custom configuration subclass. Here's an example that extends GrailsAnnotationConfiguration and overrides all three SQL generation methods:

package com.yourcompany.yourapp;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;

public class MyConfiguration extends GrailsAnnotationConfiguration {

   private static final String[] IGNORE_NAMES = { "foo", "bar" };

   @Override
   public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException {
      return prune(super.generateDropSchemaScript(dialect));
   }

   @Override
   public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException {
      return prune(super.generateSchemaCreationScript(dialect));
   }

   @Override
   public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata)
         throws HibernateException {
      return prune(super.generateSchemaUpdateScript(dialect, databaseMetadata));
   }

   private String[] prune(String[] script) {
      List<String> pruned = new ArrayList<String>();
      for (String command : script) {
         for (String ignoreName : IGNORE_NAMES) {
            if (!command.toLowerCase().contains(" table " + ignoreName + " ")) {
               pruned.add(command);
            }
         }
      }
      return pruned.toArray(new String[pruned.size()]);
   }
}

You don't need to override all three, e.g. you could let creates go through but remove updates.

This gets registered in grails-app/conf/DataSource.groovy:

dataSource {
   pooled = true
   driverClassName = ...
   username = ...
   password = ...
   configClass = com.yourcompany.yourapp.MyConfiguration
}

Note that the class has to be written in Java because of an issue with private methods in the base class clashing with methods that Groovy adds to all groovy classes.

Upvotes: 11

Related Questions