tricoredb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -0
- data/LICENSE +201 -0
- data/README.md +377 -0
- data/lib/tricoredb/builders.rb +142 -0
- data/lib/tricoredb/client.rb +979 -0
- data/lib/tricoredb/errors.rb +99 -0
- data/lib/tricoredb/frame.rb +106 -0
- data/lib/tricoredb/params.rb +121 -0
- data/lib/tricoredb/pool.rb +159 -0
- data/lib/tricoredb/response.rb +131 -0
- data/lib/tricoredb/transport.rb +184 -0
- data/lib/tricoredb/version.rb +6 -0
- data/lib/tricoredb.rb +21 -0
- data/tricoredb.gemspec +30 -0
- metadata +92 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TriCoreDB
|
|
4
|
+
# Builders for the server's `DocumentFilter`, externally tagged.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# TriCoreDB::Filter.all_of(TriCoreDB::Filter.eq("city", "Pune"), TriCoreDB::Filter.gt("visits", 4))
|
|
8
|
+
module Filter
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
# @return [String] matches every document
|
|
12
|
+
def all
|
|
13
|
+
"All"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
%w[Eq Ne Gt Gte Lt Lte Contains].each do |variant|
|
|
17
|
+
define_method(variant.downcase) do |field, value|
|
|
18
|
+
{ variant => { "field" => field.to_s, "value" => value } }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# `field` equals any of `values`.
|
|
23
|
+
# @return [Hash]
|
|
24
|
+
def in_list(field, values)
|
|
25
|
+
{ "In" => { "field" => field.to_s, "values" => Array(values) } }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Every sub-filter must match.
|
|
29
|
+
# @return [Hash]
|
|
30
|
+
def all_of(*filters)
|
|
31
|
+
{ "And" => filters.flatten }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
alias_method :and, :all_of
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Builders for `GroupAccumulator`.
|
|
40
|
+
module Acc
|
|
41
|
+
module_function
|
|
42
|
+
|
|
43
|
+
%w[Sum Avg Min Max].each do |variant|
|
|
44
|
+
define_method(variant.downcase) do |output, field|
|
|
45
|
+
{ "output" => output.to_s, "op" => { variant => field.to_s } }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Counts documents in the group.
|
|
50
|
+
# @return [Hash]
|
|
51
|
+
def count(output)
|
|
52
|
+
{ "output" => output.to_s, "op" => "Count" }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Builders for `AggregateStage`. Stages apply strictly in order.
|
|
57
|
+
module Stage
|
|
58
|
+
module_function
|
|
59
|
+
|
|
60
|
+
# @return [Hash]
|
|
61
|
+
def match(filter)
|
|
62
|
+
{ "Match" => filter }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @param by [Hash] from {by_field} or {by_constant}
|
|
66
|
+
# @param accumulators [Array<Hash>] from {Acc}
|
|
67
|
+
# @return [Hash]
|
|
68
|
+
def group(by, accumulators = [])
|
|
69
|
+
{ "Group" => { "by" => by, "accumulators" => accumulators } }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @param keys [Array<Array(String, Boolean)>, Array<Hash>] `[field, descending]` pairs or `{field:, descending:}`
|
|
73
|
+
# @return [Hash]
|
|
74
|
+
def sort(*keys)
|
|
75
|
+
list = keys.flatten(1).map do |k|
|
|
76
|
+
if k.is_a?(Hash)
|
|
77
|
+
{ "field" => (k[:field] || k["field"]).to_s, "descending" => !!(k[:descending] || k["descending"]) }
|
|
78
|
+
elsif k.is_a?(Array)
|
|
79
|
+
{ "field" => k[0].to_s, "descending" => !!k[1] }
|
|
80
|
+
else
|
|
81
|
+
{ "field" => k.to_s, "descending" => false }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
{ "Sort" => list }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def skip(n)
|
|
88
|
+
{ "Skip" => Integer(n) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def limit(n)
|
|
92
|
+
{ "Limit" => Integer(n) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def project(fields, include: true)
|
|
96
|
+
{ "Project" => { "fields" => Array(fields).map(&:to_s), "include" => include ? true : false } }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Collapse the stream to one document `{field => n}`.
|
|
100
|
+
def count(field)
|
|
101
|
+
{ "Count" => { "field" => field.to_s } }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def by_field(field)
|
|
105
|
+
{ "Field" => field.to_s }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def by_constant(value)
|
|
109
|
+
{ "Constant" => value }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Builders for `LlmSource`.
|
|
114
|
+
module LlmSource
|
|
115
|
+
module_function
|
|
116
|
+
|
|
117
|
+
# @return [Hash]
|
|
118
|
+
def sql(query)
|
|
119
|
+
{ "Sql" => { "query" => query.to_s } }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @return [Hash]
|
|
123
|
+
def documents(collection, filter: Filter.all, limit: nil)
|
|
124
|
+
{ "DocumentFind" => { "collection" => collection.to_s, "filter" => filter, "limit" => limit } }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Accepts a built source, or `{sql:}` / `{collection:, filter:, limit:}`.
|
|
128
|
+
# @return [Hash]
|
|
129
|
+
def coerce(src)
|
|
130
|
+
return src if src.is_a?(Hash) && (src.key?("Sql") || src.key?("DocumentFind"))
|
|
131
|
+
raise ArgumentError, "an LLM source must be a Hash" unless src.is_a?(Hash)
|
|
132
|
+
|
|
133
|
+
sql_text = src[:sql] || src["sql"]
|
|
134
|
+
return sql(sql_text) if sql_text
|
|
135
|
+
|
|
136
|
+
coll = src[:collection] || src["collection"]
|
|
137
|
+
raise ArgumentError, "an LLM source needs :sql or :collection" unless coll
|
|
138
|
+
|
|
139
|
+
documents(coll, filter: src[:filter] || src["filter"] || Filter.all, limit: src[:limit] || src["limit"])
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|