Skip to content

Commit f402612

Browse files
authored
Merge pull request #29 from zookzook/sessions
Add support for session and transaction
2 parents 26d9db4 + 4176248 commit f402612

36 files changed

+2119
-689
lines changed

.travis.yml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,19 @@ sudo: required
22
language: elixir
33

44
elixir:
5-
- 1.6
6-
- 1.7
75
- 1.8
6+
- 1.9
87

98
install:
109
- wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${MONGODB}.tgz
11-
- tar xzf mongodb-linux-x86_64-${MONGODB}.tgz
12-
- ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --version
10+
- mkdir ${PWD}/mongodb
11+
- tar xzf mongodb-linux-x86_64-${MONGODB}.tgz --strip-components=1 -C ${PWD}/mongodb
1312

1413
before_script:
15-
- export PATH=${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/:$PATH
14+
- export PATH=${PWD}/mongodb/bin/:$PATH
1615
- bash ./start_mongo.bash
17-
- mkdir ${PWD}/mongodb-linux-x86_64-${MONGODB}/data
18-
- ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --dbpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/data --logpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/mongodb.log --fork
16+
- mkdir ${PWD}/mongodb/data
17+
- ${PWD}/mongodb/bin/mongod --dbpath ${PWD}/mongodb/data --logpath ${PWD}/mongodb/mongodb.log --fork
1918

2019
script:
2120
- mix local.hex --force
@@ -27,4 +26,4 @@ env:
2726
- MONGODB=3.2.20
2827
- MONGODB=3.4.16
2928
- MONGODB=3.6.6
30-
- MONGODB=4.0.9
29+
- MONGODB=ubuntu1604-v4.2-latest

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
## 0.6.0
2+
3+
* Enhancements
4+
* refactored `writeConcern`
5+
* refactored `filter_nils`
6+
* refactored usage of `ReadPreference`
7+
* added support for sessions (`ServerSession`, `SessionPool`, `Session`)
8+
* added support for transaction
9+
* added Decimal128 encoder
10+
* added support for transaction to gridfs and bulk operation
11+
* added `create` command (explicitly creating a collection or view)
12+
13+
114
## 0.5.7
215

316
* Bug Fixes

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ for the individual options.
2222
* [x] Removed depreacated op codes ([See](https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#request-opcodes))
2323
* [x] Added `op_msg` support ([See](https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op-msg))
2424
* [x] Added bulk writes ([See](https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#write))
25-
* [ ] Add support for driver sessions ([See](https://github.com/mongodb/specifications/blob/master/source/sessions/driver-sessions.rst))
26-
* [ ] Add support driver transactions ([See](https://github.com/mongodb/specifications/blob/master/source/transactions/transactions.rst))
25+
* [x] Add support for driver sessions ([See](https://github.com/mongodb/specifications/blob/master/source/sessions/driver-sessions.rst))
26+
* [x] Add support driver transactions ([See](https://github.com/mongodb/specifications/blob/master/source/transactions/transactions.rst))
2727
* [ ] Add support for `op_compressed` ([See](https://github.com/mongodb/specifications/blob/master/source/compression/OP_COMPRESSED.rst))
2828
* [ ] Because the driver is used in production environments, quick adjustments are necessary.
2929

3030
## Features
3131

32-
* Supports MongoDB versions 3.2, 3.4, 3.6, 4.0
32+
* Supports MongoDB versions 3.2, 3.4, 3.6, 4.0, 4.2
3333
* Connection pooling ([through DBConnection 2.x](https://github.com/elixir-ecto/db_connection))
3434
* Streaming cursors
3535
* Performant ObjectID generation
@@ -57,6 +57,7 @@ for the individual options.
5757
symbol "foo" (2)
5858
min key :BSON_min
5959
max key :BSON_max
60+
decimal128 Decimal{}
6061

6162
1) Since BSON documents are ordered Elixir maps cannot be used to fully represent them. This driver chose to accept both maps and lists of key-value pairs when encoding but will only decode documents to lists. This has the side-effect that it's impossible to discern empty arrays from empty documents. Additionally the driver will accept both atoms and strings for document keys but will only decode to strings.
6263

config/config.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ use Mix.Config
88
# if you want to provide default values for your application for third-
99
# party users, it should be done in your mix.exs file.
1010

11+
config :logger, :console,
12+
level: :info,
13+
truncate: 1024,
14+
format: "$time [$level] $message ($metadata)\n\n",
15+
metadata: [:module, :function, :line]
16+
1117
# Sample configuration:
1218
#
1319
# config :logger, :console,

jetbrains.svg

Lines changed: 66 additions & 0 deletions
Loading

lib/bson/decimal128.ex

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
defmodule BSON.Decimal128 do
2+
3+
@moduledoc """
4+
see https://en.wikipedia.org/wiki/Decimal128_floating-point_format
5+
"""
6+
27
use Bitwise
38

49
@signed_bit_mask 1 <<< 63
@@ -7,13 +12,22 @@ defmodule BSON.Decimal128 do
712
@combintation_nan 31
813
@exponent_mask 0x3fff
914
@exponent_bias 6176
15+
@max_exponent 6111
16+
@min_exponent -6176
17+
@s_nan_mask 0x1 <<< 57
18+
@significand_mask ((0x1 <<< 49)-1)
19+
@low_mask 0xffffffffffffffff
1020

1121
def decode(<<_::little-64, high::little-64>> = bits) do
1222
is_negative = (high &&& @signed_bit_mask) == (@signed_bit_mask)
1323
combination = (high >>> 58 &&& @combination_mask)
1424
two_highest_bits_set = combination >>> 3 == 3
1525
is_infinity = two_highest_bits_set && combination == @combintation_infinity
16-
is_nan = two_highest_bits_set && combination == @combintation_nan
26+
is_nan = case {(two_highest_bits_set && combination) == @combintation_nan, (high &&& @s_nan_mask) == @s_nan_mask} do
27+
{true, true} -> :sNan
28+
{true, false} -> :qNan
29+
_ -> false
30+
end
1731

1832
exponent = exponent(high, two_highest_bits_set)
1933

@@ -27,11 +41,52 @@ defmodule BSON.Decimal128 do
2741
)
2842
end
2943

44+
@doc """
45+
s 11110 xx...x ±infinity
46+
s 11111 0x...x a quiet NaN
47+
s 11111 1x...x a signalling NaN
48+
"""
49+
def encode(%Decimal{sign: -1, coef: :inf}) do
50+
low = 0
51+
high = 0x3e <<< 58
52+
<<low::little-64, high::little-64>>
53+
end
54+
def encode(%Decimal{coef: :inf}) do
55+
low = 0
56+
high = 0x1e <<< 58
57+
<<low::little-64, high::little-64>>
58+
end
59+
def encode(%Decimal{coef: :qNaN}) do
60+
low = 0
61+
high = 0x1f <<< 58
62+
<<low::little-64, high::little-64>>
63+
end
64+
def encode(%Decimal{coef: :sNaN}) do
65+
low = 0
66+
high = 0x3f <<< 57
67+
<<low::little-64, high::little-64>>
68+
end
69+
def encode(%Decimal{sign: sign, coef: significand, exp: exponent}) when exponent >= @min_exponent and exponent <= @max_exponent do
70+
biasedExponent = exponent + @exponent_bias
71+
low = significand &&& @low_mask
72+
high = (significand >>> 64) &&& @significand_mask ## mask max significand
73+
high = bor(high, biasedExponent <<< 49)
74+
high = case sign do
75+
1 -> high
76+
_ -> bor(high, @signed_bit_mask)
77+
end
78+
79+
<<low::little-64, high::little-64>>
80+
end
81+
def encode(%Decimal{exp: exponent}) do
82+
message = "Exponent is out of range for Decimal128 encoding, #{exponent}"
83+
raise ArgumentError, message
84+
end
85+
3086
defp exponent(high, _two_highest_bits_set = true) do
3187
biased_exponent = (high >>> 47) &&& @exponent_mask
3288
biased_exponent - @exponent_bias
3389
end
34-
3590
defp exponent(high, _two_highest_bits_not_set) do
3691
biased_exponent = (high >>> 49) &&& @exponent_mask
3792
biased_exponent - @exponent_bias
@@ -40,23 +95,21 @@ defmodule BSON.Decimal128 do
4095
defp value(%{is_negative: true, is_infinity: true}, _, _) do
4196
%Decimal{sign: -1, coef: :inf}
4297
end
43-
4498
defp value(%{is_negative: false, is_infinity: true}, _, _) do
4599
%Decimal{coef: :inf}
46100
end
47-
48-
defp value(%{is_nan: true}, _, _) do
101+
defp value(%{is_nan: :qNan}, _, _) do
49102
%Decimal{coef: :qNaN}
50103
end
51-
104+
defp value(%{is_nan: :sNan}, _, _) do
105+
%Decimal{coef: :sNaN}
106+
end
52107
defp value(%{two_highest_bits_set: true}, _, _) do
53108
%Decimal{sign: 0, coef: 0, exp: 0}
54109
end
55-
56110
defp value(%{is_negative: true}, coef, exponent) do
57111
%Decimal{sign: -1, coef: coef, exp: exponent}
58112
end
59-
60113
defp value(_, coef, exponent) do
61114
%Decimal{coef: coef, exp: exponent}
62115
end

lib/bson/encoder.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ defmodule BSON.Encoder do
5151
def encode(%BSON.Timestamp{value: epoch, ordinal: ordinal}),
5252
do: <<ordinal::int32, epoch::int32>>
5353

54+
def encode(%BSON.LongNumber{value: value}), do: <<value::int64>>
55+
56+
def encode(%Decimal{} = value), do: BSON.Decimal128.encode(value)
57+
5458
def encode([]) do
5559
document([])
5660
end
@@ -140,6 +144,8 @@ defmodule BSON.Encoder do
140144
defp type(%BSON.JavaScript{scope: nil}), do: @type_js
141145
defp type(%BSON.JavaScript{}), do: @type_js_scope
142146
defp type(%BSON.Timestamp{}), do: @type_timestamp
147+
defp type(%BSON.LongNumber{}), do: @type_int64
148+
defp type(%Decimal{}), do: @type_decimal128
143149
defp type(nil), do: @type_null
144150
defp type(:BSON_min), do: @type_min
145151
defp type(:BSON_max), do: @type_max

lib/bson/types.ex

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,33 @@ defmodule BSON.Timestamp do
151151
@type t :: %__MODULE__{value: integer, ordinal: integer}
152152
defstruct [:value, :ordinal]
153153

154+
def is_after(this, that) do
155+
(this.value > that.value or (this.value == that.value and this.ordinal > that.ordinal))
156+
end
157+
158+
def is_before(this, that) do
159+
(this.value < that.value or (this.value == that.value and this.ordinal < that.ordinal))
160+
end
161+
154162
defimpl Inspect do
155163
def inspect(%BSON.Timestamp{value: value, ordinal: ordinal}, _opts) do
156164
"#BSON.Timestamp<#{value}:#{ordinal}>"
157165
end
158166
end
159167
end
168+
169+
defmodule BSON.LongNumber do
170+
@moduledoc """
171+
Represents BSON long type
172+
"""
173+
174+
@type t :: %__MODULE__{value: integer}
175+
176+
defstruct [value: 0]
177+
178+
defimpl Inspect do
179+
def inspect(%BSON.LongNumber{value: value}, _opts) do
180+
"#BSON.LongNumber<#{value}>"
181+
end
182+
end
183+
end

0 commit comments

Comments
 (0)