root/trunk/grails-app/conf/DatabaseUpgrade.groovy @ 1496

Revision 1496, 6.8 KB (checked in by robert@…, 3 years ago)

Updated database upgrade script to work properly with postgresql

  • Property svn:keywords set to Rev Author Date
Line 
1import groovy.sql.Sql
2import dbnp.studycapturing.Study
3import org.codehaus.groovy.grails.commons.ConfigurationHolder
4
5/**
6 * A script to automatically perform database changes
7 *
8 * @Author      Jeroen Wesbeek
9 * @Since       20101209
10 *
11 * Revision information:
12 * $Rev$
13 * $Author$
14 * $Date$
15 */
16class DatabaseUpgrade {
17        /**
18         * handle database upgrades
19         *
20         * @param dataSource
21         */
22        public static void handleUpgrades(dataSource) {
23                // get a sql instance
24                groovy.sql.Sql sql = new groovy.sql.Sql(dataSource)
25
26                // get configuration
27                def config = ConfigurationHolder.config
28                def db = config.dataSource.driverClassName
29
30                // execute per-change check and upgrade code
31                changeStudyDescription(sql, db)                         // r1245 / r1246
32                changeStudyDescriptionToText(sql, db)           // r1327
33                changeTemplateTextFieldSignatures(sql, db)      // prevent Grails issue, see http://jira.codehaus.org/browse/GRAILS-6754
34                setAssayModuleDefaultValues(sql, db)            // 1490
35        }
36
37        /**
38         * execute database change r1245 / r1246 if required
39         * @param sql
40         * @param db
41         */
42        public static void changeStudyDescription(sql, db) {
43                // check if we need to perform this upgrade
44                if (sql.firstRow("SELECT count(*) as total FROM template_field WHERE templatefieldentity='dbnp.studycapturing.Study' AND templatefieldname='Description'").total > 0) {
45                        // grom that we are performing the upgrade
46                        "performing database upgrade: study description".grom()
47
48                        // database upgrade required
49                        try {
50                                // get the template field id
51                                def id = sql.firstRow("SELECT id FROM template_field WHERE templatefieldentity='dbnp.studycapturing.Study' AND templatefieldname='Description'").id
52
53                                // iterate through all obsolete study descriptions
54                                sql.eachRow("SELECT study_id, template_text_fields_elt as description FROM study_template_text_fields WHERE template_text_fields_idx='Description'") { row ->
55                                        // migrate the template description to the study object itself
56                                        // so we don't have to bother with sql injections, etc
57                                        def study = Study.findById( row.study_id )
58                                        study.setFieldValue('description', row.description)
59                                        if (!(study.validate() && study.save())) {
60                                                throw new Exception("could not save study with id ${row.study_id}")
61                                        }
62                                }
63
64                                // delete all obsolete descriptions
65                                sql.execute("DELETE FROM study_template_text_fields WHERE template_text_fields_idx='Description'")
66
67                                // find all template id's where this field is used
68                                sql.eachRow("SELECT DISTINCT template_fields_id, fields_idx FROM template_template_field WHERE template_field_id=${id}") { row ->
69                                        // delete the template_template_field reference
70                                        sql.execute("DELETE FROM template_template_field WHERE template_field_id=${id} AND template_fields_id=${row.template_fields_id}")
71
72                                        // and lower the idx-es of the remaining fields
73                                        sql.execute("UPDATE template_template_field SET fields_idx=fields_idx-1 WHERE fields_idx>${row.fields_idx} AND template_fields_id=${row.template_fields_id}")
74                                }
75
76                                // and delete the obsolete template field
77                                sql.execute("DELETE FROM template_field WHERE id=${id}")
78                        } catch (Exception e) {
79                                "changeStudyDescription database upgrade failed: " + e.getMessage()
80                        }
81                }
82        }
83
84        /**
85         * execute database change r1327 if required
86         * @param sql
87         * @param db
88         */
89        public static void changeStudyDescriptionToText(sql, db) {
90                // are we running postgreSQL ?
91                if (db == "org.postgresql.Driver") {
92                        // check if column 'description' in table 'study' is not of type 'text'
93                        if (sql.firstRow("SELECT count(*) as total FROM information_schema.columns WHERE columns.table_schema::text = 'public'::text AND columns.table_name='study' AND column_name='description' AND data_type != 'text'").total > 0) {
94                                // grom that we are performing the upgrade
95                                "performing database upgrade: study description to text".grom()
96
97                                // database upgrade required
98                                try {
99                                        // change the datatype of study::description to text
100                                        sql.execute("ALTER TABLE study ALTER COLUMN description TYPE text")
101                                } catch (Exception e) {
102                                        "changeStudyDescriptionToText database upgrade failed: " + e.getMessage()
103                                }
104                        }
105                }
106        }
107
108        /**
109         * it appears that some TEXT template fields are not of type 'text'
110         * due to an issue in how Grails' GORM works with domain inheritance
111         * (see http://jira.codehaus.org/browse/GRAILS-6754)
112         * @param sql
113         * @param db
114         */
115        public static void changeTemplateTextFieldSignatures(sql, db) {
116                if (db == "org.postgresql.Driver") {
117                        // check if any TEXT template fields are of type 'text'
118                        sql.eachRow("SELECT columns.table_name as tablename FROM information_schema.columns WHERE columns.table_schema::text = 'public'::text AND column_name='template_text_fields_elt' AND data_type != 'text';")
119                        { row ->
120                                "performing database upgrade: ${row.tablename} template_text_fields_string/elt to text".grom()
121                                try {
122                                        // change the datatype of text fields to text
123                                        sql.execute(sprintf("ALTER TABLE %s ALTER COLUMN template_text_fields_elt TYPE text", row.tablename))
124                                        sql.execute(sprintf("ALTER TABLE %s ALTER COLUMN template_text_fields_string TYPE text", row.tablename))
125
126                                } catch (Exception e) {
127                                        "changeTemplateTextFieldSignatures database upgrade failed: " + e.getMessage()
128                                }
129                        }
130                }
131        }
132       
133        /**
134        * The fields 'notify' and 'openInFrame' have been added to AssayModule. However, there
135        * seems to be no method to setting the default values of these fields in the database. They
136        * are set to NULL by default, so all existing fields have 'NULL' set.
137        * This method sets the default values
138        * @param sql
139        * @param db
140        */
141   public static void setAssayModuleDefaultValues(sql, db) {
142           "performing database upgrade: assay_module default values for boolean fields".grom()
143
144           // are we running postgreSQL ?
145           if (db == "org.postgresql.Driver") {
146                   try {
147                           sql.execute("UPDATE assay_module SET notify = FALSE WHERE notify IS NULL")
148                   } catch (Exception e) {
149                           println "setAssayModuleDefaultValues notify field couldn't be set to default value: " + e.getMessage()
150                   }
151                   try {
152                           sql.execute("UPDATE assay_module SET open_in_frame = TRUE WHERE open_in_frame IS NULL")
153                   } catch (Exception e) {
154                           println "setAssayModuleDefaultValues openInFrame field couldn't be set to default value: " + e.getMessage()
155                           println "Maybe gdt plugin is not updated yet after revision 109"
156                   }
157           }
158           
159           // Are we running MySQL
160           if( db == "com.mysql.jdbc.Driver" ) {
161                   try {
162                           sql.execute("UPDATE assay_module SET notify = 0 WHERE notify IS NULL")
163                   } catch (Exception e) {
164                           println "setAssayModuleDefaultValues notify field couldn't be set to default value: " + e.getMessage()
165                   }
166                   try {
167                           sql.execute("UPDATE assay_module SET open_in_frame = 1 WHERE open_in_frame IS NULL")
168                   } catch (Exception e) {
169                           println "setAssayModuleDefaultValues openInFrame field couldn't be set to default value: " + e.getMessage()
170                           println "Maybe gdt plugin is not updated yet after revision 109"
171                   }
172           }
173   }
174}
Note: See TracBrowser for help on using the browser.