Class: Tina4::DocStore::SqliteCollection

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/docstore.rb

Overview

A SQLite-backed collection exposing the everyday Mongo API.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conn, name) ⇒ SqliteCollection

Returns a new instance of SqliteCollection.

Raises:

  • (ArgumentError)


462
463
464
465
466
467
468
469
470
471
# File 'lib/tina4/docstore.rb', line 462

def initialize(conn, name)
  @connection = conn
  @name = name.to_s
  raise ArgumentError, "DocStore: invalid collection name #{name.inspect}" unless @name.match?(/\A[A-Za-z_][A-Za-z0-9_]*\z/)

  @quoted_name = "\"#{@name}\""
  @connection.execute(
    "CREATE TABLE IF NOT EXISTS #{@quoted_name} (_id TEXT PRIMARY KEY, doc TEXT NOT NULL)"
  )
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



460
461
462
# File 'lib/tina4/docstore.rb', line 460

def connection
  @connection
end

Instance Method Details

#count_documents(filter = nil) ⇒ Object



518
519
520
521
522
# File 'lib/tina4/docstore.rb', line 518

def count_documents(filter = nil)
  where, params = DocStore.compile_filter(filter || {})
  row = @connection.execute("SELECT count(*) AS c FROM #{@quoted_name} WHERE #{where}", params).first
  scalar(row).to_i
end

#delete_many(filter) ⇒ Object



595
596
597
598
599
600
# File 'lib/tina4/docstore.rb', line 595

def delete_many(filter)
  where, params = DocStore.compile_filter(filter || {})
  before = count_documents(filter)
  @connection.execute("DELETE FROM #{@quoted_name} WHERE #{where}", params)
  DeleteResult.new(before)
end

#delete_one(filter) ⇒ Object

– deletes –



587
588
589
590
591
592
593
# File 'lib/tina4/docstore.rb', line 587

def delete_one(filter)
  rows = matching_rows(filter, limit: 1)
  return DeleteResult.new(0) if rows.empty?

  @connection.execute("DELETE FROM #{@quoted_name} WHERE _id = ?", [rows.first.first])
  DeleteResult.new(1)
end

#distinct(key, filter = nil) ⇒ Object



529
530
531
532
533
534
535
536
# File 'lib/tina4/docstore.rb', line 529

def distinct(key, filter = nil)
  seen = []
  find(filter).each do |doc|
    v = doc[key.to_s]
    seen << v unless seen.include?(v)
  end
  seen
end

#dropObject



602
603
604
# File 'lib/tina4/docstore.rb', line 602

def drop
  @connection.execute("DROP TABLE IF EXISTS #{@quoted_name}")
end

#dump(document) ⇒ Object

– helpers –



476
# File 'lib/tina4/docstore.rb', line 476

def dump(document) = JSON.generate(DocStore.encode_value(document))

#estimated_document_countObject



524
525
526
527
# File 'lib/tina4/docstore.rb', line 524

def estimated_document_count
  row = @connection.execute("SELECT count(*) AS c FROM #{@quoted_name}").first
  scalar(row).to_i
end

#find(filter = nil, projection = nil) ⇒ Object

– reads –



509
510
511
512
# File 'lib/tina4/docstore.rb', line 509

def find(filter = nil, projection = nil)
  where, params = DocStore.compile_filter(filter || {})
  Cursor.new(self, where, params, projection)
end

#find_one(filter = nil, projection = nil) ⇒ Object



514
515
516
# File 'lib/tina4/docstore.rb', line 514

def find_one(filter = nil, projection = nil)
  find(filter, projection).limit(1).to_a.first
end

#insert_many(documents) ⇒ Object



494
495
496
497
498
499
500
501
502
503
504
505
506
# File 'lib/tina4/docstore.rb', line 494

def insert_many(documents)
  ids = []
  documents.each do |document|
    doc = stringify(document)
    doc["_id"] = ObjectId.new unless doc.key?("_id")
    ids << doc["_id"]
    @connection.execute(
      "INSERT INTO #{@quoted_name} (_id, doc) VALUES (?, ?)",
      [DocStore.id_key(doc["_id"]), dump(doc)]
    )
  end
  InsertManyResult.new(ids)
end

#insert_one(document) ⇒ Object

– writes –



484
485
486
487
488
489
490
491
492
# File 'lib/tina4/docstore.rb', line 484

def insert_one(document)
  doc = stringify(document)
  doc["_id"] = ObjectId.new unless doc.key?("_id")
  @connection.execute(
    "INSERT INTO #{@quoted_name} (_id, doc) VALUES (?, ?)",
    [DocStore.id_key(doc["_id"]), dump(doc)]
  )
  InsertOneResult.new(doc["_id"])
end

#load_doc(doc_text, projection = nil) ⇒ Object



478
479
480
481
# File 'lib/tina4/docstore.rb', line 478

def load_doc(doc_text, projection = nil)
  doc = DocStore.decode_value(JSON.parse(doc_text))
  projection ? DocStore.project(doc, projection) : doc
end

#quoted_nameObject



473
# File 'lib/tina4/docstore.rb', line 473

def quoted_name = @quoted_name

#replace_one(filter, replacement, upsert: false) ⇒ Object



568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/tina4/docstore.rb', line 568

def replace_one(filter, replacement, upsert: false)
  rows = matching_rows(filter, limit: 1)
  if rows.empty?
    if upsert
      doc = stringify(replacement)
      doc["_id"] = ObjectId.new unless doc.key?("_id")
      insert_one(doc)
      return UpdateResult.new(0, 0, doc["_id"])
    end
    return UpdateResult.new(0, 0, nil)
  end
  old_id, doc_text = rows.first
  doc = stringify(replacement)
  doc["_id"] = DocStore.decode_value(JSON.parse(doc_text))["_id"] unless doc.key?("_id")
  write_back(old_id, doc)
  UpdateResult.new(1, 1, nil)
end

#update_many(filter, update, upsert: false) ⇒ Object



553
554
555
556
557
558
559
560
561
562
563
564
565
566
# File 'lib/tina4/docstore.rb', line 553

def update_many(filter, update, upsert: false)
  rows = matching_rows(filter)
  return do_upsert(filter, update) if rows.empty? && upsert

  matched = 0
  modified = 0
  rows.each do |old_id, doc_text|
    matched += 1
    doc = DocStore.decode_value(JSON.parse(doc_text))
    new_doc = DocStore.apply_update(doc, update)
    modified += 1 if write_back(old_id, new_doc)
  end
  UpdateResult.new(matched, modified, nil)
end

#update_one(filter, update, upsert: false) ⇒ Object

– updates (filter pushed to SQL; mutation applied per matched doc) –



539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'lib/tina4/docstore.rb', line 539

def update_one(filter, update, upsert: false)
  rows = matching_rows(filter, limit: 1)
  if rows.empty?
    return do_upsert(filter, update) if upsert

    return UpdateResult.new(0, 0, nil)
  end
  old_id, doc_text = rows.first
  doc = DocStore.decode_value(JSON.parse(doc_text))
  new_doc = DocStore.apply_update(doc, update)
  modified = write_back(old_id, new_doc)
  UpdateResult.new(1, modified ? 1 : 0, nil)
end