1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "MysqlUpgraderFrom_1_16_To_1_24.h"
23
24 #include <U2Core/U2AttributeUtils.h>
25
26 #include "mysql_dbi/MysqlDbi.h"
27 #include "mysql_dbi/MysqlObjectDbi.h"
28 #include "mysql_dbi/util/MysqlHelpers.h"
29
30 namespace U2 {
31
32 const QString MysqlUpgraderFrom_1_16_To_1_24::META_INFO_MARKER = "##";
33 const QString MysqlUpgraderFrom_1_16_To_1_24::HEADER_MARKER = "#";
34 const QString MysqlUpgraderFrom_1_16_To_1_24::COLUMN_SEPARATOR = "\t";
35
MysqlUpgraderFrom_1_16_To_1_24(MysqlDbi * dbi)36 MysqlUpgraderFrom_1_16_To_1_24::MysqlUpgraderFrom_1_16_To_1_24(MysqlDbi *dbi)
37 : MysqlUpgrader(Version::parseVersion("1.16.0"), Version::parseVersion("1.24.0"), dbi) {
38 }
39
upgrade(U2OpStatus & os) const40 void MysqlUpgraderFrom_1_16_To_1_24::upgrade(U2OpStatus &os) const {
41 MysqlTransaction t(dbi->getDbRef(), os);
42
43 upgradeVariantDbi(os);
44 CHECK_OP(os, );
45
46 dbi->setProperty(U2DbiOptions::APP_MIN_COMPATIBLE_VERSION, versionTo.text, os);
47 }
48
upgradeVariantDbi(U2OpStatus & os) const49 void MysqlUpgraderFrom_1_16_To_1_24::upgradeVariantDbi(U2OpStatus &os) const {
50 coreLog.trace("Variant DBI upgrading");
51
52 MysqlTransaction t(dbi->getDbRef(), os);
53
54 QMap<U2DataId, QStringList> trackId2header;
55
56 extractAttributes(os, trackId2header);
57 CHECK_OP(os, );
58
59 repackInfo(os, trackId2header);
60 CHECK_OP(os, );
61
62 updateScheme(os);
63 }
64
65 namespace {
66
convertInfo(const QString & additionalInfo,const QStringList & header)67 QString convertInfo(const QString &additionalInfo, const QStringList &header) {
68 StrStrMap convertedInfoMap;
69 CHECK(!additionalInfo.isEmpty(), QString());
70 QStringList splittedInfo = additionalInfo.split("\t", QString::SkipEmptyParts);
71 CHECK(!splittedInfo.isEmpty(), QString());
72
73 convertedInfoMap.insert(U2Variant::VCF4_QUAL, splittedInfo.takeFirst());
74
75 if (!splittedInfo.isEmpty()) {
76 convertedInfoMap.insert(U2Variant::VCF4_FILTER, splittedInfo.takeFirst());
77 }
78
79 if (!splittedInfo.isEmpty()) {
80 convertedInfoMap.insert(U2Variant::VCF4_INFO, splittedInfo.takeFirst());
81 }
82
83 static const int maxVcf4MandatoryColumnNumber = 7; // VCF4 format supposes 8 mandatory columns
84 for (int i = maxVcf4MandatoryColumnNumber + 1; i < header.size(); i++) {
85 convertedInfoMap.insert(header[i], splittedInfo.isEmpty() ? "." : splittedInfo.takeFirst());
86 }
87
88 if (!splittedInfo.isEmpty()) {
89 // There is no possibility to split the data correctly, because it was splitted by spaces not by tabulations
90 convertedInfoMap.insert(QString::number(qMax(maxVcf4MandatoryColumnNumber, header.size()) + 1), splittedInfo.join("\t"));
91 }
92
93 return StrPackUtils::packMap(convertedInfoMap);
94 }
95
96 } // namespace
97
repackInfo(U2OpStatus & os,const QMap<U2DataId,QStringList> & trackId2header) const98 void MysqlUpgraderFrom_1_16_To_1_24::repackInfo(U2OpStatus &os, const QMap<U2DataId, QStringList> &trackId2header) const {
99 coreLog.trace("Additional info repacking");
100
101 MysqlTransaction t(dbi->getDbRef(), os);
102
103 const qint64 variantsCount = U2SqlQuery("SELECT count(*) from Variant", dbi->getDbRef(), os).selectInt64();
104
105 static QString getQueryString("SELECT id, track, additionalInfo FROM Variant");
106 static QString setQueryString("UPDATE Variant SET additionalInfo = :additionalInfo WHERE id = :id");
107 U2SqlQuery getQuery(getQueryString, dbi->getDbRef(), os);
108 U2SqlQuery setQuery(setQueryString, dbi->getDbRef(), os);
109
110 QSet<U2DataId> trackIds;
111
112 qint64 number = 0;
113 while (getQuery.step()) {
114 CHECK_OP(os, );
115 const qint64 dbiId = getQuery.getInt64(0);
116 const QString additionalInfo = getQuery.getString(2);
117 const U2DataId trackId = getQuery.getDataId(1, U2Type::VariantTrack);
118 trackIds << trackId;
119
120 const QString convertedInfo = convertInfo(additionalInfo, trackId2header[trackId]);
121
122 setQuery.bindString(":additionalInfo", convertedInfo);
123 setQuery.bindInt64(":id", dbiId);
124 setQuery.execute();
125 CHECK_OP(os, );
126
127 number++;
128 if (number % 100 == 0) {
129 coreLog.trace(QString("Variants processed: %1/%2").arg(number).arg(variantsCount));
130 }
131 }
132
133 if (number % 100 != 0) {
134 coreLog.trace(QString("Variants processed: %1/%2").arg(number).arg(variantsCount));
135 }
136
137 number = 0;
138 foreach (const U2DataId &trackId, trackIds) {
139 MysqlObjectDbi::incrementVersion(trackId, dbi->getDbRef(), os);
140 CHECK_OP(os, );
141
142 number++;
143 if (number % 10 == 0) {
144 coreLog.trace(QString("Object versions processed: %1/%2").arg(number).arg(trackIds.size()));
145 }
146 }
147
148 if (number % 10 != 0) {
149 coreLog.trace(QString("Object versions processed: %1/%2").arg(number).arg(trackIds.size()));
150 }
151 }
152
extractAttributes(U2OpStatus & os,QMap<U2DataId,QStringList> & trackId2header) const153 void MysqlUpgraderFrom_1_16_To_1_24::extractAttributes(U2OpStatus &os, QMap<U2DataId, QStringList> &trackId2header) const {
154 coreLog.trace("Attributes extracting");
155
156 const qint64 tracksCount = U2SqlQuery("SELECT count(*) from VariantTrack", dbi->getDbRef(), os).selectInt64();
157 CHECK_OP(os, );
158
159 QScopedPointer<U2DbiIterator<U2VariantTrack>> variantTracksIterator(dbi->getVariantDbi()->getVariantTracks(TrackType_All, os));
160 CHECK_OP(os, );
161
162 qint64 number = 0;
163 while (variantTracksIterator->hasNext()) {
164 U2VariantTrack variantTrack = variantTracksIterator->next();
165 CHECK_OP(os, );
166
167 QString metaInfo;
168 QStringList header;
169 splitFileHeader(variantTrack.fileHeader, metaInfo, header);
170
171 trackId2header.insert(variantTrack.id, header);
172
173 addStringAttribute(os, variantTrack, U2VariantTrack::META_INFO_ATTRIBUTE, metaInfo);
174 CHECK_OP(os, );
175 addStringAttribute(os, variantTrack, U2VariantTrack::HEADER_ATTRIBUTE, StrPackUtils::packStringList(header));
176 CHECK_OP(os, );
177
178 number++;
179 if (number % 10 == 0) {
180 coreLog.trace(QString("Variant tracks processed: %1/%2").arg(number).arg(tracksCount));
181 }
182 }
183
184 if (number % 10 != 0) {
185 coreLog.trace(QString("Variant tracks processed: %1/%2").arg(number).arg(tracksCount));
186 }
187 }
188
updateScheme(U2OpStatus & os) const189 void MysqlUpgraderFrom_1_16_To_1_24::updateScheme(U2OpStatus &os) const {
190 coreLog.trace("Scheme updating");
191 U2SqlQuery("ALTER TABLE VariantTrack DROP COLUMN fileHeader;", dbi->getDbRef(), os).execute();
192 }
193
addStringAttribute(U2OpStatus & os,const U2VariantTrack & variantTrack,const QString & attributeName,const QString & attributeValue) const194 void MysqlUpgraderFrom_1_16_To_1_24::addStringAttribute(U2OpStatus &os, const U2VariantTrack &variantTrack, const QString &attributeName, const QString &attributeValue) const {
195 CHECK(!attributeValue.isEmpty(), );
196 U2StringAttribute attribute;
197 U2AttributeUtils::init(attribute, variantTrack, attributeName);
198 attribute.value = attributeValue;
199 dbi->getAttributeDbi()->createStringAttribute(attribute, os);
200 }
201
splitFileHeader(const QString & fileHeader,QString & metaInfo,QStringList & header)202 void MysqlUpgraderFrom_1_16_To_1_24::splitFileHeader(const QString &fileHeader, QString &metaInfo, QStringList &header) {
203 const QStringList lines = fileHeader.split(QRegExp("\\n\\r?"), QString::SkipEmptyParts);
204 foreach (const QString &line, lines) {
205 if (line.startsWith(META_INFO_MARKER)) {
206 metaInfo += line + "\n";
207 } else if (line.startsWith(HEADER_MARKER)) {
208 header = line.split(COLUMN_SEPARATOR);
209 }
210 }
211 }
212
213 } // namespace U2
214