kriszyp / lmdb-js

Simple, efficient, ultra-fast, scalable data store wrapper for LMDB
Other
484 stars 39 forks source link

Range queries seem to be broken in 1.6.0-beta.1? #69

Closed vladar closed 2 years ago

vladar commented 3 years ago

Reproduction:

const { open } = require("lmdb-store")

const db = open({
  name: `store`,
  path: process.cwd() + `/test`,
})

const keys = [
  [ 'foo', 0 ],
  [ 'foo', 1 ],
  [ 'foo', 2 ],
]

async function run() {
  await db.clear()

  let promise
  keys.forEach((key, i) => {
    promise = db.put(key, i)
  })
  await promise

  const result = db.getRange({
    start: [ 'foo', 2 ],
    end: [ 'foo', [2, null] ],
  })
  console.log(Array.from(result))
}

run().catch(console.error)

Expected output:

[ { key: [ 'foo', 2 ], value: 2 } ] (I see this in 1.5.5)

Actual output:

[] (in 1.6.0-beta.1)

vladar commented 3 years ago

This kinda works:

  const result = db.getRange({
    start: ['foo', 0],
    end: [ 'foo', 1 ],
  })

But returns:

[ { key: [ 'foo', 1 ], value: 1 } ]

In 1.5.5 it returns:

[ { key: [ 'foo', 0 ], value: 0 } ]
vladar commented 3 years ago

This also returns empty [] in 1.6.0

  const result = db.getRange({
    start: ['foo'],
    end: ['foo', 1],
  })

but returned [ { key: [ 'foo', 0 ], value: 0 } ] in 1.5.5.

Just trying some examples

kriszyp commented 3 years ago

Fixes published in beta 2.

vladar commented 3 years ago

Getting core dump with the latest beta:

#
# Fatal error in , line 0
# unreachable code
#
#
#
#FailureMessage Object: 0x7ffd40d204e0
 1: 0xa92851  [/root/.nvm/versions/node/v14.17.2/bin/node]
 2: 0x1a1ac64 V8_Fatal(char const*, ...) [/root/.nvm/versions/node/v14.17.2/bin/node]
 3: 0xbc28f6 v8::CFunction::CFunction(void const*, v8::CFunctionInfo const*) [/root/.nvm/versions/node/v14.17.2/bin/node]
 4: 0x7f7f400949c5  [/spikes/gatsby/benchmarks/query-filters-sort/node_modules/lmdb-store/build/Release/lmdb-store.node]
 5: 0x7f7f4008e056 node_register_module_v83 [/spikes/gatsby/benchmarks/query-filters-sort/node_modules/lmdb-store/build/Release/lmdb-store.node]
 6: 0x9fbb07  [/root/.nvm/versions/node/v14.17.2/bin/node]
 7: 0x9fac9b node::binding::DLOpen(v8::FunctionCallbackInfo<v8::Value> const&) [/root/.nvm/versions/node/v14.17.2/bin/node]
 8: 0xc06acb  [/root/.nvm/versions/node/v14.17.2/bin/node]
 9: 0xc08076  [/root/.nvm/versions/node/v14.17.2/bin/node]
10: 0xc086f6 v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [/root/.nvm/versions/node/v14.17.2/bin/node]
11: 0x1427159  [/root/.nvm/versions/node/v14.17.2/bin/node]
Illegal instruction (core dumped)
error Command failed with exit code 132.

And something similar on Windows:

#
# Fatal error in , line 0
# unreachable code
#
#
#
#FailureMessage Object: 0000001B28EFB650
 1: 00007FF62B84046F napi_wrap+109311
 2: 00007FF62B774C4F std::basic_ostream<char,std::char_traits<char> >::operator<<+57167
 3: 00007FF62C3AFAA2 V8_Fatal+162
 4: 00007FF62C089F9A v8::CFunction::CFunction+170
 5: 00007FFAA15A1F42 EnvWrap::setupExports+4738 [c:\dev\gatsby\node_modules\lmdb-store\src\env.cpp]:L1137
 6: 00007FFAA159A60E node_register_module_v83+14 [c:\dev\gatsby\node_modules\lmdb-store\src\node-lmdb.cpp]:L38
 7: 00007FF62B809C5C node::Buffer::New+6972
 8: 00007FF62B80A783 node::Buffer::New+9827
 9: 00007FF62C05FC2F v8::internal::Builtins::builtin_handle+321439
