ODEUM(3)
ODEUM(3) โ Quick Database Manager ๐ bestie, you're in the right place.
โจ NAME โจ
Odeum โ the inverted API of QDBM. no cap. ๐
โจ SYNOPSIS โจ
okay so here's the whole cast of characters, literally every prototype, no skips, no edits:
#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
typedef struct { int id; int score; } ODPAIR;
ODEUM *odopen(const char *name, int omode);
int odclose(ODEUM *odeum);
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
int odout(ODEUM *odeum, const char *uri);
int odoutbyid(ODEUM *odeum, int id);
ODDOC *odget(ODEUM *odeum, const char *uri);
ODDOC *odgetbyid(ODEUM *odeum, int id);
int odgetidbyuri(ODEUM *odeum, const char *uri);
int odcheck(ODEUM *odeum, int id);
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
int odsearchdnum(ODEUM *odeum, const char *word);
int oditerinit(ODEUM *odeum);
ODDOC *oditernext(ODEUM *odeum);
int odsync(ODEUM *odeum);
int odoptimize(ODEUM *odeum);
char *odname(ODEUM *odeum);
double odfsiz(ODEUM *odeum);
int odbnum(ODEUM *odeum);
int odbusenum(ODEUM *odeum);
int oddnum(ODEUM *odeum);
int odwnum(ODEUM *odeum);
int odwritable(ODEUM *odeum);
int odfatalerror(ODEUM *odeum);
int odinode(ODEUM *odeum);
time_t odmtime(ODEUM *odeum);
int odmerge(const char *name, const CBLIST *elemnames);
int odremove(const char *name);
ODDOC *oddocopen(const char *uri);
void oddocclose(ODDOC *doc);
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
int oddocid(const ODDOC *doc);
const char *oddocuri(const ODDOC *doc);
const char *oddocgetattr(const ODDOC *doc, const char *name);
const CBLIST *oddocnwords(const ODDOC *doc);
const CBLIST *oddocawords(const ODDOC *doc);
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
CBLIST *odbreaktext(const char *text);
char *odnormalizeword(const char *asis);
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum,
int *np);
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum,
int *np);
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int
bnum, int *np);
void odpairssort(ODPAIR *pairs, int pnum);
double odlogarithm(double x);
double odvectorcosine(const int *avec, const int *bvec, int vnum);
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords,
CBLIST *nwords);
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char
*delimchars, const char *gluechars);
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST
*errors);
๐ธ DESCRIPTION ๐ธ
okay so Odeum is the API that handles an inverted index. and what even is an inverted index? it's a data structure to retrieve a list of some documents that include one of words which were extracted from a population of documents. it makes realizing a full-text search system easy, fr fr. Odeum provides an abstract data structure which consists of words and attributes of a document. it's used when an application stores a document into a database and when an application retrieves some documents from a database. ๐
Odeum does not provide methods to extract the text from the original data of a document. that part? it should be implemented by applications, bestie. although Odeum provides utilities to extract words from a text, it is oriented to such languages whose words are separated with space characters as English. if an application handles such languages which need morphological analysis or N-gram analysis as Japanese, or if an application perform more such rarefied analysis of natural languages as stemming, its own analyzing method can be adopted. result of search is expressed as an array contains elements which are structures composed of the ID number of documents and its score. in order to search with two or more words, Odeum provides utilities of set operations. periodt. ๐
Odeum is implemented, based on Curia, Cabin, and Villa. Odeum creates a database with a directory name. some databases of Curia and Villa are placed in the specified directory. for example, casket/docs, casket/index, and casket/rdocs are created in the case that a database directory named as casket. let's break it down:
docsis a database directory of Curia. the key of each record is the ID number of a document, and the value is such attributes as URI.indexis a database directory of Curia. the key of each record is the normalized form of a word, and the value is an array whose element is a pair of the ID number of a document including the word and its score.rdocsis a database file of Villa. the key of each record is the URI of a document, and the value is its ID number.
in order to use Odeum, you should include depot.h, cabin.h, odeum.h and stdlib.h in the source files. usually, the following description will be near the beginning of a source file.
#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
a pointer to ODEUM is used as a database handle. a database handle is opened with the function odopen and closed with odclose. you should not refer directly to any member of the handle. if a fatal error occurs in a database, any access method via the handle except odclose will not work and return error status. although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. ๐ซ
a pointer to ODDOC is used as a document handle. a document handle is opened with the function oddocopen and closed with oddocclose. you should not refer directly to any member of the handle. a document consists of attributes and words. each word is expressed as a pair of a normalized form and a appearance form.
Odeum also assign the external variable dpecode with the error code. the function dperrmsg is used in order to get the message of the error code.
structures of ODPAIR type is used in order to handle results of search.
typedef struct { int id; int score; } ODPAIR;
idspecifies the ID number of a document.scorespecifies the score calculated from the number of searching words in the document.
odopen โ get a database handle
ODEUM *odopen(const char *name, int omode);
name specifies the name of a database directory. omode specifies the connection mode: OD_OWRITER as a writer, OD_OREADER as a reader. if the mode is OD_OWRITER, the following may be added by bitwise or: OD_OCREAT, which means it creates a new database if not exist, OD_OTRUNC, which means it creates a new database regardless if one exists. both of OD_OREADER and OD_OWRITER can be added to by bitwise or: OD_ONOLCK, which means it opens a database directory without file locking, or OD_OLCKNB, which means locking is performed without blocking. the return value is the database handle or NULL if it is not successful. while connecting as a writer, an exclusive lock is invoked to the database directory. while connecting as a reader, a shared lock is invoked to the database directory. the thread blocks until the lock is achieved. if OD_ONOLCK is used, the application is responsible for exclusion control.
โ ๏ธ bestie, if OD_ONOLCK is used, the application is responsible for exclusion control. that's on you, not on Odeum.
odclose โ close a database handle
int odclose(ODEUM *odeum);
odeum specifies a database handle. if successful, the return value is true, else, it is false. because the region of a closed handle is released, it becomes impossible to use the handle. updating a database is assured to be written when the handle is closed.
๐ญ if a writer opens a database but does not close it appropriately, the database will be broken. periodt. don't do that.
odput โ store a document
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
odeum specifies a database handle connected as a writer. doc specifies a document handle. wmax specifies the max number of words to be stored in the document database. if it is negative, the number is unlimited. over specifies whether the data of the duplicated document is overwritten or not. if it is false and the URI of the document is duplicated, the function returns as an error. if successful, the return value is true, else, it is false.
odout โ delete a document specified by a URI
int odout(ODEUM *odeum, const char *uri);
odeum specifies a database handle connected as a writer. uri specifies the string of the URI of a document. if successful, the return value is true, else, it is false. false is returned when no document corresponds to the specified URI.
odoutbyid โ delete a document specified by an ID number
int odoutbyid(ODEUM *odeum, int id);
odeum specifies a database handle connected as a writer. id specifies the ID number of a document. if successful, the return value is true, else, it is false. false is returned when no document corresponds to the specified ID number.
odget โ retrieve a document specified by a URI
ODDOC *odget(ODEUM *odeum, const char *uri);
odeum specifies a database handle. uri specifies the string of the URI of a document. if successful, the return value is the handle of the corresponding document, else, it is NULL. NULL is returned when no document corresponds to the specified URI. because the handle of the return value is opened with the function oddocopen, it should be closed with the function oddocclose.
odgetbyid โ retrieve a document by an ID number
ODDOC *odgetbyid(ODEUM *odeum, int id);
odeum specifies a database handle. id specifies the ID number of a document. if successful, the return value is the handle of the corresponding document, else, it is NULL. NULL is returned when no document corresponds to the specified ID number. because the handle of the return value is opened with the function oddocopen, it should be closed with the function oddocclose.
the function odgetidbyuri is used in order to retrieve the ID of the document specified by a URI.
int odgetidbyuri(ODEUM *odeum, const char *uri);
odeum is your database handle, bestie. uri is the string of the URI of a document. If it slays, you get the ID number of the document back. If not, you get -1. And -1 specifically means no document matches that URI. Periodt. ๐
int odcheck(ODEUM *odeum, int id);
The function odcheck is used to check whether the document specified by an ID number exists. odeum is your database handle. id is the ID number of a document. Return value is true if the document exists, else false. So like, a vibe check for documents. โจ
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
The function odsearch is used to search the inverted index for documents including a particular word. odeum is your database handle. word is the searching word. max is the max number of documents to be retrieve. np is the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else itโs NULL. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. So like, ghost data? ๐ป Keep that in mind.
int odsearchdnum(ODEUM *odeum, const char *word);
The function odsearchnum is used to get the number of documents including a word. (And yes, the prototype says odsearchdnum โ iconic typo energy, we keep it fr fr.) odeum is your database handle. word is the searching word. If successful, return value is the number of documents including the word, else -1. Because this function does not read the entity of the inverted index, it is faster than odsearch. Itโs giving speedrun mode. ๐โโ๏ธ๐จ
int oditerinit(ODEUM *odeum);
The function oditerinit is used to initialize the iterator of a database handle. odeum is your database handle. If successful, return value is true, else false. The iterator is used to access every document stored in a database. Set up your little tour bus, bestie. ๐โจ
ODDOC *oditernext(ODEUM *odeum);
The function oditernext is used to get the next key of the iterator. odeum is your database handle. If successful, return value is the handle of the next document, else NULL. NULL is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function oddocopen, it should be closed with the function oddocclose. So like, close your tabs when youโre done. ๐
int odsync(ODEUM *odeum);
The function odsync is used to synchronize updating contents with the files and the devices. odeum is your database handle connected as a writer. If successful, return value is true, else false. This function is useful when another process uses the connected database directory. Sync it up, periodt. โจ
int odoptimize(ODEUM *odeum);
The function odoptimize is used to optimize a database. odeum is your database handle connected as a writer. If successful, return value is true, else false. Elements of the deleted documents in the inverted index are purged. Clean up those ghosts. ๐ป๐งน
char *odname(ODEUM *odeum);
The function odname is used to get the name of a database. odeum is your database handle. If successful, return value is the pointer to the region of the name of the database, else NULL. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. Free it, bestie. ๐ซถ
double odfsiz(ODEUM *odeum);
The function odfsiz is used to get the total size of database files. odeum is your database handle. If successful, return value is the total size of the database files, else -1.0. Size check ๐
int odbnum(ODEUM *odeum);
The function odbnum is used to get the total number of the elements of the bucket arrays in the inverted index. odeum is your database handle. If successful, return value is the total number of the elements of the bucket arrays, else -1.
int odbusenum(ODEUM *odeum);
The function odbusenum is used to get the total number of the used elements of the bucket arrays in the inverted index. odeum is your database handle. If successful, return value is the total number of the used elements of the bucket arrays, else -1.
int oddnum(ODEUM *odeum);
The function oddnum is used to get the number of the documents stored in a database. odeum is your database handle. If successful, return value is the number of the documents stored in the database, else -1.
int odwnum(ODEUM *odeum);
The function odwnum is used to get the number of the words stored in a database. odeum is your database handle. If successful, return value is the number of the words stored in the database, else -1. Because of the I/O buffer, the return value may be less than the hard number. So like, itโs an estimate, not exact. Iykyk. ๐คทโโ๏ธ
int odwritable(ODEUM *odeum);
The function odwritable is used to check whether a database handle is a writer or not. odeum is your database handle. Return value is true if the handle is a writer, false if not. Are you the main character writer? ๐โโ๏ธ
int odfatalerror(ODEUM *odeum);
The function odfatalerror is used to check whether a database has a fatal error or not. odeum is your database handle. Return value is true if the database has a fatal error, false if not. Yikes, check for drama. ๐
int odinode(ODEUM *odeum);
The function odinode is used to get the inode number of a database directory. odeum is your database handle. Return value is the inode number of the database directory.
time_t odmtime(ODEUM *odeum);
The function odmtime is used to get the last modified time of a database. odeum is your database handle. Return value is the last modified time of the database. When was the last glow up? โจ
int odmerge(const char *name, const CBLIST *elemnames);
The function odmerge is used to merge plural database directories. name specifies the name of a database directory to create. elemnames specifies a list of names of element databases. If successful, return value is true, else false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored. First come, first served, bestie. ๐
int odremove(const char *name);
The function odremove is used to remove a database directory. name specifies the name of a database directory. If successful, return value is true, else false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function. Itโs giving delete button. ๐๏ธ
ODDOC *oddocopen(const char *uri);
The function oddocopen is used to get a document handle. uri specifies the URI of a document. Return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database. So like, you get a temp handle, the real ID comes later. โณ
void oddocclose(ODDOC *doc);
The function oddocclose is used to close a document handle. doc specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle. Close it and say bye. ๐
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
The function oddocaddattr is used to add an attribute to a document. doc specifies a document handle. name specifies the string of the name of an attribute. value specifies the string of the value of the attribute. Add some flair. โจ
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
The function oddocaddword is used to add a word to a document. doc specifies a document handle. normal specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. asis specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application. So normal = search key, asis = how it actually looks. Two moods, same word. ๐
int oddocid(const ODDOC *doc);
The function oddocid is used to get the ID number of a document. doc specifies a document handle. Return value is the ID number of a document. Get that ID, bestie. ๐ชช
const char *oddocuri(const ODDOC *doc);
The function oddocuri is used to get the URI of a document. doc specifies a document handle. Return value is the string of the URI of a document. The link, the source, the vibe. โจ
const char *oddocgetattr(const ODDOC *doc, const char *name);
The function oddocgetattr is used to get the value of an attribute of a document. doc specifies a document handle. name specifies the string of the name of an attribute. Return value is the string of the value of the attribute, or NULL if no attribute corresponds. If itโs not there, you get NULL, no cap. ๐ซ
const CBLIST *oddocnwords(const ODDOC *doc);
The function oddocnwords is used to get the list handle contains words in normalized form of a document. doc specifies a document handle. Return value is the list handle contains words in normalized form. The normalized word list, periodt. ๐
const CBLIST *oddocawords(const ODDOC *doc);
The function oddocawords is used to get the list handle contains words in appearance form of a document. doc specifies a document handle. Return value is the list handle contains words in appearance form. The appearance word list, slay. ๐
๐ oddocscores
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
Okay so bestie, this function is giving you a map handle that has keywords in normalized form plus their scores. ๐บ๏ธโจ
docโ specifies a document handle.maxโ specifies the max number of keywords to get.odeumโ specifies a database handle with which the IDF for weighting is calculate. If it isNULL, it is not used.
The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function cbmapopen, it should be closed with the function cbmapclose if it is no longer in use. ๐
โจ odbreaktext
CBLIST *odbreaktext(const char *text);
This one breaks a text into words in appearance form. ๐ช
textโ specifies the string of a text.
The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function cblistopen, it should be closed with the function cblistclose if it is no longer in use. ๐
๐ฆ odnormalizeword
char *odnormalizeword(const char *asis);
Makes the normalized form of a word. ๐ง
asisโ specifies the string of the appearance form of a word.
The return value is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. ๐ซถ
๐ odpairsand
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
Gets the common elements of two sets of documents. It's giving intersection energy. ๐ฅ
apairsโ specifies the pointer to the former document array.anumโ specifies the number of the elements of the former document array.bpairsโ specifies the pointer to the latter document array.bnumโ specifies the number of the elements of the latter document array.npโ specifies the pointer to a variable to which the number of the elements of the return value is assigned.
The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. ๐
๐ odpairsor
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
Gets the sum of elements of two sets of documents. Union vibes. ๐ซ
apairsโ specifies the pointer to the former document array.anumโ specifies the number of the elements of the former document array.bpairsโ specifies the pointer to the latter document array.bnumโ specifies the number of the elements of the latter document array.npโ specifies the pointer to a variable to which the number of the elements of the return value is assigned.
The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. โจ
๐ odpairsnotand
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
Gets the difference set of documents. Former minus latter, no cap. ๐ โโ๏ธ
apairsโ specifies the pointer to the former document array.anumโ specifies the number of the elements of the former document array.bpairsโ specifies the pointer to the latter document array of the sum of elements.bnumโ specifies the number of the elements of the latter document array.npโ specifies the pointer to a variable to which the number of the elements of the return value is assigned.
The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. ๐ญ
๐ odpairssort
void odpairssort(ODPAIR *pairs, int pnum);
Sorts a set of documents in descending order of scores. Bestie said sort by score, so we sort by score. ๐
pairsโ specifies the pointer to a document array.pnumโ specifies the number of the elements of the document array.
๐ธ odlogarithm
double odlogarithm(double x);
Gets the natural logarithm of a number. Math but make it cute. ๐งฎ
xโ specifies a number.
The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results. ๐ข
๐ odvectorcosine
double odvectorcosine(const int *avec, const int *bvec, int vnum);
Gets the cosine of the angle of two vectors. Similarity queen. ๐ฏโโ๏ธ
avecโ specifies the pointer to one array of numbers.bvecโ specifies the pointer to the other array of numbers.vnumโ specifies the number of elements of each array.
The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents. ๐ฏ
๐ odsettuning
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
Sets the global tuning parameters. Tweak the vibe. โ๏ธ
ibnumโ specifies the number of buckets for inverted indexes.idnumโ specifies the division number of inverted index.cbnumโ specifies the number of buckets for dirty buffers.csizโ specifies the maximum bytes to use memory for dirty buffers.
The default setting is equivalent to odsettuning(32749, 7, 262139, 8388608). This function should be called before opening a handle. โ ๏ธ
๐ง odanalyzetext
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
Breaks a text into words and stores appearance forms and normalized form into lists. Two lists, one text, iconic. ๐
odeumโ specifies a database handle.textโ specifies the string of a text.awordsโ specifies a list handle into which appearance form is store.nwordsโ specifies a list handle into which normalized form is store. If it isNULL, it is ignored.
Words are separated with space characters and such delimiters as period, comma and so on. ๐ซถ
๐ฆ odsetcharclass
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
Sets the classes of characters used by odanalyzetext. Character class tea. โ
odeumโ specifies a database handle.spacecharsโ specifies a string contains space characters.delimcharsโ specifies a string contains delimiter characters.gluecharsโ specifies a string contains glue characters.
๐ฅ odquery
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
Queries a database using a small boolean query language. Search era. ๐
odeumโ specifies a database handle.queryโ specifies the text of the query.npโ specifies the pointer to a variable to which the number of the elements of the return value is assigned.errorsโ specifies a list handle into which error messages are stored. If it isNULL, it is ignored.
If successful, the return value is the pointer to an array, else, it is NULL. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the malloc call, it should be released with the free call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. ๐ณ
If QDBM was built with POSIX thread enabled, the global variable dpecode is treated as thread specific data, and functions of Odeum are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that errno, malloc, and so on are thread-safe. ๐งต
If QDBM was built with ZLIB enabled, records in the database for document attributes are compressed. In that case, the size of the database is reduced to 30% or less. Thus, you should enable ZLIB if you use Odeum. A database of Odeum created without ZLIB enabled is not available on environment with ZLIB enabled, and vice versa. If ZLIB was not enabled but LZO, LZO is used instead. ๐๏ธ
The query language of the function odquery is a basic language following this grammar:
expr ::= subexpr ( op subexpr )*
subexpr ::= WORD
subexpr ::= LPAREN expr RPAREN
Operators are "&" (AND), "|" (OR), and "!" (NOTAND). You can use parenthesis to group sub-expressions together in order to change order of operations. The given query is broken up using the function odanalyzetext, so if you want to specify different text breaking rules, then make sure that you at least set "&", "|", "!", "(", and ")" to be delimiter characters. Consecutive words are treated as having an implicit "&" operator between them, so "zed shaw" is actually "zed & shaw". ๐ค
The encoding of the query text should be the same with the encoding of target documents. Moreover, each of space characters, delimiter characters, and glue characters should be single byte. ๐ค
๐ SEE ALSO
That's the tea, bestie! This page is from the Man Page source, version ODEUM(3), dated 2004-04-22. Stay iconic. ๐โจ
๐ฆ where this page comes from
- debian bookworm: libqdbm-dev 1.8.78-12+b1 ยท LGPL-2.1-or-later
- debian trixie: libqdbm-dev 1.8.78-13+b3 ยท LGPL-2.1-or-later
- fedora 43: qdbm-devel 1.8.78-71.fc43 ยท LGPL-2.1-or-later
- fedora 43: qdbm-devel 1.8.78-71.fc43 ยท LGPL-2.1-or-later
- fedora 44: qdbm-devel 1.8.78-75.fc44 ยท LGPL-2.1-or-later
- fedora 44: qdbm-devel 1.8.78-75.fc44 ยท LGPL-2.1-or-later
- ubuntu jammy: libqdbm-dev 1.8.78-11build3 ยท LGPL-2.1-or-later
- ubuntu noble: libqdbm-dev 1.8.78-12.1build2 ยท LGPL-2.1-or-later
- ubuntu questing: libqdbm-dev 1.8.78-13build2
- ubuntu resolute: libqdbm-dev 1.8.78-15 ยท LGPL-2.1-or-later
- ubuntu stonking: libqdbm-dev 1.8.78-16build1 ยท LGPL-2.1-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms