Class: Flukso::FluksoDB

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db, tablename) ⇒ FluksoDB

constuctor: give SQLite::Database object as argument. see class methods.



75
76
77
78
79
# File 'lib/flukso/database.rb', line 75

def initialize(db, tablename)
  @tablename=tablename
  @db=db;
  @db.results_as_hash = true
end

Class Method Details

.create(filename, tablename) ⇒ Object

create a new database



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/flukso/database.rb', line 34

def self.create(filename, tablename)
  filename=String.new(File.expand_path(filename));
  if File.exists?(filename)
    raise "Database file #{filename} already exists."
  end
  puts "Creating new database file #{filename}" if $verbose
  db = SQLite3::Database.open(filename)
  schema = FluksoDB.fill_template( DB_SCHEMA, { 'TABLE_NAME' => tablename} )
  db.execute_batch(schema)
  return FluksoDB.new(db, tablename);
end

.fill_template(templateStr, values) ⇒ Object

See: freshmeat.net/articles/templates-in-ruby template: Returns a string formed from a template and replacement values

templateStr - The template string (format shown below) values - A hash of replacement values

Example format:

"Dear :::customer:::,\nPlease pay us :::amount:::.\n"

The “customer” and “amount” strings are used as keys to index against the values hash.



66
67
68
69
70
71
72
# File 'lib/flukso/database.rb', line 66

def self.fill_template( templateStr, values )
  outStr = templateStr.clone()
  values.keys.each { |key|
    outStr.gsub!( /:::#{key}:::/, values[ key ] )
  }
  outStr
end

.open(filename, tablename) ⇒ Object

open an existing database



46
47
48
49
50
51
52
53
# File 'lib/flukso/database.rb', line 46

def self.open(filename, tablename)
  filename=File.expand_path(filename);
  if not File.exists?(filename)
    raise "Database file #{filename} does not exist."
  end
  db = SQLite3::Database.open( filename)
  return FluksoDB.new(db, tablename);
end

Instance Method Details

#appendNewReadings(readings) ⇒ Object

Appends the readings of the provided array to the database.



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

def appendNewReadings(readings)
  insertCounter=0
  last_timestamp=0
  begin
    last_reading=find_reading_last();
    last_timestamp=last_reading.utc_timestamp;
  rescue Flukso::ElementNotFoundError => e
    puts "Empty database - not able to provide last reading."
  end
  readings.each{|reading|
    if reading.utc_timestamp > last_timestamp
      puts "Appending #{reading}" if $verbose
      storeReading(reading);
      insertCounter += 1
    else
      puts "Skipping reading at #{reading.utc_timestamp}, already in DB." if $verbose
    end
  }
  return insertCounter
end

#closeObject



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

def close
  @db.close;
end

#each_reading(&block) ⇒ Object



142
143
144
145
146
147
148
149
# File 'lib/flukso/database.rb', line 142

def each_reading(&block)
  stmt=<<-SQL
  SELECT * FROM #{@tablename}
  order by epochtime ASC;
  SQL
  #puts "Using statement #{stmt}" if $verbose
  helper_yield_results(stmt, block);
end

#each_reading_between(starttime, endtime, &block) ⇒ Object



133
134
135
136
137
138
139
140
141
# File 'lib/flukso/database.rb', line 133

def each_reading_between(starttime, endtime, &block)
  stmt=<<-SQL
  SELECT * FROM #{@tablename}
  WHERE epochtime >= #{starttime} AND epochtime <= #{endtime}
  ORDER BY epochtime ASC;
  SQL
  #puts "Using statement #{stmt}" if $verbose
  helper_yield_results(stmt, block);
end

#find_last_reading(amount) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/flukso/database.rb', line 150

def find_last_reading(amount)
  if not amount.class==Fixnum
    raise "Must provide the number of last readings desired as an Fixnum."
  end
  stmt=<<-SQL
  SELECT * FROM #{@tablename}
  order by epochtime DESC limit #{amount};
  SQL
  #puts "Using statement #{stmt}" if $verbose
  readings=Array.new
  @db.execute(stmt) {|row|
    value=row['VALUE'].to_f;
    #timestamp=Time.at(row['EPOCHTIME'].to_f);
    timestamp=row['EPOCHTIME'].to_f;
    #puts "Creating new UTCReading: #{timestamp}, #{value}"
    reading=UTCReading.new(timestamp, value);
    readings << reading
  }
  if readings.empty?
    raise ElementNotFoundError
  end
  return readings;
end

#find_reading_by_epochtime(time) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/flukso/database.rb', line 173

def find_reading_by_epochtime(time)
  stmt=<<-SQL
    SELECT * FROM #{@tablename}
    WHERE epochtime ='#{time}';
  SQL
  readings=Array.new
  @db.execute(stmt) {|row|
    reading=UTCReading.new(row['TIMESTAMP'].to_i, row['VALUE'].to_i)
    readings << reading
  }
  if readings.empty?
    raise ElementNotFoundError
  end
  return readings[0];
end

#find_reading_lastObject



118
119
120
# File 'lib/flukso/database.rb', line 118

def find_reading_last
  return find_last_reading(1)[0];
end

#find_reading_last_fiveObject



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

def find_reading_last_five
  return find_last_reading(5);
end

#helper_yield_results(querystatement, block) ⇒ Object

Avoid redundant code. Takes a block and executes it on the query data. See innig.net/software/ruby/closures-in-ruby.rb



123
124
125
126
127
128
129
130
131
132
# File 'lib/flukso/database.rb', line 123

def helper_yield_results(querystatement, block)
  @db.execute(querystatement) {|row|
    value=row['VALUE'].to_f;
    #timestamp=Time.at(row['EPOCHTIME'].to_f);
    timestamp=row['EPOCHTIME'].to_f;
    #puts "Creating new UTCReading: #{timestamp}, #{value}"
    reading=UTCReading.new(timestamp, value);
    block.call(reading);
  }
end

#storeReading(reading) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/flukso/database.rb', line 104

def storeReading(reading)
  # TODO: Make this more efficient, recycle insert statements.
  if reading.class != UTCReading
    raise "Must give a UTCReading instance."
  end
  stmt=<<-SQL
  INSERT INTO #{@tablename}
  VALUES ('#{reading.utc_timestamp}', '#{reading.value}'); 
  SQL
  @db.execute(stmt)
end