1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.store.migration.hibernate

File R35101XWIKI7645DataMigration.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart1.png
82% of files have more coverage

Code metrics

10
39
7
2
186
113
16
0.41
5.57
3.5
2.29

Classes

Class Line # Actions
R35101XWIKI7645DataMigration 60 11 0% 7 14
0.12512.5%
R35101XWIKI7645DataMigration.R35101Work 110 28 0% 9 40
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20   
21    package com.xpn.xwiki.store.migration.hibernate;
22   
23    import java.sql.Connection;
24    import java.sql.PreparedStatement;
25    import java.sql.ResultSet;
26    import java.sql.SQLException;
27    import java.sql.Statement;
28   
29    import javax.inject.Named;
30    import javax.inject.Singleton;
31   
32    import org.hibernate.HibernateException;
33    import org.hibernate.Session;
34    import org.hibernate.jdbc.Work;
35    import org.xwiki.component.annotation.Component;
36   
37    import com.xpn.xwiki.XWiki;
38    import com.xpn.xwiki.XWikiContext;
39    import com.xpn.xwiki.XWikiException;
40    import com.xpn.xwiki.store.DatabaseProduct;
41    import com.xpn.xwiki.store.XWikiHibernateBaseStore.HibernateCallback;
42    import com.xpn.xwiki.store.migration.DataMigrationException;
43    import com.xpn.xwiki.store.migration.XWikiDBVersion;
44    import com.xpn.xwiki.web.Utils;
45   
46    /**
47    * Migration for XWIKI-7564: Manually change the SQL type of long binary columns from LONG RAW to proper BLOBs when the
48    * underlying database is Oracle. More specifically, this migrator changes the attachment content and attachment archive
49    * columns from LONG RAW to BLOB, and rebuilds the indexes on those tables afterwards. The columns must be switched to
50    * BLOB since this is the expected column type when using the new mapping files. Rebuilding the indexes is needed
51    * because changing a table's columns automatically invalidates the indexes on those tables, and with unusable indexes
52    * any new insertion in those tables will trigger an exception.
53    *
54    * @version $Id: fac3f891bd02b52595d7f20724f14442ddbbb89a $
55    * @since 3.5.1
56    */
57    @Component
58    @Named("R35101XWIKI7645")
59    @Singleton
 
60    public class R35101XWIKI7645DataMigration extends AbstractHibernateDataMigration
61    {
 
62  0 toggle @Override
63    public String getDescription()
64    {
65  0 return "See http://jira.xwiki.org/browse/XWIKI-7645";
66    }
67   
 
68  206 toggle @Override
69    public XWikiDBVersion getVersion()
70    {
71  206 return new XWikiDBVersion(35101);
72    }
73   
 
74  0 toggle @Override
75    public boolean shouldExecute(XWikiDBVersion startupVersion)
76    {
77  0 boolean shouldExecute = false;
78  0 try {
79  0 getStore().beginTransaction(getXWikiContext());
80    // Run this migration if the database isn't new
81  0 shouldExecute = getStore().getDatabaseProductName() == DatabaseProduct.ORACLE;
82  0 getStore().endTransaction(getXWikiContext(), false);
83    } catch (XWikiException ex) {
84    // Shouldn't happen, ignore
85    } catch (DataMigrationException ex) {
86    // Shouldn't happen, ignore
87    }
88  0 return shouldExecute;
89    }
90   
 
91  0 toggle @Override
92    public void hibernateMigrate() throws DataMigrationException, XWikiException
93    {
94  0 getStore().executeWrite(getXWikiContext(), new HibernateCallback<Object>()
95    {
 
96  0 toggle @Override
97    public Object doInHibernate(Session session) throws HibernateException, XWikiException
98    {
99  0 session.doWork(new R35101Work());
100  0 return Boolean.TRUE;
101    }
102    });
103    }
104   
105    /**
106    * Hibernate {@link Work} class doing the actual work of this migrator.
107    *
108    * @version $Id: fac3f891bd02b52595d7f20724f14442ddbbb89a $
109    */
 
110    private static class R35101Work implements Work
111    {
 
112  0 toggle @Override
113    public void execute(Connection connection) throws SQLException
114    {
115  0 String[][] tablesToFix = new String[][] {
116    { "XWIKIATTACHMENT_CONTENT", "XWA_CONTENT" },
117    { "XWIKIATTACHMENT_ARCHIVE", "XWA_ARCHIVE" } };
118  0 Statement stmt = connection.createStatement();
119  0 PreparedStatement getIndexesQuery = connection.prepareStatement(
120    "SELECT index_name FROM all_indexes WHERE table_owner=? AND table_name=? AND index_type='NORMAL'");
121   
122  0 for (String[] table : tablesToFix) {
123  0 try {
124  0 stmt.execute("ALTER TABLE " + table[0] + " MODIFY (" + table[1] + " blob)");
125    } catch (SQLException ex) {
126    // This exception is thrown when this migrator isn't really needed. This happens when migrating from
127    // a version between 3.2 and 3.5, which do use the proper table structure, but we can't easily
128    // distinguish between a pre-3.2 database and a post-3.2 database.
129    // ORA-22859 on Oracle 11g, but ORA-22858 on Oracle 10g should be ignored.
130  0 if (ex.getMessage().contains("ORA-22859") || ex.getMessage().contains("ORA-22858")) {
131  0 return;
132    } else {
133  0 throw ex;
134    }
135    }
136  0 getIndexesQuery.setString(1, getSchemaFromWikiName(Utils.getContext().getWikiId()));
137  0 getIndexesQuery.setString(2, table[0]);
138  0 ResultSet indexes = getIndexesQuery.executeQuery();
139  0 while (indexes.next()) {
140  0 String index = indexes.getString(1);
141  0 stmt.execute("ALTER INDEX " + index + " REBUILD");
142    }
143    }
144    }
145   
146    /**
147    * The actual schema name isn't always the same as the virtual wiki name. Two settings in xwiki.cfg can change
148    * this. For the main wiki, by default "xwiki" is used as the schema name, but the {@code xwiki.db} setting can
149    * override this. Also, the {@code xwiki.db.prefix} can define a prefix that should be appended to all schema
150    * names, so that all the wikis in a farm can have a common prefix. And on Oracle, the schema name is always
151    * uppercased.
152    *
153    * @param wikiName the name of the virtual wiki for which to compute the schema name
154    * @return the schema name corresponding to the virtual wiki, in UPPERCASE
155    */
 
156  0 toggle private String getSchemaFromWikiName(String wikiName)
157    {
158  0 if (wikiName == null) {
159  0 return null;
160    }
161   
162  0 XWikiContext context = Utils.getContext();
163  0 XWiki wiki = context.getWiki();
164   
165  0 String schema;
166  0 if (context.isMainWiki(wikiName)) {
167    // Main wiki database, by default is "xwiki", but can be changed in xwiki.cfg
168  0 schema = wiki.Param("xwiki.db");
169  0 if (schema == null) {
170  0 schema = wikiName;
171    }
172    } else {
173    // Virtual wiki database name is the name of the wiki
174  0 schema = wikiName.replace('-', '_');
175    }
176   
177    // Apply an optional prefix defined in xwiki.cfg
178  0 String prefix = wiki.Param("xwiki.db.prefix", "");
179  0 schema = prefix + schema;
180   
181    // Oracle schema names are UPPERCASE
182  0 return schema.toUpperCase();
183    }
184   
185    }
186    }