{"id":22045227,"url":"https://github.com/nigelhorne/database-abstraction","last_synced_at":"2025-05-08T07:46:49.184Z","repository":{"id":219772944,"uuid":"749870029","full_name":"nigelhorne/Database-Abstraction","owner":"nigelhorne","description":"Read-only database abstraction layer (ORM)","archived":false,"fork":false,"pushed_at":"2025-04-15T20:43:13.000Z","size":180,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-03T05:08:54.711Z","etag":null,"topics":["caching","cpan","cpan-module","csv","database","dbi","orm","orm-library","perl","perl5","sqlite","xml"],"latest_commit_sha":null,"homepage":"https://metacpan.org/pod/Database::Abstraction","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nigelhorne.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github [ nigelhorne ]":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://www.paypal.com/paypalme/bandsman"]}},"created_at":"2024-01-29T15:05:18.000Z","updated_at":"2025-04-15T20:43:17.000Z","dependencies_parsed_at":"2024-04-25T20:28:59.448Z","dependency_job_id":"f0219aff-e816-4193-8371-2e015f38f42c","html_url":"https://github.com/nigelhorne/Database-Abstraction","commit_stats":null,"previous_names":["nigelhorne/database-abstraction"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nigelhorne%2FDatabase-Abstraction","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nigelhorne%2FDatabase-Abstraction/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nigelhorne%2FDatabase-Abstraction/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nigelhorne%2FDatabase-Abstraction/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nigelhorne","download_url":"https://codeload.github.com/nigelhorne/Database-Abstraction/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253025334,"owners_count":21842409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caching","cpan","cpan-module","csv","database","dbi","orm","orm-library","perl","perl5","sqlite","xml"],"created_at":"2024-11-30T13:12:20.613Z","updated_at":"2025-05-08T07:46:49.176Z","avatar_url":"https://github.com/nigelhorne.png","language":"Perl","funding_links":["https://www.paypal.com/paypalme/bandsman"],"categories":[],"sub_categories":[],"readme":"Database-Abstraction\n====================\n\n[![Appveyor Status](https://ci.appveyor.com/api/projects/status/1t1yhvagx00c2qi8?svg=true)](https://ci.appveyor.com/project/nigelhorne/database-abstraction)\n[![CircleCI](https://dl.circleci.com/status-badge/img/circleci/8CE7w65gte4YmSREC2GBgW/THucjGauwLPtHu1MMAueHj/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/circleci/8CE7w65gte4YmSREC2GBgW/THucjGauwLPtHu1MMAueHj/tree/main)\n[![Coveralls Status](https://coveralls.io/repos/github/nigelhorne/Database-Abstraction/badge.svg?branch=master)](https://coveralls.io/github/nigelhorne/Database-Abstraction?branch=master)\n[![CPAN](https://img.shields.io/cpan/v/Database-Abstraction.svg)](http://search.cpan.org/~nhorne/Database-Abstraction/)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/nigelhorne/ntpdate/ntpdate.yml?branch=master)\n![Perl Version](https://img.shields.io/badge/perl-5.8+-blue)\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://x.com/intent/tweet?text=Information+about+the+Database+Environment+#perl+#ORM\u0026url=https://github.com/nigelhorne/database-abstraction\u0026via=nigelhorne)\n\n# NAME\n\nDatabase::Abstraction - Read-only Database Abstraction Layer (ORM)\n\n# VERSION\n\nVersion 0.26\n\n# DESCRIPTION\n\n`Database::Abstraction` is a read-only database abstraction layer (ORM) for Perl,\ndesigned to provide a simple interface for accessing and querying various types of databases such as CSV, XML, and SQLite without the need to write SQL queries.\nIt promotes code maintainability by abstracting database access logic into a single interface,\nallowing users to switch between different storage formats seamlessly.\nThe module supports caching for performance optimization,\nflexible logging for debugging and monitoring,\nand includes features like the AUTOLOAD method for convenient access to database columns.\nBy handling numerous database and file formats,\n`Database::Abstraction` adds versatility and simplifies the management of read-intensive applications.\n\n# SYNOPSIS\n\nAbstract class giving read-only access to CSV,\nXML,\nBerkeleyDB and SQLite databases via Perl without writing any SQL,\nusing caching for performance optimization.\n\nThe module promotes code maintainability by abstracting database access logic into a single interface.\nUsers can switch between different storage formats without changing application logic.\nThe ability to handle numerous database and file formats adds versatility and makes it useful for a variety of applications.\n\nIt's a simple ORM like interface which,\nfor all of its simplicity,\nallows you to do a lot of the heavy lifting of simple database operations without any SQL.\nIt offers functionalities like opening the database and fetching data based on various criteria.\n\nBuilt-in support for flexible and configurable caching improves performance for read-intensive applications.\n\nSupports logging to debug and monitor database operations.\n\nLook for databases in $directory in this order:\n\n- 1 `SQLite`\n\n    File ends with .sql\n\n- 2 `PSV`\n\n    Pipe separated file, file ends with .psv\n\n- 3 `CSV`\n\n    File ends with .csv or .db, can be gzipped. Note the default sep\\_char is '!' not ','\n\n- 4 `XML`\n\n    File ends with .xml\n\n- 5 `BerkeleyDB`\n\n    File ends with .db\n\nThe AUTOLOAD feature allows for convenient access to database columns using method calls.\nIt hides the complexity of querying the underlying data storage.\n\nIf the table has a key column,\nentries are keyed on that and sorts are based on it.\nTo turn that off, pass 'no\\_entry' to the constructor, for legacy\nreasons it's enabled by default.\nThe key column's default name is 'entry', but it can be overridden by the 'id' parameter.\n\nArrays are made read-only before being returned.\nTo disable that, pass `no_fixate` to the constructor.\n\nCSV files that are not no\\_entry can have empty lines or comment lines starting with '#',\nto make them more readable.\n\n# EXAMPLE\n\nIf the file /var/dat/foo.csv contains something like:\n\n    \"customer_id\",\"name\"\n    \"plugh\",\"John\"\n    \"xyzzy\",\"Jane\"\n\nCreate a driver for the file in .../Database/foo.pm:\n\n    package Database::foo;\n\n    use Database::Abstraction;\n\n    our @ISA = ('Database::Abstraction');\n\n    # Regular CSV: There is no entry column and the separators are commas\n    sub new\n    {\n        my $class = shift;\n        my %args = (ref($_[0]) eq 'HASH') ? %{$_[0]} : @_;\n\n        return $class-\u003eSUPER::new(no_entry =\u003e 1, sep_char =\u003e ',', %args);\n    }\n\nYou can then use this code to access the data via the driver:\n\n    # Opens the file, e.g. /var/dat/foo.csv\n    my $foo = Database::foo-\u003enew(directory =\u003e '/var/dat');\n\n    # Prints \"John\"\n    print 'Customer name ', $foo-\u003ename(customer_id =\u003e 'plugh'), \"\\n\";\n\n    # Prints:\n    #  $VAR1 = {\n    #     'customer_id' =\u003e 'xyzzy',\n    #     'name' =\u003e 'Jane'\n    #  };\n    my $row = $foo-\u003efetchrow_hashref(customer_id =\u003e 'xyzzy');\n    print Data::Dumper-\u003enew([$row])-\u003eDump();\n\n# SUBROUTINES/METHODS\n\n## init\n\nInitializes the abstraction class and its subclasses with optional arguments for configuration.\n\n    Database::Abstraction::init(directory =\u003e '../data');\n\nSee the documentation for new to see what variables can be set.\n\nReturns a reference to a hash of the current values.\nTherefore when given with no arguments you can get the current default values:\n\n    my $defaults = Database::Abstraction::init();\n    print $defaults-\u003e{'directory'}, \"\\n\";\n\n## new\n\nCreate an object to point to a read-only database.\n\nArguments:\n\nTakes different argument formats (hash or positional)\n\n- `auto_load`\n\n    Enable/disable the AUTOLOAD feature.\n    The default is to have it enabled.\n\n- `cache`\n\n    Place to store results\n\n- `cache_duration`\n\n    How long to store results in the cache (default is 1 hour).\n\n- `config_file`\n\n    Points to a configuration file which contains the parameters to `new()`.\n    The file can be in any common format including `YAML`, `XML`, and `INI`.\n    This allows the parameters to be set at run time.\n\n- `expires_in`\n\n    Synonym of `cache_duration`, for compatibility with `CHI`.\n\n- `dbname`\n\n    The prefix of name of the database file (default is name of the table).\n    The database will be held in a file such as $dbname.csv.\n\n- `directory`\n\n    Where the database file is held.\n    If only one argument is given to `new()`, it is taken to be `directory`.\n\n- `filename`\n\n    Filename containing the data.\n    When not given,\n    the filename is derived from the tablename\n    which in turn comes from the class name.\n\n- `logger`\n\n    Takes an optional parameter logger, which is used for warnings and traces.\n    Can be an object that understands warn() and trace() messages,\n    such as a [Log::Log4perl](https://metacpan.org/pod/Log%3A%3ALog4perl) or [Log::Any](https://metacpan.org/pod/Log%3A%3AAny) object,\n    a reference to code,\n    or a filename.\n\n- `max_slurp_size`\n\n    CSV/PSV/XML files smaller than this are held in a HASH in RAM (default is 16K),\n    falling back to SQL on larger data sets.\n    Setting this value to 0 will turn this feature off,\n    thus forcing SQL to be used to access the database\n\nIf the arguments are not set, tries to take from class level defaults.\n\nChecks for abstract class usage.\n\nSlurp mode assumes that the key column (entry) is unique.\nIf it isn't, searches will be incomplete.\nTurn off slurp mode on those databases,\nby setting a low value for max\\_slurp\\_size.\n\nClones existing objects with or without modifications.\nUses Carp::carp to log warnings for incorrect usage or potential mistakes.\n\n## set\\_logger\n\nSets the class, code reference, or file that will be used for logging.\n\n## selectall\\_hashref\n\nReturns a reference to an array of hash references of all the data meeting\nthe given criteria.\n\nNote that since this returns an array ref,\noptimisations such as \"LIMIT 1\" will not be used.\n\nUse caching if that is available.\n\n## selectall\\_hash\n\nSimilar to selectall\\_hashref but returns an array of hash references.\n\n## fetchrow\\_hashref\n\nReturns a hash reference for a single row in a table.\n\nSpecial argument: table: determines the table to read from if not the default,\nwhich is worked out from the class name\n\nWhen no\\_entry is not set allow just one argument to be given: the entry value.\n\n## execute\n\nExecute the given SQL query on the database.\nIn an array context, returns an array of hash refs,\nin a scalar context returns a hash of the first row\n\nOn CSV tables without no\\_entry, it may help to add\n\"WHERE entry IS NOT NULL AND entry NOT LIKE '#%'\"\nto the query.\n\nIf the data have been slurped,\nthis will still work by accessing that actual database.\n\n## updated\n\nReturns the timestamp of the last database update.\n\n## AUTOLOAD\n\nDirectly access a database column.\n\nReturns all entries in a column, a single entry based on criteria.\nUses cached data if available.\n\nReturns an array of the matches,\nor only the first when called in scalar context\n\nIf the database has a column called \"entry\" you can do a quick lookup with\n\n    my $value = $foo-\u003ecolumn('123');    # where \"column\" is the value you're after\n\n    my @entries = $foo-\u003eentry();\n    print 'There are ', scalar(@entries), \" entries in the database\\n\";\n\nSet distinct or unique to 1 if you're after a unique list.\n\nThrows an error in slurp mode when an invalid column name is given.\n\n# AUTHOR\n\nNigel Horne, `\u003cnjh at nigelhorne.com\u003e`\n\n# BUGS\n\nThe default delimiter for CSV files is set to '!', not ',' for historical reasons.\nI really ought to fix that.\n\nIt would be nice for the key column to be called key, not entry,\nhowever key's a reserved word in SQL.\n\nThe no\\_entry parameter should be no\\_id.\n\nXML slurping is hard,\nso if XML fails for you on a small file force non-slurping mode with\n\n    $foo = MyPackageName::Database::Foo-\u003enew({\n        directory =\u003e '/var/dat',\n        max_slurp_size =\u003e 0     # force to not use slurp and therefore to use SQL\n    });\n\n# LICENSE AND COPYRIGHT\n\nCopyright 2015-2025 Nigel Horne.\n\nThis program is released under the following licence: GPL2.\nUsage is subject to licence terms.\nThe licence terms of this software are as follows:\nPersonal single user, single computer use: GPL2\nAll other users (for example Commercial, Charity, Educational, Government)\nmust apply in writing for a licence for use from Nigel Horne at the\nabove e-mail.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnigelhorne%2Fdatabase-abstraction","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnigelhorne%2Fdatabase-abstraction","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnigelhorne%2Fdatabase-abstraction/lists"}