Class: LiveJournal::Database

Inherits:
Object
  • Object
show all
Defined in:
lib/livejournal/database.rb

Overview

An interface for an SQLite database dump.

Defined Under Namespace

Classes: Error

Constant Summary collapse

EXPECTED_DATABASE_VERSION =
"3"
SCHEMA =
%q{
CREATE TABLE meta (
  key TEXT PRIMARY KEY,
  value TEXT
);
CREATE TABLE entry (
  itemid INTEGER PRIMARY KEY,
  anum INTEGER,
  subject TEXT,
  event TEXT,
  moodid INTEGER, mood TEXT, music TEXT, location TEXT, taglist TEXT,
  pickeyword TEXT, preformatted INTEGER, backdated INTEGER,
  comments INTEGER, year INTEGER, month INTEGER, day INTEGER,
  timestamp INTEGER, security INTEGER
);
CREATE INDEX dateindex ON entry (year, month, day);
CREATE INDEX timeindex ON entry (timestamp);
CREATE TABLE comment (
  commentid INTEGER PRIMARY KEY,
  posterid INTEGER,
  itemid INTEGER,
  parentid INTEGER,
  state TEXT,  -- screened/deleted/frozen/active
  subject TEXT,
  body TEXT,
  timestamp INTEGER  -- unix timestamp
);
CREATE INDEX commententry ON comment (itemid);
CREATE TABLE users (
  userid INTEGER PRIMARY KEY,
  username TEXT
);
CREATE TABLE commentprop (
  commentid INTEGER,  -- not primary key 'cause non-unique
  key TEXT,
  value TEXT
);
}.gsub(/^      /, '')

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, create_if_necessary = false) ⇒ Database

Returns a new instance of Database.

Raises:

  • (Errno::ENOENT)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/livejournal/database.rb', line 82

def initialize(filename, create_if_necessary=false)
  exists = FileTest::exists? filename
  raise Errno::ENOENT if not create_if_necessary and not exists
  @db = SQLite3::Database.new(filename)

  # We'd like to use type translation, but it unfortunately fails on MAX()
  # queries.
  # @db.type_translation = true

  if exists
    # Existing database!
    version = self.version
    unless version == EXPECTED_DATABASE_VERSION
      raise Error, "Database version mismatch -- db has #{version.inspect}, expected #{EXPECTED_DATABASE_VERSION.inspect}"
    end
  end

  if create_if_necessary and not exists
    # New database!  Initialize it.
    transaction do
      @db.execute_batch(SCHEMA)
    end
    self.version = EXPECTED_DATABASE_VERSION
  end
end

Instance Attribute Details

#dbObject (readonly)

The underlying SQLite3 database.



80
81
82
# File 'lib/livejournal/database.rb', line 80

def db
  @db
end

Class Method Details

.db_value(name, sym) ⇒ Object

:nodoc:



125
126
127
128
# File 'lib/livejournal/database.rb', line 125

