OHI Value-Based Payments
 PreviousHomeNext 
3.1.2 Run InstallerBook Index3.2 Install Application

3.1.3 Enable Total Recall (optional)

When Total Recall Option is activated, you should decide if one or more of the new tables should be added to a Flashback Data Archive.

Syntax to enable history tracking for a table is:

ALTER TABLE <tablename> FLASHBACK ARCHIVE [<Flashback Data Archive name>];

Note that the FDA name is required only when adding the table to a non-default FDA.

To disable history tracking for a table use:

ALTER TABLE <tablename> NO FLASHBACK ARCHIVE;

For convenience, we provide an example script that can help configuring archived tables:

import groovy.sql.Sql
import java.util.logging.*

def logger = Logger.getLogger(this.class.getName());

def config = new Config(args, 'setFlashbackArchive.cfg')
// Override the default level for the top-level logger
Logger.getLogger("").setLevel(config.log.level);
config.log()

def db = Sql.newInstance( config.db.url
                        , config.db.user
                        , config.db.passwd
                        , 'oracle.jdbc.driver.OracleDriver')
this.db = db

// Get the set of tables For which FBA needs to be switched off
def getTablesToSwitchOff(tables) {
    def tableList = tables.join("', '")
    switch_off = db.rows("""select fba.owner_name as owner
                            ,      fba.table_name
                            from   dba_flashback_archive_tables fba
                            where  fba.status = 'ENABLED'
                            and    fba.owner_name||'.'||fba.table_name not in ('""" + tableList + """')
                        """)
}

for (table in config.flashback.tables) {
    switch_on = db.firstRow("""select fba.owner_name as owner
                               ,      fba.table_name
                               from   dba_flashback_archive_tables fba
                               where  fba.owner_name||'.'||fba.table_name = $table
                               and    (  fba.status is null
                                      or fba.status != 'ENABLED'
                                      )
                            """)
    if (switch_on) {
        logger.info "Switching Flashback Archiving on for table ${table}"
        def stmt = "alter table " + table + " flashback archive ${config.flashback.archive}"
        try {
            println stmt
            db.execute(stmt)
        } catch (java.sql.SQLException e) {
            logger.warning "Error occurred while executing SQL " + stmt
            logger.warning "Error was " + e.getMessage()
            println "Unable to set Flashback Archive to ${config.flashback.archive} for table ${table} " + e.getMessage()
            println "Press enter to continue"
            new InputStreamReader(System.in).readLine()
        }
    }
}

// For every table that is not in the config-list but has FBA turned on, a confirmation is asked before actually
// turning off FBA
getTablesToSwitchOff(config.flashback.tables).each { it ->
    def tableName = "${it.owner}.${it.table_name}"
    println "Switching Flashback Archiving OFF for table ${tableName}"
    println "Are you sure you want to do that? This will purge all history for this table!! (Y/N)"
    response = new InputStreamReader(System.in).readLine()
    while (response.toUpperCase() != "Y" && response.toUpperCase() != "N") {
        println "Please respond with \"Y\" or \"N\""
        response = new InputStreamReader(System.in).readLine()
    }
    if (response.toUpperCase() == "Y") {
        def stmt = "alter table " + tableName + " no flashback archive"
        try {
            println stmt
            db.execute(stmt)
            logger.warning "Flashback Archiving was switched off for table ${tableName} as per users request"
        } catch (java.sql.SQLException e) {
            logger.warning "Error occurred while executing SQL " + stmt
            logger.warning "Error was " + e.getMessage()
            println "Unable to switch off Flashback Archive for table ${tableName} " + e.getMessage()
            println "Press enter to continue"
            new InputStreamReader(System.in).readLine()
        }
    } else {
        println "Flashback Archiving was NOT switched off for table ${tableName}."
        logger.warning "Flashback Archiving was NOT switched off for table ${tableName} as per users request"
    }
}

class Config {
  private static Logger logger = Logger.getLogger(Config.class.getName())
  def configFile
  def db = [:]
  def log = [:]
  def flashback
  
  def Config(args, configFile) {
    this.configFile = configFile
    def parsedConfig
    def cl = new CliBuilder(usage:
             'setFlashbackArchive.groovy [-c configFile]')

    cl.h(longOpt:'help', 'Show usage information and quit')
    cl.c(argName:'configFile', longOpt:'cfg', args:1, required:false, 'Config file, default is ' + configFile)

    def opt = cl.parse(args)

    if (!opt) {
      // the parse failed, the usage will be shown automatically
      println "\nInvalid command line, exiting..."
      System.exit(-1)
    } else if (opt.h) {
      cl.usage()
      System.exit(0)
    }

    if (opt.c) {
      this.configFile = opt.c
    }
    try {
      parsedConfig = new ConfigSlurper().parse(new File(this.configFile).toURL())
    } catch (FileNotFoundException e) {
      logger.severe "Config file ${this.configFile} not found"
      System.exit(-1)
    }
    db = parsedConfig.db
    db.url = db.protocol + "//" + db.hostname + ":"  + db.port + "/"  + db.sid
    log = parsedConfig.log
    flashback = parsedConfig.flashback
    if (!flashback) {
      println("\nflashback is not set in Config file")
      System.exit(-1)
    }
  }
  
  def log() {
    logger.config "db=" + db.toString()
  }
}

This script works in conjunction with a configuration file that can be created by copying the following to a file named setFlashbackArchive.cfg and changing its settings to appropriate values:

import java.util.logging.Level
// Allowable values: SEVERE | WARNING | INFO | CONFIG | FINE | FINER | FINEST  
log.level = Level.INFO

// user has to be a database user with the FLASHBACK ARCHIVE object privilege granted
// on the Archive used.
db {
  protocol = 'jdbc:oracle:thin:@'
  hostname = '<your hostname>'
  port     = '<your port>'
  sid      = '<your sid>'
  user     = '<your dbuser>'
  passwd   = '<your dbpassword>'
}

// This Flashback Archive has to exist.
// It can be created by a SYSDBA or a user with
// The tables argument contains a list of tables that should be archived. 
// If you remove a table from this list, archiving will be disabled.
flashback {
    archive = '<name of your FlashBack Archive>'
    tables = ['<owner.table1>', '<owner.table2>']
}

The script can be run using Groovy (groovy <scriptname>)

 PreviousHomeNext 
3.1.2 Run Installer3.2 Install Application