App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Database/Create.pm  view on Meta::CPAN

# DATABASE_SCHEMA_VERSION revisions
#
# Schema 1, version 99.015
#   - "latest" - fetch_timestamp rather than fetch_unixtime
#   - "intraday_image" - fetch_timestamp likewise
#   - "extra" - timestamp strings rather than unixtime numbers
#   - "info" - new exchange column
#   
# Schema 2, version 99.023
#   - "preference" - missed PRIMARY KEY
#
sub upgrade_database {
  my ($dbh, $dbversion) = @_;
  print "Chart: Upgrading database from $dbversion to ",
    App::Chart::DBI::DATABASE_SCHEMA_VERSION(),"\n";
  require App::Chart::Download;

  App::Chart::Database::call_with_transaction
      ($dbh, sub {
         # version 1 adopting timestamps instead of unixtime
         if ($dbversion <= 0) { _upgrade_0_to_1 ($dbh); }
         if ($dbversion <= 1) { _upgrade_1_to_2 ($dbh); }

         $dbh->do ("INSERT OR REPLACE INTO extra (symbol,key,value)
                    VALUES ('','database-schema-version',?)",
                   undef,
                   App::Chart::DBI::DATABASE_SCHEMA_VERSION());
       });
}
sub _upgrade_0_to_1 {
  my ($dbh) = @_;
  $dbh->do ('ALTER TABLE info ADD COLUMN
                      exchange TEXT DEFAULT NULL');

  $dbh->do ('DROP TABLE latest');
  $dbh->do ($create_latest);

  $dbh->do ('DROP TABLE intraday_image');
  $dbh->do ($create_intraday_image);

  $dbh->do ("DELETE FROM extra WHERE key like '%unixtime'");
  App::Chart::Download::consider_latest_from_daily
      ([ App::Chart::Database->symbols_list() ]);
}
sub _upgrade_1_to_2 {
  my $nbh = nbh();
  $nbh->do ('DROP TABLE preference');
  $nbh->do ($create_preference);
}


# $database_filename is in filesystem charset bytes
sub initial_database {
  my ($database_filename) = @_;
  print __x("Creating {filename}\n",
            filename => Glib::filename_display_name($database_filename));

  File::Path::mkpath (File::Basename::dirname ($database_filename));
  my $dbh = DBI->connect ("dbi:SQLite:dbname=$database_filename",
                       '', '', {RaiseError=>1});
  $dbh->{sqlite_unicode} = 1;

  $dbh->do ('PRAGMA encoding = "UTF-8"');

  $dbh->do (<<'HERE');
CREATE TABLE daily (
    symbol  TEXT     NOT NULL,
    date    DATE     NOT NULL,
    open    TEXT     DEFAULT NULL,
    high    TEXT     DEFAULT NULL,
    low     TEXT     DEFAULT NULL,
    close   TEXT     DEFAULT NULL,
    volume  TEXT     DEFAULT NULL,
    openint TEXT     DEFAULT NULL,
    PRIMARY KEY (symbol, date))
HERE

# 'exchange' is for yahoo index and US symbols to differentiate NYSE, AMEX,
# NASDAQ, Philadelphia, etc, for other symbols the suffix gives the exchange
#
  $dbh->do (<<'HERE');
CREATE TABLE info (
    symbol     TEXT     NOT NULL       PRIMARY KEY,
    name       TEXT     DEFAULT NULL,
    exchange   TEXT     DEFAULT NULL,
    isin       TEXT     DEFAULT NULL,
    decimals   INT      DEFAULT 0      NOT NULL,
    currency   TEXT     DEFAULT NULL,
    historical BOOLEAN  DEFAULT 0      NOT NULL,
    CHECK (decimals >= 0))
HERE

# 'type' is meant to allow multiple flavours on the same day, like a capital
# return and a dividend.  Empty string '' for ordinary dividends.  (It's not
# NULL because a null in a primary key defeats the uniqueness (you can
# insert multiple symbol+ex_date with type=null).
#
# 'qualifier' values:
#    TBA          with amount NULL
#    estimated    when amount present, but only estimated
#    unknown      when outright unknown, with amount NULL
#
  $dbh->do (<<'HERE');
CREATE TABLE dividend (
    symbol          TEXT     NOT NULL,
    ex_date         DATE     NOT NULL,
    record_date     DATE     DEFAULT NULL,
    pay_date        DATE     DEFAULT NULL,
    type            TEXT     NOT NULL DEFAULT '',
    amount          TEXT,
    imputation      TEXT     DEFAULT NULL,
    qualifier       TEST     DEFAULT NULL,
    note            TEXT     DEFAULT NULL,
    PRIMARY KEY (symbol, ex_date, type))
HERE

  $dbh->do (<<'HERE');
CREATE TABLE split (
    symbol TEXT     NOT NULL,
    date   DATE     NOT NULL,
    new    TEXT     NOT NULL,  -- number
    old    TEXT     NOT NULL,  -- number
    note   TEXT     DEFAULT NULL,
    PRIMARY KEY (symbol, date))
HERE

  $dbh->do ($create_latest);

  $dbh->do ($create_intraday_image);

  $dbh->do (<<'HERE');
CREATE TABLE extra (
    symbol        TEXT  NOT NULL,
    key           TEXT  NOT NULL,
    value         TEXT,
    PRIMARY KEY (symbol, key))
HERE

  $dbh->do ("INSERT INTO extra (symbol,key,value)
             VALUES ('','database-schema-version',?)",
            undef,
            App::Chart::DBI::DATABASE_SCHEMA_VERSION());
}

sub nbh {
  require App::Chart::DBI;
  my $notes_filename = App::Chart::DBI::notes_filename();
  File::Path::mkpath (File::Basename::dirname ($notes_filename));
  return DBI->connect ("dbi:SQLite:dbname=$notes_filename",
                       '', '', {RaiseError=>1});
}

# $notes_filename is in filesystem charset bytes
sub initial_notes {
  my ($notes_filename) = @_;
  print __x("Creating {filename}\n",
            filename => Glib::filename_display_name($notes_filename));

  my $nbh = nbh();
  $nbh->{sqlite_unicode} = 1;
  $nbh->do ('PRAGMA encoding = "UTF-8"');

  $nbh->do ($create_preference);

  $nbh->do (<<'HERE');
CREATE TABLE annotation (
    symbol     TEXT     NOT NULL,
    id         INT      NOT NULL,
    date       DATE     NOT NULL,
    note       TEXT     NOT NULL,
    PRIMARY KEY (symbol, id))
HERE

  $nbh->do (<<'HERE');
CREATE TABLE line (
    symbol     TEXT     NOT NULL,
    id         INT      NOT NULL,
    date1      DATE     NOT NULL,
    price1     TEXT     NOT NULL,
    date2      DATE     NOT NULL,
    price2     TEXT     NOT NULL,
    horizontal BOOLEAN  NOT NULL  DEFAULT 0,
    PRIMARY KEY (symbol, id))
HERE

  $nbh->do (<<'HERE');
CREATE TABLE alert (
    symbol     TEXT     NOT NULL,
    id         INT      NOT NULL,
    price      TEXT     NOT NULL,
    above      BOOLEAN  NOT NULL,
    PRIMARY KEY (symbol, id))
HERE

  # Ought to have "symlist.key" unique and NOT NULL, and the intention is
  # for "symlist_content.symbol" to be NOT NULL too, but it's easier for
  # treeview drag and drop to loosen both those, so it can insert an empty,
  # set it to a copy of the source, then delete the source.
  #
  # The symlist key lookups are mostly done in-memory, so don't really need
  # an index.  Or maybe should have it for the REFERENCES constraint, except
  # that's not enforced by sqlite anyway.
  #
  # CREATE INDEX symlist_key_index ON symlist (key)
  #
  $nbh->do (<<'HERE');
CREATE TABLE symlist (
    seq        INT      NOT NULL,
    key        TEXT     DEFAULT NULL,
    name       TEXT     DEFAULT NULL,
    condition  TEXT     DEFAULT NULL,
    PRIMARY KEY (seq))
HERE

  $nbh->do (<<'HERE');
CREATE TABLE symlist_content (
    key        TEXT     NOT NULL  REFERENCES symlist,
    seq        INT      NOT NULL,
    symbol     TEXT     DEFAULT NULL,
    note       TEXT     DEFAULT NULL,



( run in 0.533 second using v1.01-cache-2.11-cpan-39bf76dae61 )