001/*
002 * #%L
003 * Netarchivesuite - harvester
004 * %%
005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.harvester.datamodel;
025
026import java.sql.Connection;
027import java.sql.SQLException;
028
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032import dk.netarkivet.common.CommonSettings;
033import dk.netarkivet.common.exceptions.ArgumentNotValid;
034import dk.netarkivet.common.exceptions.IOFailure;
035import dk.netarkivet.common.exceptions.IllegalState;
036import dk.netarkivet.common.exceptions.NotImplementedException;
037import dk.netarkivet.common.utils.DBUtils;
038import dk.netarkivet.common.utils.SettingsFactory;
039
040/**
041 * Defines database specific implementations used by the Harvester.
042 * <p>
043 * The actual actual implementation which is loaded is defined by the {@link CommonSettings#DB_SPECIFICS_CLASS} setting.
044 * See the sub class list for available implementations
045 */
046public abstract class DBSpecifics extends SettingsFactory<DBSpecifics> {
047
048    /** The instance of the DBSpecifics class. */
049    private static DBSpecifics instance;
050
051    private static final Logger log = LoggerFactory.getLogger(DBSpecifics.class);
052
053    /**
054     * Get the singleton instance of the DBSpecifics implementation class.
055     *
056     * @return An instance of DBSpecifics with implementations for a given DB.
057     */
058    public static synchronized DBSpecifics getInstance() {
059        if (instance == null) {
060            instance = getInstance(CommonSettings.DB_SPECIFICS_CLASS);
061        }
062        return instance;
063    }
064
065    /**
066     * Get a temporary table for short-time use. The table should be disposed of with dropTemporaryTable. The table has
067     * two columns domain_name varchar(Constants.MAX_NAME_SIZE) + config_name varchar(Constants.MAX_NAME_SIZE) All rows
068     * in the table must be deleted at commit or rollback.
069     *
070     * @param c The DB connection to use.
071     * @return The name of the created table
072     * @throws SQLException if there is a problem getting the table.
073     */
074    public abstract String getJobConfigsTmpTable(Connection c) throws SQLException;
075
076    /**
077     * Dispose of a temporary table gotten with getTemporaryTable. This can be expected to be called from within a
078     * finally clause, so it mustn't throw exceptions.
079     *
080     * @param c The DB connection to use.
081     * @param tableName The name of the temporarily created table.
082     */
083    public abstract void dropJobConfigsTmpTable(Connection c, String tableName);
084
085    /**
086     * Get the name of the JDBC driver class that handles interfacing to this server.
087     *
088     * @return The name of a JDBC driver class
089     */
090    public abstract String getDriverClassName();
091
092    /**
093     * Update a table to a newer version, if necessary. This will check the schemaversions table to see the current
094     * version and perform a table-specific update if required.
095     *
096     * @param tableName The table to update
097     * @param toVersion The version to update the table to.
098     * @throws IllegalState If the table is an unsupported version, and the toVersion is less than the current version
099     * of the table
100     * @throws NotImplementedException If no method exists for migration from current version of the table to the
101     * toVersion of the table.
102     * @throws IOFailure in case of problems in interacting with the database
103     */
104
105    public synchronized void updateTable(String tableName, int toVersion) {
106        ArgumentNotValid.checkNotNullOrEmpty(tableName, "String tableName");
107        ArgumentNotValid.checkPositive(toVersion, "int toVersion");
108
109        Connection c = HarvestDBConnection.get();
110        int currentVersion = -1;
111        try {
112            currentVersion = DBUtils.getTableVersion(c, tableName);
113        } finally {
114            HarvestDBConnection.release(c);
115        }
116        if (currentVersion == toVersion) {
117            // Nothing to do. Version of table is already correct.
118            return;
119        }
120        log.info("Trying to migrate table '" + tableName + "' from version '" + currentVersion + "' to version '"
121                + toVersion + "'.");
122
123        if (currentVersion > toVersion) {
124            throw new IllegalState("Database is in an illegalState: The current version of table '" + tableName
125                    + "' is not acceptable (current version is greater than requested version).");
126        }
127
128        if (tableName.equals(HarvesterDatabaseTables.JOBS.getTablename())) {
129            upgradeJobsTable(currentVersion, toVersion);
130        } else if (tableName.equals(HarvesterDatabaseTables.FULLHARVESTS.getTablename())) {
131            upgradeFullharvestsTable(currentVersion, toVersion);
132        } else if (tableName.equals(HarvesterDatabaseTables.CONFIGURATIONS.getTablename())) {
133            upgradeConfigurationsTable(currentVersion, toVersion);
134        } else if (tableName.equals(HarvesterDatabaseTables.GLOBALCRAWLERTRAPLISTS.getTablename())) {
135            upgradeGlobalcrawlertraplistsTable(currentVersion, toVersion);
136        } else if (tableName.equals(HarvesterDatabaseTables.GLOBALCRAWLERTRAPEXPRESSIONS.getTablename())) {
137            upgradeGlobalcrawlertrapexpressionsTable(currentVersion, toVersion);
138        } else if (tableName.equals(HarvesterDatabaseTables.RUNNINGJOBSHISTORY.getTablename())) {
139            upgradeRunningjobshistoryTable(currentVersion, toVersion);
140        } else if (tableName.equals(HarvesterDatabaseTables.RUNNINGJOBSMONITOR.getTablename())) {
141            upgradeRunningjobsmonitor(currentVersion, toVersion);
142        } else if (tableName.equals(HarvesterDatabaseTables.FRONTIERREPORTMONITOR.getTablename())) {
143            upgradeFrontierreportmonitorTable(currentVersion, toVersion);
144        } else if (tableName.equals(HarvesterDatabaseTables.EXTENDEDFIELD.getTablename())) {
145            upgradeExtendedFieldTable(currentVersion, toVersion);
146        } else if (tableName.equals(HarvesterDatabaseTables.EXTENDEDFIELDVALUE.getTablename())) {
147            upgradeExtendedFieldValueTable(currentVersion, toVersion);
148        } else if (tableName.equals(HarvesterDatabaseTables.EXTENDEDFIELDTYPE.getTablename())) {
149            upgradeExtendedFieldTypeTable(currentVersion, toVersion);
150        } else if (tableName.equals(HarvesterDatabaseTables.DOMAINS.getTablename())) {
151            upgradeDomainsTable(currentVersion, toVersion);
152        } else if (tableName.equals(HarvesterDatabaseTables.HARVESTDEFINITIONS.getTablename())) {
153            upgradeHarvestdefinitionsTable(currentVersion, toVersion);
154        } else if (tableName.equals(HarvesterDatabaseTables.ORDERTEMPLATES.getTablename())) {
155            upgradeOrderTemplatesTable(currentVersion, toVersion);
156        } else if (tableName.equals(HarvesterDatabaseTables.HARVESTCHANNELS.getTablename())) {
157            upgradeHarvestchannelTable(currentVersion, toVersion);
158        } else if (tableName.equals(HarvesterDatabaseTables.EAVTYPEATTRIBUTE.getTablename())) {
159            upgradeEavTypeAttributeTable(currentVersion, toVersion);
160        } else if (tableName.equals(HarvesterDatabaseTables.EAVATTRIBUTE.getTablename())) {
161            upgradeEavAttributeTable(currentVersion, toVersion);
162        } else {
163            // Add new if else when other tables need to be upgraded
164            throw new NotImplementedException("No method exists for migrating table '" + tableName + "' to version "
165                    + toVersion);
166        }
167    }
168
169    private void upgradeOrderTemplatesTable (int currentVersion, int toVersion) {
170        if (currentVersion == 1 && toVersion == 2 ) {
171            migrateOrderTemplatesTablev1tov2();
172            currentVersion = 2;
173        }
174         // insert new migrations here
175        if (currentVersion != HarvesterDatabaseTables.ORDERTEMPLATES.getRequiredVersion()) {
176            throw new NotImplementedException("No method exists for migrating table '"
177                    + HarvesterDatabaseTables.ORDERTEMPLATES.getTablename() + "' from version " + currentVersion
178                    + " to version " + toVersion);
179        }
180    }
181
182    private void upgradeHarvestdefinitionsTable(int currentVersion, int toVersion) {
183        if (currentVersion < 2) {
184            throw new IllegalState("Database is in an illegalState: The current version " + currentVersion
185                    + " of table '" + HarvesterDatabaseTables.HARVESTDEFINITIONS.getTablename()
186                    + "' is not acceptable. The current table version is less than open source version 2. "
187                    + "Probably a wrong entry in the schemaversions table");
188        }
189        if (currentVersion == 2 && toVersion >= 3) {
190            migrateHarvestdefinitionsv2tov3();
191            currentVersion = 3;
192        }
193        if (currentVersion == 3 && toVersion >= 4) {
194            migrateHarvestdefinitionsv3tov4();
195            currentVersion = 4;
196        }
197        // insert new migrations here
198        if (currentVersion != HarvesterDatabaseTables.HARVESTDEFINITIONS.getRequiredVersion()) {
199            throw new NotImplementedException("No method exists for migrating table '"
200                    + HarvesterDatabaseTables.HARVESTDEFINITIONS.getTablename() + "' from version " + currentVersion
201                    + " to version " + toVersion);
202        }
203
204    }
205
206    private void upgradeExtendedFieldTypeTable(int currentVersion, int toVersion) {
207        if (currentVersion == 0 && toVersion >= 1) {
208            createExtendedFieldTypeTable();
209            currentVersion = 1;
210        }
211        if (currentVersion > HarvesterDatabaseTables.EXTENDEDFIELDTYPE.getRequiredVersion()) {
212            throw new NotImplementedException("No method exists for migrating table '"
213                    + HarvesterDatabaseTables.EXTENDEDFIELDTYPE.getTablename() + "' from version " + currentVersion
214                    + " to version " + toVersion);
215        }
216    }
217
218    private void upgradeExtendedFieldValueTable(int currentVersion, int toVersion) {
219        if (currentVersion == 0 && toVersion >= 1) {
220            createExtendedFieldValueTable();
221            currentVersion = 1;
222        }
223        if (currentVersion == 1 && toVersion >= 2) {
224            migrateExtendedFieldTableValueV1toV2();
225            currentVersion = 2;
226        }
227
228        if (currentVersion > HarvesterDatabaseTables.EXTENDEDFIELDVALUE.getRequiredVersion()) {
229            throw new NotImplementedException("No method exists for migrating table '"
230                    + HarvesterDatabaseTables.EXTENDEDFIELDVALUE.getTablename() + "' from version " + currentVersion
231                    + " to version " + toVersion);
232        }
233    }
234
235    private void upgradeExtendedFieldTable(int currentVersion, int toVersion) {
236        if (currentVersion == 0 && toVersion >= 1) {
237            createExtendedFieldTable();
238            currentVersion = 1;
239        }
240        if (currentVersion == 1 && toVersion >= 2) {
241            migrateExtendedFieldTableV1toV2();
242            currentVersion = 2;
243        }
244        if (currentVersion > HarvesterDatabaseTables.EXTENDEDFIELD.getRequiredVersion()) {
245            throw new NotImplementedException("No method exists for migrating table '"
246                    + HarvesterDatabaseTables.EXTENDEDFIELD.getTablename() + "' from version " + currentVersion
247                    + " to version " + toVersion);
248        }
249    }
250
251    /**
252     * Migrate the frontierreportmonitor table.
253     *
254     * @param currentVersion the current version of the frontierreportmonitor table
255     * @param toVersion the required version of the frontierreportmonitor table
256     */
257    private void upgradeFrontierreportmonitorTable(int currentVersion, int toVersion) {
258        if (currentVersion == 0 && toVersion == 1) {
259            createFrontierReportMonitorTable();
260            currentVersion = 1;
261        }
262        // insert new migrations here
263        if (currentVersion > HarvesterDatabaseTables.FRONTIERREPORTMONITOR.getRequiredVersion()) {
264            throw new NotImplementedException("No method exists for migrating table '"
265                    + HarvesterDatabaseTables.FRONTIERREPORTMONITOR.getTablename() + "' from version " + currentVersion
266                    + " to version " + toVersion);
267        }
268    }
269
270    /**
271     * Migrate the runningjobsmonitor table.
272     *
273     * @param currentVersion the current version of the runningjobsmonitor table
274     * @param toVersion the required version of the runningjobsmonitor table
275     */
276    private void upgradeRunningjobsmonitor(int currentVersion, int toVersion) {
277        if (currentVersion == 0 && toVersion >= 1) {
278            createRunningJobsMonitorTable();
279            currentVersion = 1;
280        }
281        if (currentVersion == 1 && toVersion >= 2) {
282            migrateRunningJobsMonitorTableV1ToV2();
283            currentVersion = 2;
284        }
285        if (currentVersion > HarvesterDatabaseTables.RUNNINGJOBSMONITOR.getRequiredVersion()) {
286            throw new NotImplementedException("No method exists for migrating table '"
287                    + HarvesterDatabaseTables.RUNNINGJOBSMONITOR.getTablename() + "' from version " + currentVersion
288                    + " to version " + toVersion);
289        }
290    }
291
292    /**
293     * Migrate the runningjobshistory table.
294     *
295     * @param currentVersion the current version of the runningjobshistory table
296     * @param toVersion The required version of the runningjobshistory table
297     */
298    private void upgradeRunningjobshistoryTable(int currentVersion, int toVersion) {
299        if (currentVersion == 0 && toVersion >= 1) {
300            createRunningJobsHistoryTable();
301            currentVersion = 1;
302        }
303        if (currentVersion == 1 && toVersion >= 2) {
304            migrateRunningJobsHistoryTableV1ToV2();
305            currentVersion = 2;
306        }
307        // insert new migrations here
308        if (currentVersion > HarvesterDatabaseTables.RUNNINGJOBSHISTORY.getRequiredVersion()) {
309            throw new NotImplementedException("No method exists for migrating table '"
310                    + HarvesterDatabaseTables.RUNNINGJOBSHISTORY.getTablename() + "' from version " + currentVersion
311                    + " to version " + toVersion);
312        }
313
314    }
315
316    /**
317     * Migrate the globalecrawlertrapexpressions table.
318     *
319     * @param currentVersion the current version of the jobs table
320     * @param toVersion The required version of the jobs table
321     */
322    private void upgradeGlobalcrawlertrapexpressionsTable(int currentVersion, int toVersion) {
323        if (currentVersion == 0 && toVersion >= 1) {
324            createGlobalCrawlerTrapExpressions();
325            currentVersion = 1;
326        }
327        // insert new migrations here
328        if (currentVersion > HarvesterDatabaseTables.GLOBALCRAWLERTRAPEXPRESSIONS.getRequiredVersion()) {
329            throw new NotImplementedException("No method exists for migrating table '"
330                    + HarvesterDatabaseTables.GLOBALCRAWLERTRAPEXPRESSIONS.getTablename() + "' from version "
331                    + currentVersion + " to version " + toVersion);
332        }
333
334    }
335
336    /**
337     * Migrate the globalecrawlertraplists table.
338     *
339     * @param currentVersion the current version of the globalecrawlertraplists table
340     * @param toVersion The required version of the globalecrawlertraplists table
341     */
342    private void upgradeGlobalcrawlertraplistsTable(int currentVersion, int toVersion) {
343        if (currentVersion == 0 && toVersion >= 1) {
344            createGlobalCrawlerTrapLists();
345            currentVersion = 1;
346        }
347        // insert new migrations here
348        if (currentVersion > HarvesterDatabaseTables.GLOBALCRAWLERTRAPLISTS.getRequiredVersion()) {
349            throw new NotImplementedException("No method exists for migrating table '"
350                    + HarvesterDatabaseTables.GLOBALCRAWLERTRAPLISTS.getTablename() + "' from version "
351                    + currentVersion + " to version " + toVersion);
352        }
353
354    }
355
356    /**
357     * Migrate the jobs table.
358     *
359     * @param currentVersion the current version of the jobs table
360     * @param toVersion The required version of the jobs table
361     */
362    private void upgradeJobsTable(int currentVersion, int toVersion) {
363        if (currentVersion < 3) {
364            throw new IllegalState("Database is in an illegalState: " + "The current version " + currentVersion
365                    + " of table '" + HarvesterDatabaseTables.JOBS.getTablename() + "' is not acceptable. "
366                    + "(current version is less than open source version).");
367        }
368        if (currentVersion == 3 && toVersion >= 4) {
369            migrateJobsv3tov4();
370            currentVersion = 4;
371        }
372        if (currentVersion == 4 && toVersion >= 5) {
373            migrateJobsv4tov5();
374            currentVersion = 5;
375        }
376        if (currentVersion == 5 && toVersion >= 6) {
377            migrateJobsv5tov6();
378            currentVersion = 6;
379        }
380        if (currentVersion == 6 && toVersion >= 7) {
381            migrateJobsv6tov7();
382            currentVersion = 7;
383        }
384        if (currentVersion == 7 && toVersion >= 8) {
385            migrateJobsv7tov8();
386            currentVersion = 8;
387        }
388        if (currentVersion == 8 && toVersion >= 9) {
389            migrateJobsv8tov9();
390            currentVersion = 9;
391        }
392        if (currentVersion == 9 && toVersion >= 10) {
393            migrateJobsv9tov10();
394            currentVersion = 10;
395        }
396        // future updates of the jobs table are inserted here
397        if (currentVersion == HarvesterDatabaseTables.JOBS.getRequiredVersion()
398                && toVersion >= HarvesterDatabaseTables.JOBS.getRequiredVersion() + 1) {
399            throw new NotImplementedException("No method exists for migrating table '"
400                    + HarvesterDatabaseTables.JOBS.getTablename() + "' from version " + currentVersion + " to version "
401                    + toVersion);
402        }
403
404        if (currentVersion > HarvesterDatabaseTables.JOBS.getRequiredVersion()) {
405            throw new IllegalState("Database is in an illegalState: " + "The current version (" + currentVersion
406                    + ") of table '" + HarvesterDatabaseTables.JOBS.getTablename()
407                    + "' is not an acceptable/known version. ");
408        }
409    }
410
411    /**
412     * Migrate the configurations table.
413     *
414     * @param currentVersion the current version of the configurations table
415     * @param toVersion the required version of the configurations table
416     */
417    private void upgradeConfigurationsTable(int currentVersion, int toVersion) {
418        if (currentVersion < 3) {
419            throw new IllegalState("Database is in an illegalState: " + "The current version " + currentVersion
420                    + " of table '" + HarvesterDatabaseTables.CONFIGURATIONS.getTablename() + "' is not acceptable. "
421                    + "(current version is less than open source version).");
422        }
423        if (currentVersion == 3 && toVersion >= 4) {
424            migrateConfigurationsv3ov4();
425            currentVersion = 4;
426        }
427
428        if (currentVersion == 4 && toVersion >= 5) {
429            migrateConfigurationsv4tov5();
430            currentVersion = 5;
431        }
432        // insert future migrations here
433        if (currentVersion == HarvesterDatabaseTables.CONFIGURATIONS.getRequiredVersion()
434                && toVersion >= HarvesterDatabaseTables.CONFIGURATIONS.getRequiredVersion() + 1) {
435            throw new NotImplementedException("No method exists for migrating table '"
436                    + HarvesterDatabaseTables.CONFIGURATIONS.getTablename() + "' from version " + currentVersion
437                    + " to version " + toVersion);
438        }
439
440        if (currentVersion > HarvesterDatabaseTables.CONFIGURATIONS.getRequiredVersion()) {
441            throw new IllegalState("Database is in an illegalState: " + "The current version (" + currentVersion
442                    + ") of table '" + HarvesterDatabaseTables.CONFIGURATIONS.getTablename()
443                    + "' is not an acceptable/known version. ");
444        }
445    }
446
447    private void upgradeDomainsTable(int currentVersion, int toVersion) {
448        if (currentVersion < 2) {
449            throw new IllegalState("Database is in an illegalState: " + "The current version " + currentVersion
450                    + " of table '" + HarvesterDatabaseTables.DOMAINS.getTablename() + "' is not acceptable. "
451                    + "(current version is less than open source version).");
452        }
453        if (currentVersion == 2 && toVersion >= 3) {
454            migrateDomainsv2tov3();
455            currentVersion = 3;
456        }
457    }
458
459    /**
460     * Migrate the fullharvests table.
461     *
462     * @param currentVersion the current version of the fullharvests table
463     * @param toVersion the required version of the fullharvests table
464     */
465    private void upgradeFullharvestsTable(int currentVersion, int toVersion) {
466        if (currentVersion < 2) {
467            throw new IllegalState("Database is in an illegalState: " + "The current version " + currentVersion
468                    + " of table '" + HarvesterDatabaseTables.FULLHARVESTS.getTablename() + "' is not acceptable. "
469                    + "(current version is less than open source version).");
470        }
471        if (currentVersion == 2 && toVersion >= 3) {
472            migrateFullharvestsv2tov3();
473            currentVersion = 3;
474        }
475
476        if (currentVersion == 3 && toVersion >= 4) {
477            migrateFullharvestsv3tov4();
478            currentVersion = 4;
479        }
480
481        if (currentVersion == 4 && toVersion >= 5) {
482            migrateFullharvestsv4tov5();
483            currentVersion = 5;
484        }
485
486        // insert future migrations here
487        if (currentVersion == HarvesterDatabaseTables.FULLHARVESTS.getRequiredVersion()
488                && toVersion >= HarvesterDatabaseTables.FULLHARVESTS.getRequiredVersion() + 1) {
489            throw new NotImplementedException("No method exists for migrating table '"
490                    + HarvesterDatabaseTables.FULLHARVESTS.getTablename() + "' from version " + currentVersion
491                    + " to version " + toVersion);
492        }
493    }
494
495    /**
496     * Migrate the harvestchannel table.
497     *
498     * @param currentVersion the current version of the harvestchannel table
499     * @param toVersion the required version of the harvestchannel table
500     */
501    private void upgradeHarvestchannelTable(int currentVersion, int toVersion) {
502        if (currentVersion == 0 && toVersion >= 1) {
503            createHarvestChannelTable();
504            currentVersion = 1;
505        }
506    }
507
508    protected abstract void createHarvestChannelTable();
509
510    /**
511     * Migrates the 'jobs' table from version 3 to version 4 consisting of a change of the field forcemaxbytes from int
512     * to bigint and setting its default to -1. Furthermore the default value for field num_configs is set to 0.
513     *
514     * @throws IOFailure in case of problems in interacting with the database
515     */
516    protected abstract void migrateJobsv3tov4();
517
518    /**
519     * Migrates the 'jobs' table from version 4 to version 5 consisting of adding new fields 'resubmitted_as_job' and
520     * 'submittedDate'.
521     *
522     * @throws IOFailure in case of problems in interacting with the database
523     */
524    protected abstract void migrateJobsv4tov5();
525
526    /**
527     * Migrates the 'configurations' table from version 3 to version 4. This consists of altering the default value of
528     * field 'maxbytes' to -1.
529     */
530    protected abstract void migrateConfigurationsv3ov4();
531
532    /**
533     * Migrates the 'fullharvests' table from version 2 to version 3. This consists of altering the default value of
534     * field 'maxbytes' to -1.
535     */
536    protected abstract void migrateFullharvestsv2tov3();
537
538    /**
539     * Migrates the 'runningjobshistory' table from version 1 to version 2. This consists of adding the new column
540     * 'retiredQueuesCount'.
541     */
542    protected abstract void migrateRunningJobsHistoryTableV1ToV2();
543
544    /**
545     * Migrates the 'runningjobsmonitor' table from version 1 to version 2. This consists of adding the new column
546     * 'retiredQueuesCount'.
547     */
548    protected abstract void migrateRunningJobsMonitorTableV1ToV2();
549
550    /**
551     * Migrates the 'domains' table from version 2 to version 3. This consists of altering the type of the crawlertraps
552     * column to "text" in postgres, and noop in derbyDB
553     */
554    protected abstract void migrateDomainsv2tov3();
555
556    /**
557     * Creates the initial (version 1) of table 'global_crawler_trap_lists'.
558     */
559    protected abstract void createGlobalCrawlerTrapLists();
560
561    /**
562     * Creates the initial (version 1) of table 'global_crawler_trap_expressions'.
563     */
564    protected abstract void createGlobalCrawlerTrapExpressions();
565
566    /**
567     * Formats the LIMIT sub-clause of an SQL order clause. This sub-clause allows to paginate query results and its
568     * syntax might be dependant on the target RDBMS
569     *
570     * @param limit the maximum number of rows to fetch.
571     * @param offset the starting offset in the full query results.
572     * @return the proper sub-clause.
573     */
574    public abstract String getOrderByLimitAndOffsetSubClause(long limit, long offset);
575
576    /**
577     * Returns true if the target RDBMS supports CLOBs. If possible seedlists will be stored as CLOBs.
578     *
579     * @return true if CLOBs are supported, false otherwise.
580     */
581    public abstract boolean supportsClob();
582
583    /**
584     * Create the frontierReportMonitor table in the database.
585     */
586    public abstract void createFrontierReportMonitorTable();
587
588    /**
589     * Create the frontierReportMonitor table in the database.
590     */
591    public abstract void createRunningJobsHistoryTable();
592
593    /**
594     * Create the frontierReportMonitor table in the database.
595     */
596    public abstract void createRunningJobsMonitorTable();
597
598    /**
599     * Migrates the 'jobs' table from version 5 to version 6. Adds the field 'forcemaxrunningtime'.
600     *
601     * @throws IOFailure in case of problems in interacting with the database
602     */
603    protected abstract void migrateJobsv5tov6();
604
605    /**
606     * Migrates the 'configurations' table from version 4 to version 5. This consists of altering the field 'maxobjects'
607     * from being an int to a bigint.
608     */
609    protected abstract void migrateConfigurationsv4tov5();
610
611    /**
612     * Migrates the 'fullharvests' table from version 3 to version 4. This consists of adding the field
613     * 'maxjobrunningtime'.
614     */
615    protected abstract void migrateFullharvestsv3tov4();
616
617    /**
618     * Migrates the 'fullharvests' table from version 4 to version 5. This consists of adding the field 'isindexready'.
619     */
620    protected abstract void migrateFullharvestsv4tov5();
621
622    /**
623     * Create the extendedfieldtype table in the database.
624     */
625    protected abstract void createExtendedFieldTypeTable();
626
627    /**
628     * Create the extendedfield table in the database.
629     */
630    protected abstract void createExtendedFieldTable();
631
632    /**
633     * Create the extendedfieldvalue table in the database.
634     */
635    protected abstract void createExtendedFieldValueTable();
636
637    /**
638     * Migrates the 'jobs' table from version 6 to version 7 consisting of adding the bigint fieldcontinuationof with
639     * null as default.
640     */
641    protected abstract void migrateJobsv6tov7();
642
643    /**
644     * Migrates the 'jobs' table from version 7 to version 8 consisting of adding the date creationdate with null as
645     * default.
646     */
647    protected abstract void migrateJobsv7tov8();
648
649    /**
650     * Migrates the 'jobs' table from version 8 to version 9 consisting of adding the string harvestname_prefix with
651     * null as default.
652     */
653    protected abstract void migrateJobsv8tov9();
654
655    /**
656     * Migrates the 'harvestdefinitions' table from version 2 to version 3 consisting of adding the string audience with
657     * null as default.
658     */
659    protected abstract void migrateHarvestdefinitionsv2tov3();
660
661    /**
662     * Migrates the 'harvestdefinitions' table from version 3 to version 4 consisting of adding the bigint channel_id
663     * field.
664     */
665    protected abstract void migrateHarvestdefinitionsv3tov4();
666
667    /**
668     * Migrates the 'jobs' table from version 9 to version 10 consisting of adding the channel (varchar 300) and a
669     * 'snapshot'
670     */
671    protected abstract void migrateJobsv9tov10();
672
673    /**
674     * Migrates the 'ExtendedFieldTable' from version 1 to version 2 consisting of adding the maxlen field
675     */
676    protected abstract void migrateExtendedFieldTableV1toV2();
677
678    /**
679     * Migrates the 'ExtendedFieldValueTable' from version 1 to version 2 changing the maxlen of content to 30000
680     */
681    protected abstract void migrateExtendedFieldTableValueV1toV2();
682
683    /**
684     * Migrates the table 'ordertemplates' from version 1 to version 2, adding a boolean 'isActive" flag.
685     */
686    protected abstract void migrateOrderTemplatesTablev1tov2();
687
688    /**
689     * Update all tables in the enum class {@link HarvesterDatabaseTables} to the required version. There is no attempt
690     * to undo the update.
691     */
692    public void updateTables() {
693        for (HarvesterDatabaseTables table : HarvesterDatabaseTables.values()) {
694            updateTable(table.getTablename(), table.getRequiredVersion());
695        }
696    }
697
698    /**
699     * Migrate the eavtypeattribute table.
700     * @param currentVersion the current version of the eavtypeattribute table
701     * @param toVersion the required version of the eavtypeattribute table
702     */
703    public void upgradeEavTypeAttributeTable(int currentVersion, int toVersion) {
704        if (currentVersion == 0 && toVersion >= 1) {
705                createEavTypeAttributeTable(1);
706            currentVersion = 1;
707        }
708        if (currentVersion > HarvesterDatabaseTables.EAVTYPEATTRIBUTE.getRequiredVersion()) {
709            throw new NotImplementedException("No method exists for migrating table '"
710                    + HarvesterDatabaseTables.EAVTYPEATTRIBUTE.getTablename() + "' from version " + currentVersion
711                    + " to version " + toVersion);
712        }
713    }
714
715    /**
716     * Create the EavTypeAttribute table in the database.
717     */
718    public abstract void createEavTypeAttributeTable(int toVersion);
719
720    /**
721     * Migrate the eavattribute table.
722     * @param currentVersion the current version of the eavattribute table
723     * @param toVersion the required version of the eavattribute table
724     */
725    public void upgradeEavAttributeTable(int currentVersion, int toVersion) {
726        if (currentVersion == 0 && toVersion >= 1) {
727                createEavAttributeTable(1);
728            currentVersion = 1;
729        }
730        if (currentVersion > HarvesterDatabaseTables.EAVATTRIBUTE.getRequiredVersion()) {
731            throw new NotImplementedException("No method exists for migrating table '"
732                    + HarvesterDatabaseTables.EAVATTRIBUTE.getTablename() + "' from version " + currentVersion
733                    + " to version " + toVersion);
734        }
735    }
736
737    /**
738     * Create the EavAttributeTable table in the database.
739     */
740    public abstract void createEavAttributeTable(int toVersion);
741
742}