cursor support
This commit is contained in:
parent
9156d52871
commit
15245d2e1c
4 changed files with 479 additions and 11 deletions
70
README.md
70
README.md
|
@ -20,7 +20,9 @@ This module is Perl5 binding for Unqlite.
|
||||||
|
|
||||||
If you want to know more information about Unqlite, see [http://unqlite.org/](http://unqlite.org/).
|
If you want to know more information about Unqlite, see [http://unqlite.org/](http://unqlite.org/).
|
||||||
|
|
||||||
Current version of Unqlite.pm supports only some `kv_*` methods. Patches welcome.
|
This version of Unqlite.pm does not provides document store feature. Patches welcome.
|
||||||
|
|
||||||
|
__You can use Unqlite.pm as DBM__.
|
||||||
|
|
||||||
# METHODS
|
# METHODS
|
||||||
|
|
||||||
|
@ -48,6 +50,72 @@ Current version of Unqlite.pm supports only some `kv_*` methods. Patches welcome
|
||||||
|
|
||||||
This API returns stringified version of `$db->rc()`. It's not human readable but it's better than magic number.
|
This API returns stringified version of `$db->rc()`. It's not human readable but it's better than magic number.
|
||||||
|
|
||||||
|
- `my $cursor = $db->cursor_init()`
|
||||||
|
|
||||||
|
Create new cursor object.
|
||||||
|
|
||||||
|
# Unqlite::Cursor
|
||||||
|
|
||||||
|
Unqlite supports cursor for iterating entries.
|
||||||
|
|
||||||
|
Here is example code:
|
||||||
|
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
my @ret;
|
||||||
|
for ($cursor->first_entry; $cursor->valid_entry; $cursor->next_entry) {
|
||||||
|
push @ret, $cursor->key(), $cursor->data()
|
||||||
|
}
|
||||||
|
|
||||||
|
## METHODS
|
||||||
|
|
||||||
|
- `$cursor->first_entry()`
|
||||||
|
|
||||||
|
Seek cursor to first entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
- `$cursor->last_entry()`
|
||||||
|
|
||||||
|
Seek cursor to last entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
- `$cursor->valid_entry()`
|
||||||
|
|
||||||
|
This will return 1 when valid. 0 otherwise
|
||||||
|
|
||||||
|
- `$cursor->key()`
|
||||||
|
|
||||||
|
Get current entry's key.
|
||||||
|
|
||||||
|
- `$cursor->data()`
|
||||||
|
|
||||||
|
Get current entry's data.
|
||||||
|
|
||||||
|
- `$cursor->next_entry()`
|
||||||
|
|
||||||
|
Seek cursor to next entry.
|
||||||
|
|
||||||
|
- `$cursor->prev_entry()`
|
||||||
|
|
||||||
|
Seek cursor to previous entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
- `$cursor->seek($key, $opt=UNQLITE_CURSOR_MATCH_EXACT)`
|
||||||
|
|
||||||
|
Seek cursor to ` $key `.
|
||||||
|
|
||||||
|
You can specify the option as ` $opt `. Please see [http://unqlite.org/c\_api/unqlite\_kv\_cursor.html](http://unqlite.org/c\_api/unqlite\_kv\_cursor.html) for more details.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
- `$cursor->delete_entry()`
|
||||||
|
|
||||||
|
Delete the database entry pointed by the cursor.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
# LICENSE
|
# LICENSE
|
||||||
|
|
||||||
Copyright (C) tokuhirom.
|
Copyright (C) tokuhirom.
|
||||||
|
|
131
lib/Unqlite.pm
131
lib/Unqlite.pm
|
@ -39,6 +39,63 @@ sub errstr {
|
||||||
if ($rc==UNQLITE_LOCKERR()) { return "UNQLITE_LOCKERR" }
|
if ($rc==UNQLITE_LOCKERR()) { return "UNQLITE_LOCKERR" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub cursor_init {
|
||||||
|
my $self = shift;
|
||||||
|
bless [$self->_cursor_init(), $self], 'Unqlite::Cursor';
|
||||||
|
}
|
||||||
|
|
||||||
|
package Unqlite::Cursor;
|
||||||
|
|
||||||
|
sub first_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_first_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub key {
|
||||||
|
my $self = shift;
|
||||||
|
_key($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub data {
|
||||||
|
my $self = shift;
|
||||||
|
_data ($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub next_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_next_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub valid_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_valid_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub seek {
|
||||||
|
my $self = shift;
|
||||||
|
_seek($self->[0], @_);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub delete_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_delete_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prev_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_prev_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub last_entry {
|
||||||
|
my $self = shift;
|
||||||
|
_last_entry($self->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub DESTROY {
|
||||||
|
my $self = shift;
|
||||||
|
_release($self->[0], $self->[1]);
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
@ -66,7 +123,9 @@ This module is Perl5 binding for Unqlite.
|
||||||
|
|
||||||
If you want to know more information about Unqlite, see L<http://unqlite.org/>.
|
If you want to know more information about Unqlite, see L<http://unqlite.org/>.
|
||||||
|
|
||||||
Current version of Unqlite.pm supports only some C<kv_*> methods. Patches welcome.
|
This version of Unqlite.pm does not provides document store feature. Patches welcome.
|
||||||
|
|
||||||
|
B<You can use Unqlite.pm as DBM>.
|
||||||
|
|
||||||
=head1 METHODS
|
=head1 METHODS
|
||||||
|
|
||||||
|
@ -96,6 +155,76 @@ Return code from unqlite. It may updates after any Unqlite API call.
|
||||||
|
|
||||||
This API returns stringified version of C<< $db->rc() >>. It's not human readable but it's better than magic number.
|
This API returns stringified version of C<< $db->rc() >>. It's not human readable but it's better than magic number.
|
||||||
|
|
||||||
|
=item C<< my $cursor = $db->cursor_init() >>
|
||||||
|
|
||||||
|
Create new cursor object.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 Unqlite::Cursor
|
||||||
|
|
||||||
|
Unqlite supports cursor for iterating entries.
|
||||||
|
|
||||||
|
Here is example code:
|
||||||
|
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
my @ret;
|
||||||
|
for ($cursor->first_entry; $cursor->valid_entry; $cursor->next_entry) {
|
||||||
|
push @ret, $cursor->key(), $cursor->data()
|
||||||
|
}
|
||||||
|
|
||||||
|
=head2 METHODS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item C<< $cursor->first_entry() >>
|
||||||
|
|
||||||
|
Seek cursor to first entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
=item C<< $cursor->last_entry() >>
|
||||||
|
|
||||||
|
Seek cursor to last entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
=item C<< $cursor->valid_entry() >>
|
||||||
|
|
||||||
|
This will return 1 when valid. 0 otherwise
|
||||||
|
|
||||||
|
=item C<< $cursor->key() >>
|
||||||
|
|
||||||
|
Get current entry's key.
|
||||||
|
|
||||||
|
=item C<< $cursor->data() >>
|
||||||
|
|
||||||
|
Get current entry's data.
|
||||||
|
|
||||||
|
=item C<< $cursor->next_entry() >>
|
||||||
|
|
||||||
|
Seek cursor to next entry.
|
||||||
|
|
||||||
|
=item C<< $cursor->prev_entry() >>
|
||||||
|
|
||||||
|
Seek cursor to previous entry.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
=item C<< $cursor->seek($key, $opt=UNQLITE_CURSOR_MATCH_EXACT) >>
|
||||||
|
|
||||||
|
Seek cursor to C< $key >.
|
||||||
|
|
||||||
|
You can specify the option as C< $opt >. Please see L<http://unqlite.org/c_api/unqlite_kv_cursor.html> for more details.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
|
=item C<< $cursor->delete_entry() >>
|
||||||
|
|
||||||
|
Delete the database entry pointed by the cursor.
|
||||||
|
|
||||||
|
Return true if succeeded, false otherwise.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 LICENSE
|
=head1 LICENSE
|
||||||
|
|
226
lib/Unqlite.xs
226
lib/Unqlite.xs
|
@ -17,12 +17,11 @@ extern "C" {
|
||||||
|
|
||||||
#define XS_STATE(type, x) (INT2PTR(type, SvROK(x) ? SvIV(SvRV(x)) : SvIV(x)))
|
#define XS_STATE(type, x) (INT2PTR(type, SvROK(x) ? SvIV(SvRV(x)) : SvIV(x)))
|
||||||
|
|
||||||
/* #define XS_STRUCT2OBJ(sv, class, obj) if (obj == NULL) { sv_setsv(sv, &PL_sv_undef); } else { sv_setref_pv(sv, class, (void *) obj); } */
|
|
||||||
#define XS_STRUCT2OBJ(sv, class, obj) \
|
#define XS_STRUCT2OBJ(sv, class, obj) \
|
||||||
sv = newSViv(PTR2IV(obj)); \
|
sv = newSViv(PTR2IV(obj)); \
|
||||||
sv = newRV_noinc(sv); \
|
sv = newRV_noinc(sv); \
|
||||||
sv_bless(sv, gv_stashpv(class, 1)); \
|
sv_bless(sv, gv_stashpv(class, 1)); \
|
||||||
SvREADONLY_on(sv);
|
SvREADONLY_on(sv);
|
||||||
|
|
||||||
#define SETRC(rc) \
|
#define SETRC(rc) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -30,11 +29,6 @@ extern "C" {
|
||||||
SvIV_set(i, rc); \
|
SvIV_set(i, rc); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
{ HV * const stash = gv_stashpvn("Unqlite", strlen("Unqlite"), TRUE); \
|
|
||||||
(void)hv_store(stash, "rc", 2, newSViv(rc), 0); } */
|
|
||||||
|
|
||||||
|
|
||||||
MODULE = Unqlite PACKAGE = Unqlite
|
MODULE = Unqlite PACKAGE = Unqlite
|
||||||
|
|
||||||
PROTOTYPES: DISABLE
|
PROTOTYPES: DISABLE
|
||||||
|
@ -66,6 +60,10 @@ BOOT:
|
||||||
newCONSTSUB(stash, "UNQLITE_READ_ONLY", newSViv(UNQLITE_READ_ONLY));
|
newCONSTSUB(stash, "UNQLITE_READ_ONLY", newSViv(UNQLITE_READ_ONLY));
|
||||||
newCONSTSUB(stash, "UNQLITE_LOCKERR", newSViv(UNQLITE_LOCKERR));
|
newCONSTSUB(stash, "UNQLITE_LOCKERR", newSViv(UNQLITE_LOCKERR));
|
||||||
|
|
||||||
|
newCONSTSUB(stash, "UNQLITE_CURSOR_MATCH_EXACT", newSViv(UNQLITE_CURSOR_MATCH_EXACT));
|
||||||
|
newCONSTSUB(stash, "UNQLITE_CURSOR_MATCH_LE", newSViv(UNQLITE_CURSOR_MATCH_LE));
|
||||||
|
newCONSTSUB(stash, "UNQLITE_CURSOR_MATCH_GE", newSViv(UNQLITE_CURSOR_MATCH_GE));
|
||||||
|
|
||||||
SV*
|
SV*
|
||||||
open(klass, filename, mode=UNQLITE_OPEN_CREATE)
|
open(klass, filename, mode=UNQLITE_OPEN_CREATE)
|
||||||
const char *klass;
|
const char *klass;
|
||||||
|
@ -200,3 +198,213 @@ CODE:
|
||||||
rc = unqlite_close(pdb);
|
rc = unqlite_close(pdb);
|
||||||
SETRC(rc);
|
SETRC(rc);
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_cursor_init(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
unqlite_kv_cursor* cursor;
|
||||||
|
CODE:
|
||||||
|
unqlite *pdb = XS_STATE(unqlite*, self);
|
||||||
|
rc = unqlite_kv_cursor_init(pdb, &cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
sv = newSViv(PTR2IV(cursor));
|
||||||
|
sv = newRV_noinc(sv);
|
||||||
|
SvREADONLY_on(sv);
|
||||||
|
RETVAL = sv;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
|
||||||
|
MODULE = Unqlite PACKAGE = Unqlite::Cursor
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_first_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_first_entry(cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
int
|
||||||
|
_valid_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
/* This will return 1 when valid. 0 otherwise */
|
||||||
|
rc = unqlite_kv_cursor_valid_entry(cursor);
|
||||||
|
RETVAL = rc;
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_next_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_next_entry(cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_last_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_last_entry(cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_prev_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_prev_entry(cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_key(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
int nbytes;
|
||||||
|
char*buf;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_key(cursor, NULL, &nbytes);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc!=UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
goto last;
|
||||||
|
}
|
||||||
|
Newxz(buf, nbytes, char);
|
||||||
|
rc = unqlite_kv_cursor_key(cursor, buf, &nbytes);
|
||||||
|
SETRC(rc);
|
||||||
|
sv = newSVpv(buf, nbytes);
|
||||||
|
Safefree(buf);
|
||||||
|
RETVAL = sv;
|
||||||
|
last:
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_data(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
SV * sv;
|
||||||
|
int rc;
|
||||||
|
unqlite_int64 nbytes;
|
||||||
|
char*buf;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_data(cursor, NULL, &nbytes);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc!=UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
goto last;
|
||||||
|
}
|
||||||
|
Newxz(buf, nbytes, char);
|
||||||
|
rc = unqlite_kv_cursor_data(cursor, buf, &nbytes);
|
||||||
|
SETRC(rc);
|
||||||
|
sv = newSVpv(buf, nbytes);
|
||||||
|
Safefree(buf);
|
||||||
|
RETVAL = sv;
|
||||||
|
last:
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
void
|
||||||
|
_release(self, db)
|
||||||
|
SV * self;
|
||||||
|
SV * db;
|
||||||
|
CODE:
|
||||||
|
unqlite *pdb = XS_STATE(unqlite*, db);
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
unqlite_kv_cursor_release(pdb, cursor);
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_seek(self, key_s, opt=UNQLITE_CURSOR_MATCH_EXACT)
|
||||||
|
SV * self;
|
||||||
|
SV * key_s;
|
||||||
|
int opt;
|
||||||
|
PREINIT:
|
||||||
|
STRLEN len;
|
||||||
|
char * key;
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
key = SvPV(key_s, len);
|
||||||
|
rc = unqlite_kv_cursor_seek(cursor, key, len, opt);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
_delete_entry(self)
|
||||||
|
SV * self;
|
||||||
|
PREINIT:
|
||||||
|
int rc;
|
||||||
|
CODE:
|
||||||
|
unqlite_kv_cursor *cursor = XS_STATE(unqlite_kv_cursor*, self);
|
||||||
|
rc = unqlite_kv_cursor_delete_entry(cursor);
|
||||||
|
SETRC(rc);
|
||||||
|
if (rc == UNQLITE_OK) {
|
||||||
|
RETVAL = &PL_sv_yes;
|
||||||
|
} else {
|
||||||
|
RETVAL = &PL_sv_undef;
|
||||||
|
}
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
63
t/02_cursor.t
Normal file
63
t/02_cursor.t
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use strict;
|
||||||
|
use Test::More;
|
||||||
|
|
||||||
|
use File::Temp qw(tempdir);
|
||||||
|
use Unqlite;
|
||||||
|
|
||||||
|
my $tmp = tempdir( CLEANUP => 1 );
|
||||||
|
|
||||||
|
my $db = Unqlite->open("$tmp/foo.db");
|
||||||
|
{
|
||||||
|
isa_ok($db, 'Unqlite');
|
||||||
|
|
||||||
|
ok($db->kv_store("foo", "bar"));
|
||||||
|
ok($db->kv_store("hoge", "fuga"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
$cursor->first_entry;
|
||||||
|
is($cursor->valid_entry(), 1);
|
||||||
|
is($cursor->key(), 'hoge');
|
||||||
|
is($cursor->data(), 'fuga');
|
||||||
|
ok($cursor->next_entry());
|
||||||
|
is($cursor->valid_entry(), 1);
|
||||||
|
is($cursor->key(), 'foo');
|
||||||
|
is($cursor->data(), 'bar');
|
||||||
|
ok(!$cursor->next_entry());
|
||||||
|
is($cursor->valid_entry(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
my @ret;
|
||||||
|
for ($cursor->first_entry; $cursor->valid_entry; $cursor->next_entry) {
|
||||||
|
push @ret, $cursor->key(), $cursor->data()
|
||||||
|
}
|
||||||
|
is_deeply(\@ret, [qw(hoge fuga foo bar)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
$cursor->last_entry;
|
||||||
|
is($cursor->valid_entry(), 1);
|
||||||
|
is($cursor->key(), 'foo');
|
||||||
|
is($cursor->data(), 'bar');
|
||||||
|
ok($cursor->prev_entry());
|
||||||
|
is($cursor->valid_entry(), 1);
|
||||||
|
is($cursor->key(), 'hoge');
|
||||||
|
is($cursor->data(), 'fuga');
|
||||||
|
ok(!$cursor->prev_entry());
|
||||||
|
is($cursor->valid_entry(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $cursor = $db->cursor_init();
|
||||||
|
ok(!$cursor->seek("NON EXISTENT"));
|
||||||
|
ok($cursor->seek("foo"));
|
||||||
|
is($cursor->valid_entry(), 1);
|
||||||
|
$cursor->delete_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
||||||
|
|
Loading…
Add table
Reference in a new issue