@@ -243,17 +243,16 @@ def begin_transaction(mutable: false, graph_name: nil)
243
243
#
244
244
# @see RDF::Repository
245
245
module Implementation
246
- require 'hamster'
247
246
DEFAULT_GRAPH = false
248
247
249
248
##
250
249
# @private
251
250
def self . extend_object ( obj )
252
251
obj . instance_variable_set ( :@data , obj . options . delete ( :data ) ||
253
- Hamster :: Hash . new )
252
+ Hash . new )
254
253
obj . instance_variable_set ( :@tx_class ,
255
254
obj . options . delete ( :transaction_class ) ||
256
- SerializedTransaction )
255
+ DEFAULT_TX_CLASS )
257
256
super
258
257
end
259
258
@@ -263,7 +262,6 @@ def self.extend_object(obj)
263
262
def supports? ( feature )
264
263
case feature . to_sym
265
264
when :graph_name then @options [ :with_graph_name ]
266
- when :inference then false # forward-chaining inference
267
265
when :validity then @options . fetch ( :with_validity , true )
268
266
when :literal_equality then true
269
267
when :atomic_write then true
@@ -381,7 +379,7 @@ def apply_changeset(changeset)
381
379
##
382
380
# @see RDF::Dataset#isolation_level
383
381
def isolation_level
384
- :serializable
382
+ :snapshot
385
383
end
386
384
387
385
##
@@ -471,7 +469,7 @@ def delete_statement(statement)
471
469
# @private
472
470
# @see RDF::Mutable#clear
473
471
def clear_statements
474
- @data = @data . clear
472
+ @data = @data . class . new
475
473
end
476
474
477
475
##
@@ -513,14 +511,11 @@ def insert_to(data, statement)
513
511
unless statement_in? ( data , statement )
514
512
s , p , o , c = statement . to_quad
515
513
c ||= DEFAULT_GRAPH
516
-
517
- return data . put ( c ) do |subs |
518
- ( subs || Hamster ::Hash . new ) . put ( s ) do |preds |
519
- ( preds || Hamster ::Hash . new ) . put ( p ) do |objs |
520
- ( objs || Hamster ::Hash . new ) . put ( o , statement . options )
521
- end
522
- end
523
- end
514
+
515
+ data = data . has_key? ( c ) ? data . dup : data . merge ( c => { } )
516
+ data [ c ] = data [ c ] . has_key? ( s ) ? data [ c ] . dup : data [ c ] . merge ( s => { } )
517
+ data [ c ] [ s ] = data [ c ] [ s ] . has_key? ( p ) ? data [ c ] [ s ] . dup : data [ c ] [ s ] . merge ( p => { } )
518
+ data [ c ] [ s ] [ p ] = data [ c ] [ s ] [ p ] . merge ( o => statement . options )
524
519
end
525
520
data
526
521
end
@@ -529,93 +524,18 @@ def insert_to(data, statement)
529
524
# @private
530
525
# @return [Hamster::Hash] a new, updated hamster hash
531
526
def delete_from ( data , statement )
532
- if statement_in ?( data , statement )
527
+ if has_statement_in ?( data , statement )
533
528
s , p , o , g = statement . to_quad
534
529
g = DEFAULT_GRAPH unless supports? ( :graph_name )
535
530
g ||= DEFAULT_GRAPH
536
531
537
- os = data [ g ] [ s ] [ p ] . delete ( o )
538
- ps = os . empty? ? data [ g ] [ s ] . delete ( p ) : data [ g ] [ s ] . put ( p , os )
539
- ss = ps . empty? ? data [ g ] . delete ( s ) : data [ g ] . put ( s , ps )
540
- return ss . empty? ? data . delete ( g ) : data . put ( g , ss )
532
+ os = data [ g ] [ s ] [ p ] . dup . delete_if { | k , v | k == o }
533
+ ps = os . empty? ? data [ g ] [ s ] . dup . delete_if { | k , v | k == p } : data [ g ] [ s ] . merge ( p => os )
534
+ ss = ps . empty? ? data [ g ] . dup . delete_if { | k , v | k == s } : data [ g ] . merge ( s => ps )
535
+ return ss . empty? ? data . dup . delete_if { | k , v | k == g } : data . merge ( g => ss )
541
536
end
542
537
data
543
538
end
544
-
545
- ##
546
- # A transaction for the Hamster-based `RDF::Repository::Implementation`
547
- # with full serializability.
548
- #
549
- # @todo refactor me!
550
- # @see RDF::Transaction
551
- class SerializedTransaction < Transaction
552
- ##
553
- # @see Transaction#initialize
554
- def initialize ( *args , **options , &block )
555
- super ( *args , **options , &block )
556
- @base_snapshot = @snapshot
557
- end
558
-
559
- ##
560
- # Inserts the statement to the transaction's working snapshot.
561
- #
562
- # @see Transaction#insert_statement
563
- def insert_statement ( statement )
564
- @snapshot = @snapshot . class
565
- . new ( data : @snapshot . send ( :insert_to ,
566
- @snapshot . send ( :data ) ,
567
- process_statement ( statement ) ) )
568
- end
569
-
570
- ##
571
- # Deletes the statement from the transaction's working snapshot.
572
- #
573
- # @see Transaction#insert_statement
574
- def delete_statement ( statement )
575
- @snapshot = @snapshot . class
576
- . new ( data : @snapshot . send ( :delete_from ,
577
- @snapshot . send ( :data ) ,
578
- process_statement ( statement ) ) )
579
- end
580
-
581
- ##
582
- # @see RDF::Dataset#isolation_level
583
- def isolation_level
584
- :serializable
585
- end
586
-
587
- ##
588
- # @note this is a simple object equality check.
589
- #
590
- # @see RDF::Transaction#mutated?
591
- def mutated?
592
- !@snapshot . send ( :data ) . equal? ( repository . send ( :data ) )
593
- end
594
-
595
- ##
596
- # Replaces repository data with the transaction's snapshot in a safely
597
- # serializable fashion.
598
- #
599
- # @note this transaction uses a pessimistic merge strategy which
600
- # fails the transaction if any data has changed in the repository
601
- # since transaction start time. However, the specific guarantee is
602
- # softer: multiple concurrent conflicting transactions will not
603
- # succeed. We may choose to implement a less pessimistic merge
604
- # strategy as a non-breaking change.
605
- #
606
- # @raise [TransactionError] when the transaction can't be merged.
607
- # @see Transaction#execute
608
- def execute
609
- raise TransactionError , 'Cannot execute a rolled back transaction. ' \
610
- 'Open a new one instead.' if instance_variable_defined? ( :@rolledback ) && @rolledback
611
-
612
- raise TransactionError , 'Error merging transaction. Repository' \
613
- 'has changed during transaction time.' unless
614
- repository . send ( :data ) . equal? @base_snapshot . send ( :data )
615
-
616
- repository . send ( :data= , @snapshot . send ( :data ) )
617
- end
618
- end
619
539
end # Implementation
620
540
end # Repository
621
541
end # RDF
0 commit comments