Permalink
Browse files

* SQLite3Store

  * Basic support for using with ActiveRecord: #initialize _configuration_ can take a _connection_ option, using ActiveRecord::Base.connection.raw_connection
  * If result set is returned as a hash, change back to an array (needed, as rails sets results_as_hash attribute on DB)
  • Loading branch information...
1 parent 012e1f0 commit b8eb167c38b3dfe5f09bc51a65ee43fa37e5a1f7 @gkellogg committed Dec 17, 2010
Showing with 125 additions and 50 deletions.
  1. +8 −1 History.rdoc
  2. +1 −0 lib/rdf_context/store/abstract_sql_store.rb
  3. +111 −47 lib/rdf_context/store/sqlite3_store.rb
  4. +5 −2 rdf_context.gemspec
View
@@ -5,9 +5,16 @@
* Rspec 2.1.0
* Added Resource class, a common super-class of BNode, Graph, Literal and URIRef.
* Implemented Resource.parse and variations for sub-classes to parse N3-coded resources.
+* Literal#typed
+ * Namespaces option now is {prefix => href} rather than {prefix => Namespace}.
+ * Add all in-scope namespaces, not just those that seem to be used.
* RDFa Parser
* Upgrade for changes to RDFa 1.1 test suite
* For SVG, allow use of xml:base for non-HTML languages
+ * No longer pass vocabularies, prefixes or terms when creating XMLLiterals. Only namespaces derived via xmlns are passed to Literal#typed.
+* SQLite3Store
+ * Basic support for using with ActiveRecord: #initialize _configuration_ can take a _connection_ option, using ActiveRecord::Base.connection.raw_connection
+ * If result set is returned as a hash, change back to an array (needed, as rails sets results_as_hash attribute on DB)
=== 0.5.9.1
* Fix minor graph property caching bug relating to manipulation of sequences.
@@ -21,7 +28,7 @@
=== 0.5.8.2
* Don't create unnecessary namespaces when serializing RDF/XML.
* Don't use regexp to substitute base URI in URI serialization.
-* Added :profile_graph option to RdfaParser#parse. This MUST be a ConjunctiveGraph and will be used to save profiles that are encountered.
+* Added profile_graph option to RdfaParser#parse. This MUST be a ConjunctiveGraph and will be used to save profiles that are encountered.
* Fixme, for now, retrieval should include HTTP headers and perform appropriate HTTP cache control and check for potential updates.
* Added ConjunctiveGraph#add_quad. Adds a quad from the intended subject, predicate, object, and context.
@example
@@ -904,6 +904,7 @@ def extractTriple(tupleRt, hardCodedContext = nil)
# Takes a term value, and term type
# and Creates a term object. QuotedGraphs are instantiated differently
def createTerm(termString,termType,objLanguage=nil,objDatatype=nil)
+ #puts "createTerm(#{termString}, #{termType}, ...)" if ::RdfContext::debug?
case termType
when "L"
@literalCache[[termString, objLanguage, objDatatype]] ||= Literal.n3_encoded(termString, objLanguage, objDatatype)
@@ -13,16 +13,18 @@ module RdfContext
#
# Based on Python RdfLib SQLite
class SQLite3Store < AbstractSQLStore
- # Create a new SQLite3Store Store, should be subclassed
+ # Create a new SQLite3Store Store
# @param [URIRef] identifier
# @param[Hash] configuration Specific to type of storage
+ # @option configuration [String] :db Path to database file
+ # @option configuration [String] :connection ActiveRecord::Base.connection.raw_connection
# @return [SQLite3Store]
def initialize(identifier = nil, configuration = {})
+ configuration[:path] ||= File.join(Dir.getwd, "#{@internedId}.db")
+
super(identifier, configuration)
@autocommit_default = false
- @path = configuration[:path] || File.join(Dir.getwd, "#{@internedId}.db")
- @db = open(:path => @path) unless @db
end
# Opens the store specified by the configuration hash. If
@@ -34,57 +36,113 @@ def initialize(identifier = nil, configuration = {})
#
# @option options[String] :path Path to database file defaults to a file in the current directory based on a hash of the store identifier
def open(options)
- unless File.exist?(options[:path])
+ @db ||= options[:connection]
+ return @db if @db
+
+ if options[:path] && !File.exist?(options[:path])
@db = SQLite3::Database.new(options[:path])
- executeSQL(CREATE_ASSERTED_STATEMENTS_TABLE % @internedId)
- executeSQL(CREATE_ASSERTED_TYPE_STATEMENTS_TABLE % @internedId)
- executeSQL(CREATE_QUOTED_STATEMENTS_TABLE % @internedId)
- executeSQL(CREATE_NS_BINDS_TABLE % @internedId)
- executeSQL(CREATE_LITERAL_STATEMENTS_TABLE % @internedId)
-
- # Create indicies
- {
- asserted_table => {
- "#{@internedId}_A_termComb_index" => %w(termComb),
- "#{@internedId}_A_s_index" => %w(subject),
- "#{@internedId}_A_p_index" => %w(predicate),
- "#{@internedId}_A_o_index" => %w(object),
- "#{@internedId}_A_c_index" => %w(context),
- },
- asserted_type_table => {
- "#{@internedId}_T_termComb_index" => %w(termComb),
- "#{@internedId}_T_member_index" => %w(member),
- "#{@internedId}_T_klass_index" => %w(klass),
- "#{@internedId}_T_c_index" => %w(context),
- },
- literal_table => {
- "#{@internedId}_L_termComb_index" => %w(termComb),
- "#{@internedId}_L_s_index" => %w(subject),
- "#{@internedId}_L_p_index" => %w(predicate),
- "#{@internedId}_L_c_index" => %w(context),
- },
- quoted_table => {
- "#{@internedId}_Q_termComb_index" => %w(termComb),
- "#{@internedId}_Q_s_index" => %w(subject),
- "#{@internedId}_Q_p_index" => %w(predicate),
- "#{@internedId}_Q_o_index" => %w(object),
- "#{@internedId}_Q_c_index" => %w(context),
- },
- namespace_binds => {
- "#{@internedId}_uri_index" => %w(uri),
- }
- }.each_pair do |tablename, indicies|
- indicies.each_pair do |index, columns|
- executeSQL("CREATE INDEX #{index} on #{tablename} ('#{columns.join(', ')}')")
- end
- end
+ setup
end
raise StoreException.new("Attempt to open missing database file #{options[:path]}") unless File.exist?(options[:path])
@db = SQLite3::Database.new(options[:path])
end
- # Destroy databse
+ # Create necessary tables and indecies for this database
+ def setup
+ executeSQL(CREATE_ASSERTED_STATEMENTS_TABLE % @internedId)
+ executeSQL(CREATE_ASSERTED_TYPE_STATEMENTS_TABLE % @internedId)
+ executeSQL(CREATE_QUOTED_STATEMENTS_TABLE % @internedId)
+ executeSQL(CREATE_NS_BINDS_TABLE % @internedId)
+ executeSQL(CREATE_LITERAL_STATEMENTS_TABLE % @internedId)
+
+ # Create indicies
+ {
+ asserted_table => {
+ "#{@internedId}_A_termComb_index" => %w(termComb),
+ "#{@internedId}_A_s_index" => %w(subject),
+ "#{@internedId}_A_p_index" => %w(predicate),
+ "#{@internedId}_A_o_index" => %w(object),
+ "#{@internedId}_A_c_index" => %w(context),
+ },
+ asserted_type_table => {
+ "#{@internedId}_T_termComb_index" => %w(termComb),
+ "#{@internedId}_T_member_index" => %w(member),
+ "#{@internedId}_T_klass_index" => %w(klass),
+ "#{@internedId}_T_c_index" => %w(context),
+ },
+ literal_table => {
+ "#{@internedId}_L_termComb_index" => %w(termComb),
+ "#{@internedId}_L_s_index" => %w(subject),
+ "#{@internedId}_L_p_index" => %w(predicate),
+ "#{@internedId}_L_c_index" => %w(context),
+ },
+ quoted_table => {
+ "#{@internedId}_Q_termComb_index" => %w(termComb),
+ "#{@internedId}_Q_s_index" => %w(subject),
+ "#{@internedId}_Q_p_index" => %w(predicate),
+ "#{@internedId}_Q_o_index" => %w(object),
+ "#{@internedId}_Q_c_index" => %w(context),
+ },
+ namespace_binds => {
+ "#{@internedId}_uri_index" => %w(uri),
+ }
+ }.each_pair do |tablename, indicies|
+ indicies.each_pair do |index, columns|
+ executeSQL("CREATE INDEX #{index} on #{tablename} ('#{columns.join(', ')}')")
+ end
+ end
+ end
+
+ # Teardown DB files
+ def teardown
+ # Drop indicies
+ {
+ asserted_table => {
+ "#{@internedId}_A_termComb_index" => %w(termComb),
+ "#{@internedId}_A_s_index" => %w(subject),
+ "#{@internedId}_A_p_index" => %w(predicate),
+ "#{@internedId}_A_o_index" => %w(object),
+ "#{@internedId}_A_c_index" => %w(context),
+ },
+ asserted_type_table => {
+ "#{@internedId}_T_termComb_index" => %w(termComb),
+ "#{@internedId}_T_member_index" => %w(member),
+ "#{@internedId}_T_klass_index" => %w(klass),
+ "#{@internedId}_T_c_index" => %w(context),
+ },
+ literal_table => {
+ "#{@internedId}_L_termComb_index" => %w(termComb),
+ "#{@internedId}_L_s_index" => %w(subject),
+ "#{@internedId}_L_p_index" => %w(predicate),
+ "#{@internedId}_L_c_index" => %w(context),
+ },
+ quoted_table => {
+ "#{@internedId}_Q_termComb_index" => %w(termComb),
+ "#{@internedId}_Q_s_index" => %w(subject),
+ "#{@internedId}_Q_p_index" => %w(predicate),
+ "#{@internedId}_Q_o_index" => %w(object),
+ "#{@internedId}_Q_c_index" => %w(context),
+ },
+ namespace_binds => {
+ "#{@internedId}_uri_index" => %w(uri),
+ }
+ }.each_pair do |tablename, indicies|
+ tn = "#{@internedId}_#{tablename}"
+ indicies.each_pair do |index, columns|
+ executeSQL("DROP INDEX #{index} ON #{tn}")
+ end
+ end
+
+ # Drop tables
+ executeSQL("DROP TABLE #{namespace_binds}")
+ executeSQL("DROP TABLE #{quoted_table}")
+ executeSQL("DROP TABLE #{literal_table}")
+ executeSQL("DROP TABLE #{asserted_type_table}")
+ executeSQL("DROP TABLE #{asserted_table}")
+ end
+
+ # Destroy database
#
# @option options[String] :path Path to database file defaults to a file in the current directory based on a hash of the store identifier
def destroy(options = {})
@@ -171,6 +229,7 @@ def executeSQL(qStr, *params, &block)
if block_given?
@db.execute(@statement_cache[qStr], *params) do |row|
puts "executeSQL res: #{row.inspect}" if ::RdfContext::debug?
+ row = row.keys.select{|k| k.is_a?(Integer)}.sort.map{|k| row[k]} if row.is_a?(Hash)
yield(row)
end
else
@@ -222,5 +281,10 @@ def executeSQL(qStr, *params, &block)
uri text,
PRIMARY KEY (prefix)))
+ DROP_ASSERTED_STATEMENTS_TABLE = %(DROP TABLE %s_asserted_statements)
+ DROP_ASSERTED_TYPE_STATEMENTS_TABLE = %(DROP TABLE %s_type_statements)
+ DROP_LITERAL_STATEMENTS_TABLE = %(DROP TABLE %s_literal_statements)
+ DROP_QUOTED_STATEMENTS_TABLE = %(DROP TABLE %s_quoted_statements)
+ DROP_NS_BINDS_TABLE = %(DROP TABLE %s_namespace_binds)
end
end
View
@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = %q{rdf_context}
- s.version = "0.5.9.1"
+ s.version = "0.5.10"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Gregg Kellogg"]
- s.date = %q{2010-12-14}
+ s.date = %q{2010-12-16}
s.default_executable = %q{rdf_context}
s.description = %q{ RdfContext parses RDF/XML, RDFa and N3-rdf into a Graph object. It also serializes RDF/XML and N-Triples from the Graph.
@@ -69,6 +69,7 @@ Gem::Specification.new do |s|
"lib/rdf_context/term_utils.rb",
"lib/rdf_context/triple.rb",
"lib/rdf_context/uriref.rb",
+ "rdf_context.gemspec",
"script/console",
"script/tc",
"spec/.gitignore",
@@ -605,6 +606,7 @@ Gem::Specification.new do |s|
"spec/swap_test/ref/bnode.n3",
"spec/swap_test/ref/bnode.rdf",
"spec/swap_test/ref/colon-in-uri.n3",
+ "spec/swap_test/ref/contexts-1.n3",
"spec/swap_test/ref/daml-ex.n3",
"spec/swap_test/ref/daml-ont.n3",
"spec/swap_test/ref/djb1a-out.n3",
@@ -622,6 +624,7 @@ Gem::Specification.new do |s|
"spec/swap_test/ref/path1.n3",
"spec/swap_test/ref/path2.n3",
"spec/swap_test/ref/prefix1.rdf",
+ "spec/swap_test/ref/prefix2.rdf",
"spec/swap_test/ref/prefix3.rdf",
"spec/swap_test/ref/rdf-redefine.rdf",
"spec/swap_test/ref/reluri-1.rdf",

0 comments on commit b8eb167

Please sign in to comment.