001/**************************************************************** 002 * Licensed to the Apache Software Foundation (ASF) under one * 003 * or more contributor license agreements. See the NOTICE file * 004 * distributed with this work for additional information * 005 * regarding copyright ownership. The ASF licenses this file * 006 * to you under the Apache License, Version 2.0 (the * 007 * "License"); you may not use this file except in compliance * 008 * with the License. You may obtain a copy of the License at * 009 * * 010 * http://www.apache.org/licenses/LICENSE-2.0 * 011 * * 012 * Unless required by applicable law or agreed to in writing, * 013 * software distributed under the License is distributed on an * 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 015 * KIND, either express or implied. See the License for the * 016 * specific language governing permissions and limitations * 017 * under the License. * 018 ****************************************************************/ 019package org.apache.james.mailbox.jpa.migrator.command; 020 021import javax.persistence.EntityManager; 022import javax.persistence.Query; 023 024import org.apache.james.mailbox.jpa.migrator.exception.JpaMigrateException; 025import org.apache.openjpa.kernel.DelegatingResultList; 026import org.apache.openjpa.lib.rop.ResultList; 027 028/** 029 * JIRA IMAP-180 is "Add @ElementJoinColumn for Property and Header tables". 030 * 031 * 1. Add the needed columns on HEADER and PROPERTY 032 * ALTER TABLE HEADER ADD COLUMN MESSAGE_ID BIGINT 033 * ALTER TABLE PROPERTY ADD COLUMN MESSAGE_ID BIGINT 034 * 035 * 2. Link the HEADER/PROPERTY tables with the MESSAGE table 036 * SELECT * FROM MESSAGE_HEADER / MESSAGE_HEADER 037 * 038 * 3. Add the needed FK and indexes on HEADER and PROPERTY 039 * CREATE INDEX SQL100727182411700 ON HEADER(MESSAGE_ID) 040 * ALTER TABLE HEADER ADD CONSTRAINT SQL100727182411700 FOREIGN KEY (MESSAGE_ID) REFERENCES MESSAGE(ID) 041 * CREATE INDEX SQL100727182411780 ON PROPERTY(MESSAGE_ID) 042 * ALTER TABLE PROPERTY ADD CONSTRAINT SQL100727182411780 FOREIGN KEY (MESSAGE_ID) REFERENCES MESSAGE(ID) 043 * 044 * 4. Drop the MESSAGE_HEADER and MESSAGE_PROPERY tables 045 * DROP TABLE MESSAGE_HEADER 046 * DROP TABLE MESSAGE_PROPERTY 047 * 048 * @link https://issues.apache.org/jira/browse/IMAP-180 049 * 050 */ 051public class IMAP180JpaMigrateCommand implements JpaMigrateCommand { 052 053 /** 054 * @see org.apache.james.mailbox.jpa.migrator.command#migrate(javax.persistence.EntityManager) 055 */ 056 public void migrate(EntityManager em) throws JpaMigrateException { 057 em.getTransaction().commit(); 058 migrateHeaders(em); 059 // Commit after header migration. 060 migrateProperties(em); 061 em.getTransaction().begin(); 062 } 063 064 /** 065 * Migrate the headers. 066 */ 067 @SuppressWarnings("rawtypes") 068 private static void migrateHeaders(EntityManager em) { 069 070 em.getTransaction().begin(); 071 Query headerCountQuery = em.createNativeQuery("SELECT COUNT(MESSAGE_ID) FROM MESSAGE_HEADER", Integer.class); 072 Integer headerCount = (Integer) headerCountQuery.getResultList().get(0); 073 System.out.println("Number of headers=" + headerCount); 074 075 JpaMigrateQuery.executeUpdate(em, "ALTER TABLE HEADER ADD COLUMN MESSAGE_ID BIGINT"); 076 077 Query headerQuery = em.createNativeQuery("SELECT MESSAGE_ID, HEADERS_ID FROM MESSAGE_HEADER"); 078 em.getTransaction().commit(); 079 080 DelegatingResultList headerNameList = (DelegatingResultList) headerQuery.getResultList(); 081 ResultList rl = headerNameList.getDelegate(); 082 for (int i=0; i < rl.size(); i++) { 083 Object[] results = (Object[]) rl.get(i); 084 Long messageId = (Long) results[0]; 085 Long headerId = (Long) results[1]; 086 em.getTransaction().begin(); 087 Query update = em.createNativeQuery("UPDATE HEADER SET MESSAGE_ID = ? WHERE ID = ?"); 088 update.setParameter(1, messageId); 089 update.setParameter(2, headerId); 090 int result = update.executeUpdate(); 091 System.out.printf("ExecuteUpdate returned a result=" + result + " for header %d of %d\n", i+1, headerCount); 092 em.getTransaction().commit(); 093 } 094 095 em.getTransaction().begin(); 096 System.out.println("Creating index."); 097 JpaMigrateQuery.executeUpdate(em, "CREATE INDEX SQL100727182411700 ON HEADER(MESSAGE_ID)"); 098 em.getTransaction().commit(); 099 100 em.getTransaction().begin(); 101 System.out.println("Creating foreign key."); 102 JpaMigrateQuery.executeUpdate(em, "ALTER TABLE HEADER ADD CONSTRAINT SQL100727182411700 FOREIGN KEY (MESSAGE_ID) REFERENCES MESSAGE(ID)"); 103 em.getTransaction().commit(); 104 105 em.getTransaction().begin(); 106 System.out.println("Dropping table."); 107 JpaMigrateQuery.executeUpdate(em, "DROP TABLE MESSAGE_HEADER"); 108 em.getTransaction().commit(); 109 110 } 111 112 /** 113 * Migrate the properties. 114 */ 115 @SuppressWarnings("rawtypes") 116 private static void migrateProperties(EntityManager em) { 117 118 em.getTransaction().begin(); 119 Query propertyCountQuery = em.createNativeQuery("SELECT COUNT(MESSAGE_ID) FROM MESSAGE_PROPERTY", Integer.class); 120 Integer propertyCount = (Integer) propertyCountQuery.getResultList().get(0); 121 System.out.println("Number of headers=" + propertyCount); 122 123 JpaMigrateQuery.executeUpdate(em, "ALTER TABLE PROPERTY ADD COLUMN MESSAGE_ID BIGINT"); 124 125 Query propertyQuery = em.createNativeQuery("SELECT MESSAGE_ID, PROPERTIES_ID FROM MESSAGE_PROPERTY"); 126 em.getTransaction().commit(); 127 128 DelegatingResultList propertyNameList = (DelegatingResultList) propertyQuery.getResultList(); 129 ResultList rl = propertyNameList.getDelegate(); 130 for (int i=0; i < rl.size(); i++) { 131 Object[] results = (Object[]) rl.get(i); 132 Long messageId = (Long) results[0]; 133 Long propertyId = (Long) results[1]; 134 em.getTransaction().begin(); 135 Query update = em.createNativeQuery("UPDATE PROPERTY SET MESSAGE_ID = ? WHERE ID = ?"); 136 update.setParameter(1, messageId); 137 update.setParameter(2, propertyId); 138 int result = update.executeUpdate(); 139 System.out.printf("ExecuteUpdate returned a result=" + result + " for property %d of %d\n", i+1, propertyCount); 140 em.getTransaction().commit(); 141 } 142 143 em.getTransaction().begin(); 144 System.out.println("Creating index."); 145 JpaMigrateQuery.executeUpdate(em, "CREATE INDEX SQL100727182411780 ON PROPERTY(MESSAGE_ID)"); 146 em.getTransaction().commit(); 147 148 em.getTransaction().begin(); 149 System.out.println("Creating foreign key."); 150 JpaMigrateQuery.executeUpdate(em, "ALTER TABLE PROPERTY ADD CONSTRAINT SQL100727182411780 FOREIGN KEY (MESSAGE_ID) REFERENCES MESSAGE(ID)"); 151 em.getTransaction().commit(); 152 153 em.getTransaction().begin(); 154 System.out.println("Dropping table."); 155 JpaMigrateQuery.executeUpdate(em, "DROP TABLE MESSAGE_PROPERTY"); 156 em.getTransaction().commit(); 157 158 } 159 160}