10: 00007FF62C05F1C4 v8::internal::Builtins::builtin_handle+318772
11: 00007FF62C05F4B7 v8::internal::Builtins::builtin_handle+319527
12: 00007FF62C05F303 v8::internal::Builtins::builtin_handle+319091
13: 00007FF62C13B5ED v8::internal::SetupIsolateDelegate::SetupHeap+464173
14: 00007FF62C0D3EF2 v8::internal::SetupIsolateDelegate::SetupHeap+40498
15: 00007FF62C0D3EF2 v8::internal::SetupIsolateDelegate::SetupHeap+40498
16: 00007FF62C0D3EF2 v8::internal::SetupIsolateDelegate::SetupHeap+40498
17: 000000E78C68E61C 

Process finished with exit code -1073741819 (0xC0000005)

But beta1 with ordered-binary@0.2.1 seems to work fine in my tests

kriszyp commented 3 years ago

Ok, sounds like I need to sort out the fast api calls headers on other node versions (or disable by default). Thanks for the heads up.

vladar commented 3 years ago

Several other test cases related to null and Symbol are failing for us with 1.6.0-beta.1 (and ordered binary 0.2.1). Repro:

const { open } = require("lmdb-store")

const db = open({
  name: `store`,
  path: process.cwd() + `/test`,
})

const undefinedSymbol = Symbol(`undef`)

const keys = [
  [ 'Test/nil:1', null, 1 ],
  [ 'Test/nil:1', undefinedSymbol, 2 ],
  [ 'Test/nil:1', 'not null', 3 ],
]

async function run() {
  db.transactionSync(() => {
    db.clear()
  })

  let promise
  keys.forEach((key, i) => {
    promise = db.put(key, i)
  })
  await promise

  // Problem 1: filter by null doesn't work
  const result = db.getRange({
    start: [ 'Test/nil:1', null ],
    end: [ 'Test/nil:1', [ null, 'ÿÿÿÿ' ] ],
  })
  // 1.5.5 returns an array with 1 item, 1.6.0-beta.1 returns []
  console.log(Array.from(result))

  // Problem 2: Symbol consumes sibling value
  console.log(Array.from(db.getRange({})))

  // Note how the symbol includes "2" (the next element within the original key):
  // [
  //   { key: [ 'Test/nil:1', null, 1 ], value: 0 },
  //   { key: [ 'Test/nil:1', Symbol(undef,2) ], value: 1 },
  //   { key: [ 'Test/nil:1', 'not null', 3 ], value: 2 }
  // ]
}

run().catch(console.error)
kriszyp commented 3 years ago

I think these should be fixed in beta 3.

vladar commented 3 years ago

I think there is one more issue with reverse flag. Repro:

const { open } = require("lmdb-store")

const db = open({
  name: `store`,
  path: process.cwd() + `/test`,
})

const keys = [
  [ 'Test/frontmatter.blue:-1', 100, 1 ],
  [ 'Test/frontmatter.blue:-1', 10010, 2 ],
  [ 'Test/frontmatter.blue:-1', 10010, 3 ],
]

async function run() {
  db.transactionSync(() => {
    db.clear()
  })

  let promise
  keys.forEach((key, i) => {
    promise = db.put(key, i)
  })
  await promise

  const result = db.getRange({
    start: [ 'Test/frontmatter.blue:-1', null],
    end: [ 'Test/frontmatter.blue:-1', null ],
    reverse: true
  })

  // 1.5.5 returns 0 results, 1.6.0-beta.3 returns 1 result:
  // [ { key: [ 'Test/frontmatter.blue:-1', 100, 1 ], value: 0 } ]
  console.log(Array.from(result))
}

run().catch(console.error)
kriszyp commented 3 years ago

Should be fixed in the v1.6.0 release.