Here is a simplified version of a DBI type scheme, almost entirely using 
convert function overloads. I temporarily have eval_foreign instead of 
eval, because I cannot figure out how to overload Base.eval successfully.

cd("/home/haldane/Julia_package")

using DataFrames
using SQLite
using Lazy

import Base.convert

type DataBaseTable
  conn::SQLiteDB
  name::String
end

type CsvFile
  file::String
end

function convert(::Type{DataBaseTable},
                 conn::SQLiteDB,
                 name::String,
                 df::DataFrame)
  create(conn,
         name,
         df,
         @>> df names map(string) )

  DataBaseTable(conn, name)
end

function convert(::Type{SQLiteDB}, string::String)
  SQLiteDB(string)
end

function eval_foreign(db::SQLiteDB, code::String)
  query(db, code)
end

function convert(::Type{Dict}, conn::SQLiteDB)
  names = @as _ begin
    "select name from sqlite_master where type = 'table'"
    eval_foreign(conn, _)
    _.values[1]
  end

  [symbol(name) => DataBaseTable(conn, name) for name in names]
end

function convert(::Type{DataFrame}, dbt::DataBaseTable)
  answer = eval_foreign(dbt.conn, "select * from $(dbt.name)" )
  df = DataFrame(answer.values)
  @>> answer.colnames map(symbol) names!(df)
end

function convert(::Type{CsvFile}, name::String, df::DataFrame)
  writetable(name, df)
  CsvFile(name)
end

function convert(::Type{DataFrame}, file::String)
  readtable(file)
end

function convert(::Type{DataFrame}, cf = CsvFile)
  readtable(cf.file)
end

conn = @>> "my_database.db" convert(SQLiteDB)

A = DataFrame(a = 1, b = 2)
B = DataFrame(a = 1, b = 2)

@>> A convert(DataBaseTable, conn, "A")
@>> B convert(DataBaseTable, conn, "B")

tables = @>> conn convert(Dict)

A = @>> begin
  tables[:A] 
  convert(DataFrame) 
  convert(CsvFile, "A.csv") 
  convert(DataFrame)
end



Reply via email to