#!/usr/bin/env ruby

#
# An Amalgalite example showing how Blob's can be utilized
#
# We'll make a database with one table, that we store files in.  We'll use the
# Blob incremental IO to store the files and retrieve them from the database
#
# This little program will store 1 or more files in the sqlite3 database when
# the 'store' action is given, and cat a file to stdout on 'retrieve'
#
# e.g.
#
#   ruby blob.rb store a.rb b.rb c.rb # => stores a.rb b.rb and c.rb in the db
#
#   ruby blob.rb retrieve a.rb        # => dumps a.rb to stdout
#

require 'rubygems'
$: << "../lib"
$: << "../ext"
require 'amalgalite'
require 'amalgalite/packer'
VALID_ACTIONS = %w[ list retrieve store ]
def usage 
  STDERR.puts "Usage: #{File.basename($0)} ( #{VALID_ACTIONS.join(' | ')} )  file(s)"
  exit 1
end

#
# This does the basic command line parsing
#
usage if ARGV.size < 1
action    = ARGV.shift
usage unless VALID_ACTIONS.include? action 
file_list = ARGV

#
# create the database if it doesn't exist
#
db = Amalgalite::Database.new( "filestore.db" )

case action
  #
  # list all the files that are stored in the database
  #
when 'list'
  db.execute("SELECT filename FROM rubylibs") do |row|
    puts row['filename']
  end

  #
  # if we are doing the store action, then loop over the files and store them in
  # the database.  This will use incremental IO to store the files directly from
  # the file names. 
  #
  # It is slightly strange in that you have to tell the Blob object what column
  # it is going to, but that is necessary at this point to be able to hook
  # automatically into the lower level incremental blob IO api.
  #
  # This also shows using the $var syntax for binding name sql values in a
  # prepared statement.
  #
when 'store'
  usage if file_list.empty?
  require 'amalgalite/packer'

  packer = Amalgalite::Packer.new( :dbfile => 'filestore.db',
                                   :compressed => false )
  packer.pack( file_list )

  #
  # dump the file that matches the right path to stdout.  This also shows
  # positional sql varible binding using the '?' syntax.
  #
when 'retrieve'
  usage if file_list.empty?
  db.execute("SELECT id, compressed, filename, contents FROM rubylibs WHERE filename = ?", file_list.first) do |row|
    STDERR.puts "Dumping #{row['filename']} to stdout"
    if row['compressed'] then
      s = row['contents'].to_s
      STDOUT.puts Amalgalite::Packer.gunzip( s )
    else
      row['contents'].write_to_io( STDOUT )
    end
  end
end
db.close