def self.db_value(name, sym)  # :nodoc:
  class_eval %{def #{sym}; get_meta(#{name.inspect}); end}
  class_eval %{def #{sym}=(v); set_meta(#{name.inspect}, v); end}
end

.optional_to_i(x) ⇒ Object

:nodoc:



74
75
76
77
# File 'lib/livejournal/database.rb', line 74

def self.optional_to_i(x) # :nodoc:
  return nil if x.nil?
  return x.to_i
end

Instance Method Details

#closeObject

Close the underlying database. (Is this necessary? Not sure.)



115
116
117
# File 'lib/livejournal/database.rb', line 115

def close
  @db.close
end

#each_entry(where = nil, &block) ⇒ Object

Yield a set of entries, ordered by ascending itemid (first to last).



167
168
169
170
171
172
# File 'lib/livejournal/database.rb', line 167

def each_entry(where=nil, &block)
  sql = 'SELECT * FROM entry'
  sql += " WHERE #{where}" if where
  sql += ' ORDER BY itemid ASC'
  query_entries sql, &block
end

#get_entry(itemid) ⇒ Object

Fetch a specific itemid.



149
150
151
# File 'lib/livejournal/database.rb', line 149

def get_entry(itemid)
  query_entry("select * from entry where itemid=?", itemid)
end

#get_meta(key) ⇒ Object

:nodoc:



119
120
121
# File 'lib/livejournal/database.rb', line 119

def get_meta key # :nodoc:
  return @db.get_first_value('SELECT value FROM meta WHERE key=?', key)
end

#journalObject

The the actual journal stored by this Database. (This is different than simply the username when usejournal is specified.)



137
138
139
# File 'lib/livejournal/database.rb', line 137

def journal
  usejournal || username
end

#last_comment_fullObject

Used for Sync::Comments.



191
192
193
194
195
# File 'lib/livejournal/database.rb', line 191

def last_comment_full
  Database::optional_to_i(
      @db.get_first_value('SELECT MAX(commentid) FROM comment ' +
                          'WHERE body IS NOT NULL'))
end

#last_comment_metaObject

Used for Sync::Comments.



186
187
188
189
# File 'lib/livejournal/database.rb', line 186

def last_comment_meta
  Database::optional_to_i(
      @db.get_first_value('SELECT MAX(commentid) FROM comment'))
end

#query_entries(sql, *sqlargs) ⇒ Object

Given SQL that selects some entries, yield each Entry.



160
161
162
163
164
# File 'lib/livejournal/database.rb', line 160

def query_entries(sql, *sqlargs) # :yields: entry
  @db.execute(sql, *sqlargs) do |row|
    yield Entry.new.load_from_database_row(row)
  end
end

#query_entry(sql, *sqlargs) ⇒ Object

Given SQL that selects an entry, return that Entry.



154
155
156
157
# File 'lib/livejournal/database.rb', line 154

def query_entry(sql, *sqlargs)
  row = @db.get_first_row(sql, *sqlargs)
  return Entry.new.load_from_database_row(row)
end

#set_meta(key, value) ⇒ Object

:nodoc:



122
123
124
# File 'lib/livejournal/database.rb', line 122

def set_meta key, value  # :nodoc:
  @db.execute('INSERT OR REPLACE INTO meta VALUES (?, ?)', key, value)
end

#store_comments_full(comments) ⇒ Object

Used for Sync::Comments.



202
203
204
# File 'lib/livejournal/database.rb', line 202

def store_comments_full(comments)
  store_comments(comments, false)
end

#store_comments_meta(comments) ⇒ Object

Used for Sync::Comments.



198
199
200
# File 'lib/livejournal/database.rb', line 198

def store_comments_meta(comments)
  store_comments(comments, true)
end

#store_entry(entry) ⇒ Object

Store an Entry.



180
181
182
183
# File 'lib/livejournal/database.rb', line 180

def store_entry entry
  sql = 'INSERT OR REPLACE INTO entry VALUES (' + ("?, " * 17) + '?)'
  @db.execute(sql, *entry.to_database_row)
end

#store_usermap(usermap) ⇒ Object

Used for Sync::Comments.



207
208
209
210
211
212
213
214
215
216
# File 'lib/livejournal/database.rb', line 207

def store_usermap(usermap)
  transaction do
    sql = "INSERT OR REPLACE INTO users VALUES (?, ?)"
    @db.prepare(sql) do |stmt|
      usermap.each do |id, user|
        stmt.execute(id, user)
      end
    end
  end
end

#total_entry_countObject

Return the total number of entries.



175
176
177
# File 'lib/livejournal/database.rb', line 175

def total_entry_count
  @db.get_first_value('SELECT COUNT(*) FROM entry').to_i
end

#trace!Object

Turn tracing on. Mostly useful for debugging.



142
143
144
145
146
# File 'lib/livejournal/database.rb', line 142

def trace!
  @db.trace() do |data, sql|
    puts "SQL> #{sql.inspect}"
  end
end

#transactionObject

Run a block within a single database transaction. Useful for bulk inserts.



110
111
112
# File 'lib/livejournal/database.rb', line 110

def transaction
  @db.transaction { yield }
end