Created
March 2, 2010 07:03
-
-
Save tenderlove/319224 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
# This is a demonstration of using SQLite3's Virtual File System API in Ruby. | |
# | |
# == Synopsis | |
# | |
# This program will store its SQLite database after the __END__ line. | |
# | |
# === In Detail | |
# | |
# SQLite3 uses the DATABase class as a proxy for our IO object. Upon | |
# instantiation, the DATABase class opens __FILE__, seeks to the point right | |
# after __END__ by using DATA.pos. It caches the value of DATA.pos for later | |
# calculations when the database engine needs to seek for reading and writing. | |
# | |
# == How can I run this code? | |
# | |
# This code requires my fork of the sqlite3-ruby bindings. The normal sqlite | |
# bindings do not expose the Virtual File System api. You can get my fork | |
# with the VFS extensions here: | |
# | |
# http://github.com/tenderlove/sqlite3-ruby/tree/vfs | |
# | |
require 'sqlite3' | |
class EvilVFS < SQLite3::VFS | |
def open name, flags | |
DATABase.new name, flags | |
end | |
end | |
class DATABase < SQLite3::VFS::File | |
def initialize name, flags | |
super | |
@store = File.open(name, File::RDWR | File::CREAT) | |
@offset = 0 | |
if File.expand_path(__FILE__) == name | |
@store.seek DATA.pos | |
@offset = DATA.pos | |
end | |
end | |
def close | |
@store.close | |
end | |
def read amt, offset | |
@store.seek(offset + @offset) | |
@store.read amt | |
end | |
def write data, offset | |
@store.seek(offset + @offset) | |
@store.write data | |
end | |
def sync opts | |
@store.fsync | |
end | |
def file_size | |
File.size(@store.path) - @offset | |
end | |
end | |
SQLite3.vfs_register(EvilVFS.new) | |
db = SQLite3::Database.new(__FILE__, nil, 'EvilVFS') | |
db.execute('create table if not exists users(id integer primary key, name string)') | |
100.times { db.execute('insert into users(name) values (?)', 'tenderlove') } | |
p db.execute('select count(*) from users') | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment