diff --git a/README.md b/README.md index fe96cf9..de5a1b6 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,14 @@ Current version of Unqlite.pm supports only some `kv_*` methods. Patches welcome Delte ` $key ` from database. +- `$db->rc();` + + Return code from unqlite. It may updates after any Unqlite API call. + +- `$db->errstr()` + + This API returns stringified version of `$db->rc()`. It's not human readable but it's better than magic number. + # LICENSE Copyright (C) tokuhirom. diff --git a/lib/Unqlite.pm b/lib/Unqlite.pm index 0990921..db41563 100644 --- a/lib/Unqlite.pm +++ b/lib/Unqlite.pm @@ -4,10 +4,41 @@ use strict; use warnings; our $VERSION = "0.01"; +our $rc = 0; use XSLoader; XSLoader::load(__PACKAGE__, $VERSION); +sub rc { $Unqlite::rc } + +sub errstr { + my $self = shift; + if ($rc==Unqlite::UNQLITE_OK()) { return "UNQLITE_OK" } + if ($rc==UNQLITE_NOMEM()) { return "UNQLITE_NOMEM" } + if ($rc==UNQLITE_ABORT()) { return "UNQLITE_ABORT" } + if ($rc==UNQLITE_IOERR()) { return "UNQLITE_IOERR" } + if ($rc==UNQLITE_CORRUPT()) { return "UNQLITE_CORRUPT" } + if ($rc==UNQLITE_LOCKED()) { return "UNQLITE_LOCKED" } + if ($rc==UNQLITE_BUSY()) { return "UNQLITE_BUSY" } + if ($rc==UNQLITE_DONE()) { return "UNQLITE_DONE" } + if ($rc==UNQLITE_PERM()) { return "UNQLITE_PERM" } + if ($rc==UNQLITE_NOTIMPLEMENTED()) { return "UNQLITE_NOTIMPLEMENTED" } + if ($rc==UNQLITE_NOTFOUND()) { return "UNQLITE_NOTFOUND" } + if ($rc==UNQLITE_NOOP()) { return "UNQLITE_NOOP" } + if ($rc==UNQLITE_INVALID()) { return "UNQLITE_INVALID" } + if ($rc==UNQLITE_EOF()) { return "UNQLITE_EOF" } + if ($rc==UNQLITE_UNKNOWN()) { return "UNQLITE_UNKNOWN" } + if ($rc==UNQLITE_LIMIT()) { return "UNQLITE_LIMIT" } + if ($rc==UNQLITE_EXISTS()) { return "UNQLITE_EXISTS" } + if ($rc==UNQLITE_EMPTY()) { return "UNQLITE_EMPTY" } + if ($rc==UNQLITE_COMPILE_ERR()) { return "UNQLITE_COMPILE_ERR" } + if ($rc==UNQLITE_VM_ERR()) { return "UNQLITE_VM_ERR" } + if ($rc==UNQLITE_FULL()) { return "UNQLITE_FULL" } + if ($rc==UNQLITE_CANTOPEN()) { return "UNQLITE_CANTOPEN" } + if ($rc==UNQLITE_READ_ONLY()) { return "UNQLITE_READ_ONLY" } + if ($rc==UNQLITE_LOCKERR()) { return "UNQLITE_LOCKERR" } +} + 1; __END__ @@ -57,6 +88,14 @@ Fetch data from database. Delte C< $key > from database. +=item C<< $db->rc(); >> + +Return code from unqlite. It may updates after any Unqlite API call. + +=item C<< $db->errstr() >> + +This API returns stringified version of C<< $db->rc() >>. It's not human readable but it's better than magic number. + =back =head1 LICENSE diff --git a/lib/Unqlite.xs b/lib/Unqlite.xs index 807b243..b0b4b30 100644 --- a/lib/Unqlite.xs +++ b/lib/Unqlite.xs @@ -24,12 +24,48 @@ extern "C" { sv_bless(sv, gv_stashpv(class, 1)); \ SvREADONLY_on(sv); +#define SETRC(rc) \ + { \ + SV * i = get_sv("Unqlite::rc", GV_ADD); \ + 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 PROTOTYPES: DISABLE +BOOT: + HV* stash = gv_stashpvn("Unqlite", strlen("Unqlite"), TRUE); + newCONSTSUB(stash, "UNQLITE_OK", newSViv(UNQLITE_OK)); + newCONSTSUB(stash, "UNQLITE_NOMEM", newSViv(UNQLITE_NOMEM)); + newCONSTSUB(stash, "UNQLITE_ABORT", newSViv(UNQLITE_ABORT)); + newCONSTSUB(stash, "UNQLITE_IOERR", newSViv(UNQLITE_IOERR)); + newCONSTSUB(stash, "UNQLITE_CORRUPT", newSViv(UNQLITE_CORRUPT)); + newCONSTSUB(stash, "UNQLITE_LOCKED", newSViv(UNQLITE_LOCKED)); + newCONSTSUB(stash, "UNQLITE_BUSY", newSViv(UNQLITE_BUSY)); + newCONSTSUB(stash, "UNQLITE_DONE", newSViv(UNQLITE_DONE)); + newCONSTSUB(stash, "UNQLITE_PERM", newSViv(UNQLITE_PERM)); + newCONSTSUB(stash, "UNQLITE_NOTIMPLEMENTED", newSViv(UNQLITE_NOTIMPLEMENTED)); + newCONSTSUB(stash, "UNQLITE_NOTFOUND", newSViv(UNQLITE_NOTFOUND)); + newCONSTSUB(stash, "UNQLITE_NOOP", newSViv(UNQLITE_NOOP)); + newCONSTSUB(stash, "UNQLITE_INVALID", newSViv(UNQLITE_INVALID)); + newCONSTSUB(stash, "UNQLITE_EOF", newSViv(UNQLITE_EOF)); + newCONSTSUB(stash, "UNQLITE_UNKNOWN", newSViv(UNQLITE_UNKNOWN)); + newCONSTSUB(stash, "UNQLITE_LIMIT", newSViv(UNQLITE_LIMIT)); + newCONSTSUB(stash, "UNQLITE_EXISTS", newSViv(UNQLITE_EXISTS)); + newCONSTSUB(stash, "UNQLITE_EMPTY", newSViv(UNQLITE_EMPTY)); + newCONSTSUB(stash, "UNQLITE_COMPILE_ERR", newSViv(UNQLITE_COMPILE_ERR)); + newCONSTSUB(stash, "UNQLITE_VM_ERR", newSViv(UNQLITE_VM_ERR)); + newCONSTSUB(stash, "UNQLITE_FULL", newSViv(UNQLITE_FULL)); + newCONSTSUB(stash, "UNQLITE_CANTOPEN", newSViv(UNQLITE_CANTOPEN)); + newCONSTSUB(stash, "UNQLITE_READ_ONLY", newSViv(UNQLITE_READ_ONLY)); + newCONSTSUB(stash, "UNQLITE_LOCKERR", newSViv(UNQLITE_LOCKERR)); + SV* open(klass, filename, mode=UNQLITE_OPEN_CREATE) const char *klass; @@ -41,6 +77,7 @@ PREINIT: int rc; CODE: rc = unqlite_open(&pdb, filename, mode); + SETRC(rc); if (rc == UNQLITE_OK) { XS_STRUCT2OBJ(sv, klass, pdb); RETVAL = sv; @@ -66,6 +103,7 @@ CODE: key_c = SvPV(key_sv, key_l); data_c = SvPV(data_sv, data_l); rc = unqlite_kv_store(pdb, key_c, key_l, data_c, data_l); + SETRC(rc); if (rc==UNQLITE_OK) { RETVAL = &PL_sv_yes; } else { @@ -90,6 +128,7 @@ CODE: key_c = SvPV(key_sv, key_l); data_c = SvPV(data_sv, data_l); rc = unqlite_kv_append(pdb, key_c, key_l, data_c, data_l); + SETRC(rc); if (rc==UNQLITE_OK) { RETVAL = &PL_sv_yes; } else { @@ -110,6 +149,7 @@ CODE: unqlite *pdb = XS_STATE(unqlite*, self); key_c = SvPV(key_sv, key_l); rc = unqlite_kv_delete(pdb, key_c, key_l); + SETRC(rc); if (rc==UNQLITE_OK) { RETVAL = &PL_sv_yes; } else { @@ -135,12 +175,14 @@ CODE: /* Allocate a buffer big enough to hold the record content */ rc = unqlite_kv_fetch(pdb, key_c, key_l, NULL, &nbytes); + SETRC(rc); if (rc!=UNQLITE_OK) { RETVAL = &PL_sv_undef; goto last; } Newxz(buf, nbytes, char); - unqlite_kv_fetch(pdb, key_c, key_l, buf, &nbytes); + rc = unqlite_kv_fetch(pdb, key_c, key_l, buf, &nbytes); + SETRC(rc); sv = newSVpv(buf, nbytes); Safefree(buf); RETVAL = sv; @@ -151,7 +193,10 @@ OUTPUT: void DESTROY(self) SV * self; +PREINIT: + int rc; CODE: unqlite *pdb = XS_STATE(unqlite*, self); - unqlite_close(pdb); + rc = unqlite_close(pdb); + SETRC(rc); diff --git a/t/01_simple.t b/t/01_simple.t index 4e56e9c..e3c0132 100644 --- a/t/01_simple.t +++ b/t/01_simple.t @@ -6,16 +6,24 @@ use Unqlite; my $tmp = tempdir( CLEANUP => 1 ); -my $db = Unqlite->open("$tmp/foo.db"); -isa_ok($db, 'Unqlite'); +{ + my $db = Unqlite->open("$tmp/foo.db"); + isa_ok($db, 'Unqlite'); -ok($db->kv_store("foo", "bar")); -is($db->kv_fetch('foo'), 'bar'); -ok($db->kv_delete('foo')); -is($db->kv_fetch('foo'), undef); -$db->kv_store('yay', 'yap'); -$db->kv_append('yay', 'po'); -is($db->kv_fetch('yay'), 'yappo'); + ok($db->kv_store("foo", "bar")); + is($db->kv_fetch('foo'), 'bar'); + ok($db->kv_delete('foo')); + is($db->kv_fetch('foo'), undef); + $db->kv_store('yay', 'yap'); + $db->kv_append('yay', 'po'); + is($db->kv_fetch('yay'), 'yappo'); + is($db->rc,0); +} + +my $db = Unqlite->open("/path/to/unexisted/file"); +is($db->kv_fetch('x'), undef); +isnt($db->rc, 0); +note $db->errstr; done_testing;